From 6d2b1b569cb4ba908c826e95b83b47d9265d0142 Mon Sep 17 00:00:00 2001 From: Ade Attwood Date: Fri, 15 Sep 2017 21:06:31 +0100 Subject: [PATCH] move over to addon --- readme.md | 2 +- src/filters/PageMin.php | 141 ++++++++++++++++++++++++++++++ src/{ => helpers}/ArrayHelper.php | 7 +- src/{ => helpers}/ArrayObject.php | 5 +- src/{ => helpers}/Dumper.php | 0 src/{ => helpers}/Enum.php | 2 +- src/web/RedirectRule.php | 60 +++++++++++++ src/web/View.php | 129 +++++++++++++++++++++++++++ tests/_data/ModelOne.php | 2 +- tests/unit/ArrayHelperCest.php | 6 +- tests/unit/ArrayObjectCest.php | 2 +- tests/unit/EnumCest.php | 2 +- 12 files changed, 345 insertions(+), 13 deletions(-) create mode 100644 src/filters/PageMin.php rename src/{ => helpers}/ArrayHelper.php (96%) rename src/{ => helpers}/ArrayObject.php (98%) rename src/{ => helpers}/Dumper.php (100%) rename src/{ => helpers}/Enum.php (99%) create mode 100644 src/web/RedirectRule.php create mode 100644 src/web/View.php diff --git a/readme.md b/readme.md index bda0286..f89f85e 100644 --- a/readme.md +++ b/readme.md @@ -7,7 +7,7 @@ A collection of uefull helpers for the Yii2 framework Install with composer ~~~php -compsoer install adeattwood/yii-helpers +compsoer install adeattwood/yii-addon ~~~ ## Class docs diff --git a/src/filters/PageMin.php b/src/filters/PageMin.php new file mode 100644 index 0000000..935d75d --- /dev/null +++ b/src/filters/PageMin.php @@ -0,0 +1,141 @@ +enabled) { + return true; + } + + $response = Yii::$app->getResponse(); + $response->on(Response::EVENT_BEFORE_SEND, [$this, 'pageMin']); + return true; + } + + public function pageMin($event) + { + Yii::$app->response->data = $this->minifyHtml($event->sender->data); + } + + public function minifyHtml( $input ) + { + if(trim($input) === "") return $input; + $input = preg_replace_callback('#<([^\/\s<>!]+)(?:\s+([^<>]*?)\s*|\s*)(\/?)>#s', function($matches) { + return '<' . $matches[1] . preg_replace('#([^\s=]+)(\=([\'"]?)(.*?)\3)?(\s+|$)#s', ' $1$2', $matches[2]) . $matches[3] . '>'; + }, str_replace("\r", "", $input)); + if(strpos($input, ' style=') !== false) { + $input = preg_replace_callback('#<([^<]+?)\s+style=([\'"])(.*?)\2(?=[\/\s>])#s', function($matches) { + return '<' . $matches[1] . ' style=' . $matches[2] . $this->minifyCss($matches[3]) . $matches[2]; + }, $input); + } + if(strpos($input, '') !== false) { + $input = preg_replace_callback('#(.*?)#is', function($matches) { + return ''. $this->minifyCss($matches[2]) . ''; + }, $input); + } + if(strpos($input, '') !== false) { + $input = preg_replace_callback('#(.*?)#is', function($matches) { + return ''. $this->minifyJs($matches[2]) . ''; + }, $input); + } + return preg_replace( + [ + '#<(img|input)(>| .*?>)#s', + '#()|(>)(?:\n*|\s{2,})(<)|^\s*|\s*$#s', + '#()|(?)\s+(<\/.*?>)|(<[^\/]*?>)\s+(?!\<)#s', + '#()|(<[^\/]*?>)\s+(<[^\/]*?>)|(<\/.*?>)\s+(<\/.*?>)#s', + '#()|(<\/.*?>)\s+(\s)(?!\<)|(?)\s+(\s)(<[^\/]*?\/?>)|(<[^\/]*?\/?>)\s+(\s)(?!\<)#s', + '#()|(<[^\/]*?>)\s+(<\/.*?>)#s', + '#<(img|input)(>| .*?>)<\/\1>#s', + '#( ) (?![<\s])#', + '#(?<=\>)( )(?=\<)#', + '#\s*\s*|(?)\n+(?=\<[^!])#s' + ], + [ + '<$1$2', + '$1$2$3', + '$1$2$3', + '$1$2$3$4$5', + '$1$2$3$4$5$6$7', + '$1$2$3', + '<$1$2', + '$1 ', + '$1', + '' + ], + $input + ); + } + + public function minifyCss($input) + { + if (trim($input) === '') { + return $input; + } + + return preg_replace( + [ + '#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')|\/\*(?!\!)(?>.*?\*\/)|^\s*|\s*$#s', + '#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/))|\s*+;\s*+(})\s*+|\s*+([*$~^|]?+=|[{};,>~+]|\s*+-(?![0-9\.])|!important\b)\s*+|([[(:])\s++|\s++([])])|\s++(:)\s*+(?!(?>[^{}"\']++|"(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')*+{)|^\s++|\s++\z|(\s)\s+#si', + '#(?<=[\s:])(0)(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)#si', + '#:(0\s+0|0\s+0\s+0\s+0)(?=[;\}]|\!important)#i', + '#(background-position):0(?=[;\}])#si', + '#(?<=[\s:,\-])0+\.(\d+)#s', + '#(\/\*(?>.*?\*\/))|(?.*?\*\/))|(\burl\()([\'"])([^\s]+?)\3(\))#si', + '#(?<=[\s:,\-]\#)([a-f0-6]+)\1([a-f0-6]+)\2([a-f0-6]+)\3#i', + '#(?<=[\{;])(border|outline):none(?=[;\}\!])#', + '#(\/\*(?>.*?\*\/))|(^|[\{\}])(?:[^\s\{\}]+)\{\}#s' + ], + [ + '$1', + '$1$2$3$4$5$6$7', + '$1', + ':0', + '$1:0 0', + '.$1', + '$1$3', + '$1$2$4$5', + '$1$2$3', + '$1:0', + '$1$2' + ], + $input + ); + } + + public function minifyJs($input) + { + if (trim($input) === '') { + return $input; + } + + return preg_replace( + [ + '#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*\/\*(?!\!|@cc_on)(?>[\s\S]*?\*\/)\s*|\s*(?.*?\*\/)|\/(?!\/)[^\n\r]*?\/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#s', + '#;+\}#', + '#([\{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=\:)#i', + '#([a-z0-9_\)\]])\[([\'"])([a-z_][a-z0-9_]*)\2\]#i' + ], + [ + '$1', + '$1$2', + '}', + '$1$3', + '$1.$3' + ], + $input + ); + } + +} diff --git a/src/ArrayHelper.php b/src/helpers/ArrayHelper.php similarity index 96% rename from src/ArrayHelper.php rename to src/helpers/ArrayHelper.php index 559d2ab..6755a7b 100644 --- a/src/ArrayHelper.php +++ b/src/helpers/ArrayHelper.php @@ -1,12 +1,13 @@ 'yiiaddon\web\RedirectRule', + * + * 'route' => '/about', + * + * 'permanents' => [ + * 'deprecated-about', + * 'an-older-deprecated-about' + * ], + * + * 'temporaries' => [ + * 'under-construction-about', + * ] + * ] + */ +class RedirectRule extends \yii\web\UrlRule +{ + public $permanents = []; + + public $temporaries = []; + + public function init() + { + if ($this->pattern === null) { + $this->pattern = false; + } + + if ($this->name === null) { + $this->name = $this->route; + } + + parent::init(); + } + + public function parseRequest($manager, $request) + { + $pathInfo = $request->getPathInfo(); + + if(in_array($pathInfo, $this->permanents)) { + $request->setPathInfo($this->name); + Yii::$app->response->redirect($this->name, 301); + } else if(in_array($pathInfo, $this->temporaries)) { + $request->setPathInfo($this->name); + Yii::$app->response->redirect($this->name, 302); + } + + parent::parseRequest($manager, $request); + Yii::$app->end(); + + } + +} diff --git a/src/web/View.php b/src/web/View.php new file mode 100644 index 0000000..1ec42ea --- /dev/null +++ b/src/web/View.php @@ -0,0 +1,129 @@ +googleAnalyticsPosition) { + $this->googleAnalyticsPosition = self::POS_END; + } + + return parent::init(); + } + + public function googleAnalyticsSet($key, $value) + { + $googleAnalyticsSet[$key] = $value; + } + + + public function renderHeadHtml() + { + $metas = [ + 'charset' => ['charset' => Yii::$app->charset], + 'viewport' => ['name' => 'viewport', 'content' => $this->viewportContent], + 'http-equiv' => ['http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge'], + 'description' => ['name' => 'description', 'content' => $this->description], + 'keywords' => $this->keywords ? ['name' => 'keywords', 'content' => $this->keywords] : false, + 'author' => $this->authorName ? ['name' => 'author', 'content' => $this->authorName] : false + ]; + + $links = [ + 'canonical' => ['rel' => 'canonical', 'href' => Url::to($this->url, true)] + ]; + + if ($this->facebook_og) { + $metas = array_merge($metas, $this->registerFacebookOg()); + } + + if ($this->twitter_card) { + $metas = array_merge($metas, $this->registerTwitterCard()); + } + + foreach ($metas as $meta => $content) { + if (!isset($this->metaTags[$meta]) && $content) { + $this->registerMetaTag($content, $meta); + } + } + + foreach ($links as $link => $content) { + if (!isset($this->metaTags[$link]) && $content) { + $this->registerLinkTag($content, $link); + } + } + + if ($this->googleAnalyticsCode) { + $this->registerGoogleAnalytics(); + } + + return '' . $this->title . '' . parent::renderHeadHtml(); + } + + public function registerGoogleAnalytics() + { + $js = "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','$this->googleAnalyticsFile','$this->googleAnalyticsVar');"; + $js .= "$this->googleAnalyticsVar('create', '$this->googleAnalyticsCode', 'auto');"; + $js .= "$this->googleAnalyticsVar('send', 'pageview');"; + + foreach ($this->googleAnalyticsSet as $key => $value) { + $js .= "$this->googleAnalyticsVar('set', '$key', '$value');"; + } + + $this->registerJS($js, $this->googleAnalyticsPosition); + + } + + public function registerFacebookOg() + { + return [ + 'og:locale' => ['property' => 'og:locale', 'content' => 'en_GB'], + 'og:type' => ['property' => 'og:type', 'content' => 'website'], + 'og:title' => ['property' => 'og:title', 'content' => $this->title], + 'og:description' => ['property' => 'og:description', 'content' => $this->description], + 'og:url' => ['property' => 'og:url', 'content' => Url::to($this->url, true)], + 'og:site_name' => ['property' => 'og:site_name', 'content' => Yii::$app->name], + 'og:image' => $this->image ? ['property' => 'og:image', 'content' => Url::to($this->image, true)] : false, + ]; + } + + public function registerTwitterCard() + { + return [ + 'twitter:card' => ['name' => 'twitter:card', 'content' => 'summary'], + 'twitter:description' => ['name' => 'twitter:description', 'content' => $this->description], + 'twitter:title' => ['name' => 'twitter:title', 'content' => $this->title], + 'twitter:url' => ['name' => 'twitter:url', 'content' => Url::to($this->url, true)], + 'twitter:site' => $this->twitterTag ? ['name' => 'twitter:site', 'content' => $this->twitterTag] : false, + 'twitter:image' => $this->image ? ['name' => 'twitter:image', 'content' => Url::to($this->image, true)] : false, + 'twitter:creator' => $this->authorTwitterTag ? ['name' => 'twitter:creator', 'content' => $this->authorTwitterTag] : false, + ]; + } + +} diff --git a/tests/_data/ModelOne.php b/tests/_data/ModelOne.php index 1433de3..9b93cfb 100644 --- a/tests/_data/ModelOne.php +++ b/tests/_data/ModelOne.php @@ -1,6 +1,6 @@