PK, Sebastian Heuer , Sebastian Bergmann * * 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; /** @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(); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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') ); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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() ); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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() ); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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'); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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') ); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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'); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; class ManifestDocument { public const XMLNS = 'https://phar.io/xml/manifest/1.0'; /** @var DOMDocument */ private $dom; public static function fromFile(string $filename): ManifestDocument { if (!\file_exists($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(); $dom = new DOMDocument(); $dom->loadXML($xmlString); $errors = \libxml_get_errors(); \libxml_use_internal_errors($prev); 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * 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') ); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; 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; } } } PK, Sebastian Heuer , Sebastian Bergmann * * 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'); } } PK_>>&src/xml/ComponentElementCollection.phpnu[, Sebastian Heuer , Sebastian Bergmann * * 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() ); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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') ); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; 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 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * 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'); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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'); } } PK, Sebastian Heuer , Sebastian Bergmann * * 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') ); } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; class InvalidApplicationNameException extends \InvalidArgumentException implements Exception { public const InvalidFormat = 2; } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; class InvalidEmailException extends \InvalidArgumentException implements Exception { } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; class ElementCollectionException extends \InvalidArgumentException implements Exception { } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; use LibXMLError; 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; class InvalidUrlException extends \InvalidArgumentException implements Exception { } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; interface Exception extends \Throwable { } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; class Url { /** @var string */ private $url; public function __construct(string $url) { $this->ensureUrlIsValid($url); $this->url = $url; } public function asString(): string { return $this->url; } /** * @param string $url * * @throws InvalidUrlException */ private function ensureUrlIsValid($url): void { if (\filter_var($url, \FILTER_VALIDATE_URL) === false) { throw new InvalidUrlException; } } } PK>#src/values/CopyrightInformation.phpnu[, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; interface Requirement { } PK, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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++; } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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++; } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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); } } PKsrc/values/License.phpnu[, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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); } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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; } } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * 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); } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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++; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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); } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; class Author { /** @var string */ private $name; /** @var Email */ private $email; public function __construct(string $name, Email $email) { $this->name = $name; $this->email = $email; } public function asString(): string { return \sprintf( '%s <%s>', $this->name, $this->email->asString() ); } public function getName(): string { return $this->name; } public function getEmail(): Email { return $this->email; } } PK, Sebastian Heuer , Sebastian Bergmann * * 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); } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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 ); } } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; } } PK, Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Manifest; 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 ); } } } PK, Sebastian Heuer , Sebastian Bergmann * * 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; 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 (VersionException $e) { throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e); } catch (Exception $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(), new Email($authorElement->getEmail()) ) ); } $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 ); } } } PKserializeToString($manifest); ``` PK, Sebastian Heuer , Sebastian Bergmann , 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 Arne Blankerts nor the names of 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 HOLDER OR 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. PK_>>&Hsrc/xml/ComponentElementCollection.phpnu[PK>#xusrc/values/CopyrightInformation.phpnu[PKysrc/values/License.phpnu[PK