*/ class ItemPack implements JsonSerializable { /** * The supported assets types * @var string[] */ private static $assetTypes = [ 'html', 'document', 'js', 'css', 'font', 'img', 'audio', 'video', 'xinclude', 'apip', 'pdf' ]; /** * The item type * @var string */ private $type; /** * The item data as arrays. Can be anything, just be careful of cyclic refs. * @var array */ private $data = []; /** * The item's required assets by type * @var array */ private $assets = []; /** * Determines what type of assets should be packed as well as packer * @example array('css'=>'base64') * @var array */ protected $assetEncoders = [ 'html' => 'none', 'document' => 'none', 'js' => 'none', 'css' => 'none', 'font' => 'none', 'img' => 'none', 'audio' => 'none', 'video' => 'none', 'xinclude' => 'none', 'apip' => 'none', 'pdf' => 'none', ]; /** * Should be @import or url() processed * @var bool */ protected $nestedResourcesInclusion = true; /** * Creates an ItemPack with the required data. * * @param string $type the item type * @param array $data the item data * * @throw InvalidArgumentException */ public function __construct($type, $data) { if (empty($type)) { throw new InvalidArgumentException('Please provide and item type'); } if (!is_array($data)) { throw new InvalidArgumentException('Please provide the item data as an array'); } $this->type = $type; $this->data = $data; } /** * Get the item type * @return string the type */ public function getType(): string { return $this->type; } /** * Get the item data * @return array the data */ public function getData(): array { return $this->data; } /** * Set item's assets of a given type to the pack. * * @param string $type * @param $assets * @param StorageDirectory|null $publicDirectory * @param bool $skipBinaries * * @throws ExceptionMissingEncoder * @throws FileNotFoundException */ public function setAssets( string $type, $assets, ?StorageDirectory $publicDirectory = null, bool $skipBinaries = false ): void { if (!is_array($assets)) { throw new InvalidArgumentException('Assets should be an array, "' . gettype($assets) . '" given'); } foreach ($assets as $asset) { $this->setAsset($type, $asset, $publicDirectory, $skipBinaries); } } /** * @param string $type * @param $asset * @param StorageDirectory|null $publicDirectory * @param bool $skipBinaries * * @throws ExceptionMissingEncoder * @throws FileNotFoundException */ public function setAsset( string $type, $asset, ?StorageDirectory $publicDirectory = null, bool $skipBinaries = false ): void { if (!in_array($type, self::$assetTypes, true)) { throw new InvalidArgumentException(sprintf( 'Unknown asset type "%s", it should be either %s', $type, implode(', ', self::$assetTypes) )); } $encoder = EncoderService::singleton()->get($this->assetEncoders[$type], $publicDirectory); $assetKey = $this->getAssetKey($asset); if ($skipBinaries && Base64::isEncodedImage($asset->getMediaIdentifier())) { return; } $this->assets[$type][$assetKey] = $encoder->encode($asset); } /** * Get item's assets of a given type. * * @param string $type the assets type, one of those who are supported * @return string[] the list of assets' URL to load */ public function getAssets(string $type): array { if (!array_key_exists($type, $this->assets)) { return []; } return $this->assets[$type]; } /** * How to serialize the pack in JSON. */ public function JsonSerialize() { return [ 'type' => $this->type, 'data' => $this->data, 'assets' => $this->assets ]; } /** * @return array */ public function getAssetEncoders(): array { return $this->assetEncoders; } /** * @param array $assetEncoders */ public function setAssetEncoders(array $assetEncoders): void { foreach ($assetEncoders as $type => $encoder) { if ($encoder == '') { $this->assetEncoders[$type] = 'none'; } else { $this->assetEncoders[$type] = $encoder; } } } /** * @return boolean */ public function isNestedResourcesInclusion(): bool { return $this->nestedResourcesInclusion; } /** * @param boolean $nestedResourcesInclusion */ public function setNestedResourcesInclusion(bool $nestedResourcesInclusion): void { $this->nestedResourcesInclusion = (bool)$nestedResourcesInclusion; } /** * @param string|MediaAsset $asset * * @throws FileNotFoundException * * @return string */ private function getAssetKey($asset): string { if (!$asset instanceof MediaAsset) { if (!is_string($asset)) { throw new LogicException('Item pack can only pack assets as string url or MediaAsset'); } return $asset; } $mediaSource = $asset->getMediaSource(); $mediaIdentifier = $asset->getMediaIdentifier(); if ( $mediaSource instanceof MediaSource || $mediaSource instanceof HttpSource || Base64::isEncodedImage($mediaIdentifier) ) { return $mediaIdentifier; } return $mediaSource->getBaseName($mediaIdentifier); } }