commit fb50e3a1c9e57b7eb2f589fa35e1de9af2e76313 Author: Andrey Pokidov Date: Wed Mar 18 16:46:43 2020 +0700 +Базовая версия Asset manager'а diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..403848e --- /dev/null +++ b/composer.json @@ -0,0 +1,20 @@ +{ + "name": "artmark/assets", + "description": "Asset manager", + "type": "library", + "license": "Proprietary", + "authors": [ + { + "name": "Andrey Pokidov", + "email": "pokidov@e-traffic.ru" + } + ], + "require": { + "php": ">=7.0.0", + }, + "autoload": { + "psr-0": { + "Artmark\\Assets\\": "src/" + } + } +} diff --git a/src/Asset.php b/src/Asset.php new file mode 100644 index 0000000..5e0a166 --- /dev/null +++ b/src/Asset.php @@ -0,0 +1,166 @@ + + */ +class Asset +{ + const TYPE_JAVASCRIPT = 'js'; + const TYPE_CSS = 'css'; + + const POSITION_HEAD = 'head'; + const POSITION_TOP = 'top'; + const POSITION_BOTTOM = 'bottom'; + + private $name = ''; + private $type = self::TYPE_JAVASCRIPT; + private $position = self::POSITION_HEAD; + private $url = ''; + private $version = ''; + + + /** + * Создаёт новый объекс Script, описывающий данные о скрипте + * @param string $url URL скрипта + * @param string|int $version Версия скрипта + * @param string $type Тип скрипта, может принимать одно из значений Script::TYPE_JAVASCRIPT или Script::TYPE_CSS + * @param string $position Место скрипта в коде страницы, может принимать одно из значений: + * + */ + public function __construct($name, $url, $version, $type = self::TYPE_JAVASCRIPT, $position = self::POSITION_HEAD) + { + self::checkName($name); + self::checkUrl($url); + self::checkVersion($url); + self::checkAssetType($type); + self::checkAssetPosition($position); + + $this->name = self::correctName($name); + $this->url = trim($url); + $this->version = is_string($version) ? trim($version) : $version; + $this->type = $type; + $this->position = $position; + } + + public function name() + { + return $this->name; + } + + public function type() + { + return $this->type; + } + + public function isJavaScript() + { + return $this->type == self::TYPE_JAVASCRIPT; + } + + public function isCss() + { + return $this->type == self::TYPE_CSS; + } + + public function position() + { + return $this->position; + } + + public function isAtHead() + { + return $this->position == self::POSITION_HEAD; + } + + public function isAtTop() + { + return $this->position == self::POSITION_TOP; + } + + public function isAtBottom() + { + return $this->position == self::POSITION_BOTTOM; + } + + public function url() + { + return $this->url; + } + + public function urlWithVersion() + { + if (!$this->hasVersion()) + { + return $this->url; + } + + return $this->url . (strpos($this->url, '?') === false ? '?' : '&') . 'v=' . urlencode($this->version); + } + + public function hasVersion() + { + return !empty($this->version); + } + + public function version() + { + return $this->version; + } + + + public static function correctName($name) + { + return strtolower(trim(strval($name))); + } + + public static function checkName($name) + { + if (!is_string($name)) { + throw new AssetException('Incorrect name type: `' . gettype($name) . '`, the name of an asset must be a string'); + } + + if (trim($name) == '') { + throw new AssetException('The name of an asset cannot be an empty string'); + } + } + + public static function checkUrl($url) + { + if (!is_string($url)) { + throw new AssetException('Incorrect URL type: `' . gettype($url) . '`, the URL of an asset must be a string'); + } + + if (trim($url) == '') { + throw new AssetException('The URL of an asset cannot be an empty string'); + } + } + + public static function checkVersion($verison) + { + if (!is_string($verison) && !is_int($verison)) { + throw new AssetException('Incorrect version type: `' . gettype($verison) . '`, the version of an asset must be a string or an integer number'); + } + } + + public static function checkAssetType($type) + { + if ($type != self::TYPE_JAVASCRIPT && $type != self::TYPE_CSS) { + throw new AssetException('Incorrect asset type: `' . $type . '`'); + } + } + + public static function checkAssetPosition($position) + { + if ($position != self::POSITION_HEAD && $position != self::POSITION_TOP && $position != self::POSITION_BOTTOM) { + throw new AssetException('Incorrect asset position: `' . $position . '`'); + } + } +} diff --git a/src/AssetException.php b/src/AssetException.php new file mode 100644 index 0000000..54178fe --- /dev/null +++ b/src/AssetException.php @@ -0,0 +1,16 @@ + + */ +class AssetException extends \Exception +{ + public function __construct(string $message = "", int $code = 0, \Throwable $previous = NULL) + { + parent::__construct($message, $code, $previous); + } +} diff --git a/src/AssetManager.php b/src/AssetManager.php new file mode 100644 index 0000000..4dfce0d --- /dev/null +++ b/src/AssetManager.php @@ -0,0 +1,167 @@ + + */ +class AssetManager +{ + /** + * @var AssetManager + */ + private static $manager = null; + + /** + * + * @var Asset[] + */ + private $assets = []; + + private function __construct() + { + } + + /** + * + * @return AssetManager + */ + public static function instance() + { + if (is_null(self::$manager)) { + self::$manager = new AssetManager(); + } + + return self::$manager; + } + + /** + * + * @return $this + */ + public function resetAssets() + { + $this->assets = []; + + return $this; + } + + /** + * + * @param string $name + * @return $this + */ + public function loadCollection($name) + { + $assets = config('assets.' . $name); + + if (!is_array($assets) || count($assets) == 0) { + return $this; + } + + foreach ($assets as $name => $assetInfo) { + $this->loadAsset($name, $assetInfo); + } + + return $this; + } + + private function loadAsset($name, $assetInfo) + { + if (!is_array($assetInfo) || !array_key_exists('type', $assetInfo) || !array_key_exists('path', $assetInfo)) { + return; + } + + $version = array_key_exists('version', $assetInfo) ? $assetInfo['version'] : ''; + $position = array_key_exists('position', $assetInfo) ? $assetInfo['position'] : Asset::POSITION_HEAD; + + $this->pushAsset(new Asset($name, $assetInfo['path'], $version, $assetInfo['type'], $position)); + } + + /** + * + * @param string $name + * @return boolean + */ + public function has($name) + { + return array_key_exists(Asset::correctName($name), $this->assets); + } + + /** + * + * @param string $name + * @return Asset + */ + public function get($name) + { + $correctedName = Asset::correctName($name); + return array_key_exists($correctedName, $this->assets) ? $this->assets[$correctedName] : null; + } + + /** + * + * @param Asset $asset + * @return $this + */ + public function pushAsset(Asset $asset) + { + $this->assets[$asset->name()] = $asset; + return $this; + } + + /** + * + * @param string $name + * @param string $url + * @param string|int $version + * @param string $position + * @return $this + */ + public function setStyleSheet($name, $url, $version = '', $position = Asset::POSITION_HEAD) + { + $asset = new Asset($name, $url, $version, Asset::TYPE_CSS, $position); + $this->pushAsset($asset); + return $this; + } + + /** + * + * @param string $name + * @param string $url + * @param string|int $version + * @param string $position + * @return $this + */ + public function setJavaScript($name, $url, $version = '', $position = Asset::POSITION_HEAD) + { + $asset = new Asset($name, $url, $version, Asset::TYPE_JAVASCRIPT, $position); + $this->pushAsset($asset); + return $this; + } + + /** + * + * @param string $position + * @param string $type + * @return Asset[] + */ + public function getAssetsFor($position, $type) + { + if (!is_string($position) || !is_string($type)) { + return []; + } + + $assets = []; + + foreach ($this->assets as $asset) { + if ($asset->type() == $type && $asset->position() == $position) { + $assets[] = $asset; + } + } + + return $assets; + } +} diff --git a/src/AssetRenderer.php b/src/AssetRenderer.php new file mode 100644 index 0000000..939ff92 --- /dev/null +++ b/src/AssetRenderer.php @@ -0,0 +1,95 @@ + + */ +class AssetRenderer +{ + /** + * + * @var AssetRenderer + */ + private static $render = null; + + private static $registered = false; + + private function __construct() + { + } + + public static function register() + { + if (self::$registered) { + return; + } + + self::$registered = true; + + Blade::directive('css_assets', function ($expression) { return 'showStyleSheet(' . $expression . '); ?>'; }); + Blade::directive('js_assets', function ($expression) { return 'showJavaScript(' . $expression . '); ?>'; }); + } + + /** + * + * @return AssetRenderer + */ + public static function instance() + { + if (is_null(self::$render)) { + self::$render = new AssetRenderer(); + } + return self::$render; + } + + public function showJavaScript($position) + { + return $this->show($position, Asset::TYPE_JAVASCRIPT); + } + + public function showStyleSheet($position) + { + return $this->show($position, Asset::TYPE_CSS); + } + + public function show($position, $type) + { + $assets = AssetManager::instance()->getAssetsFor($position, $type); + + if (empty($assets)) { + return ''; + } + + $html = ''; + + foreach ($assets as $asset) { + $html .= $this->getAssetHtml($asset); + } + + return $html; + } + + private function getAssetHtml(Asset $asset) + { + if ($asset->isCss()) { + return $this->getCssHtml($asset); + } + + return $this->getJavaAssetHtml($asset); + } + + private function getCssHtml(Asset $stylesheet) + { + return '' . "\n"; + } + + private function getJavaAssetHtml(Asset $javascript) + { + return '' . "\n"; + } +}