ManifestDocument.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <?php declare(strict_types = 1);
  2. /*
  3. * This file is part of PharIo\Manifest.
  4. *
  5. * Copyright (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de> and contributors
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. *
  10. */
  11. namespace PharIo\Manifest;
  12. use DOMDocument;
  13. use DOMElement;
  14. use Throwable;
  15. use function count;
  16. use function file_get_contents;
  17. use function is_file;
  18. use function libxml_clear_errors;
  19. use function libxml_get_errors;
  20. use function libxml_use_internal_errors;
  21. use function sprintf;
  22. class ManifestDocument {
  23. public const XMLNS = 'https://phar.io/xml/manifest/1.0';
  24. /** @var DOMDocument */
  25. private $dom;
  26. public static function fromFile(string $filename): ManifestDocument {
  27. if (!is_file($filename)) {
  28. throw new ManifestDocumentException(
  29. sprintf('File "%s" not found', $filename)
  30. );
  31. }
  32. return self::fromString(
  33. file_get_contents($filename)
  34. );
  35. }
  36. public static function fromString(string $xmlString): ManifestDocument {
  37. $prev = libxml_use_internal_errors(true);
  38. libxml_clear_errors();
  39. try {
  40. $dom = new DOMDocument();
  41. $dom->loadXML($xmlString);
  42. $errors = libxml_get_errors();
  43. libxml_use_internal_errors($prev);
  44. } catch (Throwable $t) {
  45. throw new ManifestDocumentException($t->getMessage(), 0, $t);
  46. }
  47. if (count($errors) !== 0) {
  48. throw new ManifestDocumentLoadingException($errors);
  49. }
  50. return new self($dom);
  51. }
  52. private function __construct(DOMDocument $dom) {
  53. $this->ensureCorrectDocumentType($dom);
  54. $this->dom = $dom;
  55. }
  56. public function getContainsElement(): ContainsElement {
  57. return new ContainsElement(
  58. $this->fetchElementByName('contains')
  59. );
  60. }
  61. public function getCopyrightElement(): CopyrightElement {
  62. return new CopyrightElement(
  63. $this->fetchElementByName('copyright')
  64. );
  65. }
  66. public function getRequiresElement(): RequiresElement {
  67. return new RequiresElement(
  68. $this->fetchElementByName('requires')
  69. );
  70. }
  71. public function hasBundlesElement(): bool {
  72. return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1;
  73. }
  74. public function getBundlesElement(): BundlesElement {
  75. return new BundlesElement(
  76. $this->fetchElementByName('bundles')
  77. );
  78. }
  79. private function ensureCorrectDocumentType(DOMDocument $dom): void {
  80. $root = $dom->documentElement;
  81. if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) {
  82. throw new ManifestDocumentException('Not a phar.io manifest document');
  83. }
  84. }
  85. private function fetchElementByName(string $elementName): DOMElement {
  86. $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);
  87. if (!$element instanceof DOMElement) {
  88. throw new ManifestDocumentException(
  89. sprintf('Element %s missing', $elementName)
  90. );
  91. }
  92. return $element;
  93. }
  94. }