aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/mikespub/php-epub-meta/src/Data
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/mikespub/php-epub-meta/src/Data')
-rw-r--r--vendor/mikespub/php-epub-meta/src/Data/Item.php193
-rw-r--r--vendor/mikespub/php-epub-meta/src/Data/Manifest.php174
2 files changed, 367 insertions, 0 deletions
diff --git a/vendor/mikespub/php-epub-meta/src/Data/Item.php b/vendor/mikespub/php-epub-meta/src/Data/Item.php
new file mode 100644
index 000000000..271462920
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Data/Item.php
@@ -0,0 +1,193 @@
+<?php
+
+namespace SebLucas\EPubMeta\Data;
+
+use SebLucas\EPubMeta\Tools\HtmlTools;
+use DOMDocument;
+use DOMElement;
+use DOMText;
+use DOMXPath;
+use Exception;
+
+/**
+ * An item of the EPUB manifest.
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ */
+class Item
+{
+ public const XHTML = 'application/xhtml+xml';
+ /** @var string */
+ protected $id;
+ /** @var string The path to the corresponding file. */
+ protected $href;
+ /** @var string */
+ protected $mediaType;
+ /** @var callable|null A callable to get data from the referenced file. */
+ protected $dataCallable;
+ /** @var string The data read from the referenced file. */
+ protected $data;
+ /** @var int The size of the referenced file. */
+ protected $size;
+
+ /**
+ * @param string $id This Item’s identifier.
+ * @param string $href The path to the corresponding file.
+ * @param callable $dataCallable A callable to get data from the referenced file.
+ * @param int $size The size of the referenced file.
+ * @param string|null $mediaType The media type of the corresponding file. If omitted XHTML is assumed.
+ */
+ public function __construct($id, $href, $dataCallable, $size, $mediaType = null)
+ {
+ $this->id = $id;
+ $this->href = $href;
+ $this->dataCallable = $dataCallable;
+ $this->size = $size;
+ $this->mediaType = $mediaType ?: static::XHTML;
+ }
+
+ /**
+ * @return string
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return string
+ */
+ public function getHref()
+ {
+ return $this->href;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMediaType()
+ {
+ return $this->mediaType;
+ }
+
+ /**
+ * Extract (a part of) the contents from the referenced XML file.
+ *
+ * @param string|null $fragmentBegin ID of the element where to start reading the contents.
+ * @param string|null $fragmentEnd ID of the element where to stop reading the contents.
+ * @param bool $keepMarkup Whether to keep the XHTML markup rather than extracted plain text.
+ * @return string The contents of that fragment.
+ * @throws Exception
+ */
+ public function getContents($fragmentBegin = null, $fragmentEnd = null, $keepMarkup = false)
+ {
+ $dom = new DOMDocument();
+ $dom->loadXML(HtmlTools::convertEntitiesNamedToNumeric($this->getData()));
+
+ // get the starting point
+ if ($fragmentBegin) {
+ $xp = new DOMXPath($dom);
+ $node = $xp->query("//*[@id='$fragmentBegin']")->item(0);
+ if (!$node) {
+ throw new Exception("Begin of fragment not found: No element with ID $fragmentBegin!");
+ }
+ } else {
+ $node = $dom->getElementsByTagName('body')->item(0) ?: $dom->documentElement;
+ }
+
+ $allowableTags = [
+ 'br',
+ 'p',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'span',
+ 'div',
+ 'i',
+ 'strong',
+ 'b',
+ 'table',
+ 'td',
+ 'th',
+ 'tr',
+ ];
+ $contents = '';
+ $endTags = [];
+ /** @var DOMElement|DOMText $node */
+ // traverse DOM structure till end point is reached, accumulating the contents
+ while ($node && (!$fragmentEnd || !$node->hasAttributes() || $node->getAttribute('id') != $fragmentEnd)) {
+ if ($node instanceof DOMText) {
+ // when encountering a text node append its value to the contents
+ $contents .= $keepMarkup ? htmlspecialchars($node->nodeValue) : $node->nodeValue;
+ } elseif ($node instanceof DOMElement) {
+ $tag = $node->localName;
+ if ($keepMarkup && in_array($tag, $allowableTags)) {
+ $contents .= "<$tag>";
+ $endTags[] = "</$tag>";
+ } elseif (HtmlTools::isBlockLevelElement($tag)) {
+ // add whitespace between contents of adjacent blocks
+ $endTags[] = PHP_EOL;
+ } else {
+ $endTags[] = '';
+ }
+
+ if ($node->hasChildNodes()) {
+ // step into
+ $node = $node->firstChild;
+ continue;
+ }
+ }
+
+ // leave node
+ while ($node) {
+ if ($node instanceof DOMElement) {
+ $contents .= array_pop($endTags);
+ }
+
+ if ($node->nextSibling) {
+ // step right
+ $node = $node->nextSibling;
+ break;
+ } elseif ($node = $node->parentNode) {
+ // step out
+ continue;
+ } elseif ($fragmentEnd) {
+ // reached end of DOM without finding fragment end
+ throw new Exception("End of fragment not found: No element with ID $fragmentEnd!");
+ }
+ }
+ }
+ while ($endTags) {
+ $contents .= array_pop($endTags);
+ }
+
+ return $contents;
+ }
+
+ /**
+ * Get the file data.
+ *
+ * @return string The binary data of the corresponding file.
+ */
+ public function getData()
+ {
+ if ($this->dataCallable) {
+ $this->data = call_user_func($this->dataCallable);
+ $this->dataCallable = null;
+ }
+
+ return $this->data;
+ }
+
+ /**
+ * Get the size of the corresponding file.
+ *
+ * @return int
+ */
+ public function getSize()
+ {
+ return $this->size ?: strlen($this->getData());
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Data/Manifest.php b/vendor/mikespub/php-epub-meta/src/Data/Manifest.php
new file mode 100644
index 000000000..428b2cc02
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Data/Manifest.php
@@ -0,0 +1,174 @@
+<?php
+
+namespace SebLucas\EPubMeta\Data;
+
+use ArrayAccess;
+use Countable;
+use Exception;
+use BadMethodCallException;
+use Iterator;
+
+/**
+ * EPUB manifest structure
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ * @implements \Iterator<string, Item>
+ * @implements \ArrayAccess<string, Item>
+ */
+class Manifest implements Iterator, Countable, ArrayAccess
+{
+ /** @var array|Item[] The map of all Items in this Manifest indexed by their IDs. */
+ protected $items = [];
+
+ /**
+ * Create and add an Item with the given properties.
+ *
+ * @param string $id The identifier of the new item.
+ * @param string $href The relative path of the referenced file in the EPUB.
+ * @param callable $callable A callable to get data from the referenced file in the EPUB.
+ * @param int $size The size of the referenced file in the EPUB.
+ * @param string|null $mediaType
+ * @return Item The newly created Item.
+ * @throws Exception If $id is already taken.
+ */
+ public function createItem($id, $href, $callable, $size, $mediaType = null)
+ {
+ if (isset($this->items[$id])) {
+ throw new Exception("Item with ID $id already exists!");
+ }
+ $item = new Item($id, $href, $callable, $size, $mediaType);
+ $this->items[$id] = $item;
+
+ return $item;
+ }
+
+ /**
+ * Return the current Item while iterating this Manifest.
+ *
+ * @link http://php.net/manual/en/iterator.current.php
+ * @return Item
+ */
+ public function current(): Item
+ {
+ return current($this->items);
+ }
+
+ /**
+ * Move forward to next Item while iterating this Manifest.
+ * @link http://php.net/manual/en/iterator.next.php
+ * @return void Any returned value is ignored.
+ */
+ public function next(): void
+ {
+ next($this->items);
+ }
+
+ /**
+ * Return the ID of the current Item while iterating this Manifest.
+ *
+ * @link http://php.net/manual/en/iterator.key.php
+ * @return string|null on success, or null on failure.
+ */
+ public function key(): ?string
+ {
+ return key($this->items);
+ }
+
+ /**
+ * Checks if current Iterator position is valid.
+ *
+ * @link http://php.net/manual/en/iterator.valid.php
+ * @return boolean true on success or false on failure.
+ */
+ public function valid(): bool
+ {
+ return (bool) current($this->items);
+ }
+
+ /**
+ * Rewind the Iterator to the first element.
+ *
+ * @link http://php.net/manual/en/iterator.rewind.php
+ * @return void Any returned value is ignored.
+ */
+ public function rewind(): void
+ {
+ reset($this->items);
+ }
+
+ /**
+ * Get the first Item of this Manifest.
+ *
+ * @return Item
+ */
+ public function first()
+ {
+ return reset($this->items);
+ }
+
+ /**
+ * Get the last Item of this Manifest.
+ *
+ * @return Item
+ */
+ public function last()
+ {
+ return end($this->items);
+ }
+
+ /**
+ * Count items of this Manifest.
+ *
+ * @link https://php.net/manual/en/countable.count.php
+ * @return int The number of Items contained in this Manifest.
+ */
+ public function count(): int
+ {
+ return count($this->items);
+ }
+
+ /**
+ * Whether a offset exists
+ * @link https://php.net/manual/en/arrayaccess.offsetexists.php
+ * @param string $offset An offset to check for.
+ * @return boolean true on success or false on failure.
+ */
+ public function offsetExists($offset): bool
+ {
+ return isset($this->items[$offset]);
+ }
+
+ /**
+ * Offset to retrieve
+ * @link https://php.net/manual/en/arrayaccess.offsetget.php
+ * @param string $offset The offset to retrieve.
+ * @return Item
+ */
+ public function offsetGet($offset): Item
+ {
+ return $this->items[$offset];
+ }
+
+ /**
+ * Offset to set
+ * @link https://php.net/manual/en/arrayaccess.offsetset.php
+ * @param mixed $offset The offset to assign the value to.
+ * @param mixed $value The value to set.
+ * @throws BadMethodCallException
+ */
+ public function offsetSet($offset, $value): void
+ {
+ throw new BadMethodCallException("Only reading array access is supported!");
+ }
+
+ /**
+ * Offset to unset
+ * @link https://php.net/manual/en/arrayaccess.offsetunset.php
+ * @param mixed $offset The offset to unset.
+ * @throws BadMethodCallException
+ */
+ public function offsetUnset($offset): void
+ {
+ throw new BadMethodCallException("Only reading array access is supported!");
+ }
+}