Commit 4fcaa96c2ee443fbfc9500d9dd43e6870b209600
Merge branch '5953b4f' of gitlab.artweb.com.ua:steska/clinica
Showing
9 changed files
with
580 additions
and
50 deletions
Show diff stats
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * ====================================================================================================================| | ||
| 5 | + * Компонент, который служит для обрезания строк по заданным параметрам | ||
| 6 | + * ====================================================================================================================| | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | +namespace common\components; | ||
| 10 | + | ||
| 11 | +use yii\base\Object; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * Class Substringer | ||
| 15 | + * @package common\components | ||
| 16 | + * ====================================================================================================================| | ||
| 17 | + * @method @static simpleStringSubstring | ||
| 18 | + * @method @static changeStringByRegex | ||
| 19 | + * ====================================================================================================================| | ||
| 20 | + */ | ||
| 21 | +class Substringer extends Object | ||
| 22 | +{ | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * @param string $haystack | ||
| 27 | + * @param string $needle | ||
| 28 | + * @param bool $reverse | ||
| 29 | + * @return string | ||
| 30 | + *=================================================================================================================| | ||
| 31 | + * @static | ||
| 32 | + * Метод, который берет строку, и обрезает её до заданного момента | ||
| 33 | + *=================================================================================================================| | ||
| 34 | + * @todo | ||
| 35 | + * Пока что метод адекватно работает только при том условии, что нужный нам символ/комбинация символов является | ||
| 36 | + * первой при поисковом запросе, нужно допилить логику, если например: | ||
| 37 | + * $haystack='www.site.com?sort=title_act&sort=category-1&sort=test_val_desc | ||
| 38 | + * то, обрезать всё до нужной комбинации | ||
| 39 | + *=================================================================================================================| | ||
| 40 | + * @example 1 | ||
| 41 | + * Start Data: | ||
| 42 | + * $haystack='https://www.youtube.com?v=OBwS66EBUcY | ||
| 43 | + * $needle='?'; | ||
| 44 | + * Return result: | ||
| 45 | + * $res='https://www.youtube.com/watch'; | ||
| 46 | + * @example 2 | ||
| 47 | + * Start data | ||
| 48 | + * $haystack='https://www.youtube.com/watch?v=OBwS66EBUcY'; | ||
| 49 | + * $needle ='?'; | ||
| 50 | + * $res = '?v=OBwS66EBUcY' | ||
| 51 | + * | ||
| 52 | + */ | ||
| 53 | + public static function simpleStringSubstring(string $haystack, string $needle): string | ||
| 54 | + { | ||
| 55 | + $deletePosition = strpos($haystack, $needle); | ||
| 56 | + if ($deletePosition == 0) | ||
| 57 | + return $haystack; | ||
| 58 | + $result = substr($haystack, 0, $deletePosition); | ||
| 59 | + return $result; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + | ||
| 64 | + | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * @param string $haystack | ||
| 70 | + * @param string $regex1 | ||
| 71 | + * @param string $regex2 | ||
| 72 | + * @param string $requiredDelimiter | ||
| 73 | + * @param string $firstConcatenateSymbol | ||
| 74 | + * @param string $secondConcatenateSymbol | ||
| 75 | + * @return string | ||
| 76 | + * ================================================================================================================| | ||
| 77 | + * Метод, который берет $haystack, а так же 2 Regex паттерна | ||
| 78 | + * 1) пытается найти regex совпадения | ||
| 79 | + * если их нет @return original $haystack | ||
| 80 | + * 2) вырезает всё лишнее со строки с помощью self::Substringer | ||
| 81 | + * 3) конкатенирует между собой то,что получилось за принципом | ||
| 82 | + * mainString+delimiter1+regex1Result+delimiter2+regex2Result | ||
| 83 | + * ================================================================================================================| | ||
| 84 | + * @example | ||
| 85 | + * $haystack='https://www.linija-svitla.ua/catalog/ulichnoe-osveshchenie?page_num=3&fcatlist=3268%2C&sort=test_test&3269%2C3270%2C3272%2C3273%2C3274%2C3275&page=50&per-page=18'; | ||
| 86 | + * $regex1='/(\??|&?)page=\d{1,5}&per-page=\d{1,5}/'; | ||
| 87 | + * $regex2='/(\?|&)sort=[a-zA-z_]+/'; | ||
| 88 | + * $requiredDelimiter='?'; | ||
| 89 | + * $firstConcatenateSymbol='?'; | ||
| 90 | + * $secondConcatenateSymbol='&'; | ||
| 91 | + * $res=$this->changeStringByRegex($haystack,$regex1,$regex2,$firstConcatenateSymbol,$secondConcatenateSymbol,$requiredDelimiter); | ||
| 92 | + * @example-return | ||
| 93 | + * https://www.linija-svitla.ua/catalog/ulichnoe-osveshchenie?page=50&per-page=18&sort=test_test | ||
| 94 | + * ================================================================================================================| | ||
| 95 | + * @todo | ||
| 96 | + * 1) Пока что метод работает только с 2 regex,надо будет поменять строго regex string => regex array | ||
| 97 | + * 2) Метод полюбому обрезает первый символ результирующей строки regex | ||
| 98 | + * 3) нужно сделать механизм замены строки только по 1 regex | ||
| 99 | + * ================================================================================================================| | ||
| 100 | + * | ||
| 101 | + */ | ||
| 102 | + /** | ||
| 103 | + * @param string $haystack | ||
| 104 | + * @param string $regex1 | ||
| 105 | + * @param string $regex2 | ||
| 106 | + * @param string $requiredDelimiter | ||
| 107 | + * @param string $firstConcatenateSymbol | ||
| 108 | + * @param string $secondConcatenateSymbol | ||
| 109 | + * | ||
| 110 | + * @return string | ||
| 111 | + */ | ||
| 112 | + public static function changeStringByRegex(string $haystack, string $regex1, string $regex2, string $requiredDelimiter = '', | ||
| 113 | + string $firstConcatenateSymbol = '', | ||
| 114 | + string $secondConcatenateSymbol = '' | ||
| 115 | + ): string | ||
| 116 | + { | ||
| 117 | + | ||
| 118 | + # 1 give rexe1/regex2 parts | ||
| 119 | + # IF we have no consilience with both Regex == > return $haystack | ||
| 120 | + if (preg_match($regex1, $haystack) !== 0 || preg_match($regex2, $haystack) !== 0) { | ||
| 121 | + preg_match($regex1, $haystack, $matches[0]); | ||
| 122 | + preg_match($regex2, $haystack, $matches[1]); | ||
| 123 | + } else return $haystack; | ||
| 124 | + | ||
| 125 | + # 2 give must part of string | ||
| 126 | + $mustPartOfstring = self::SimpleStringSubstring($haystack, $requiredDelimiter); | ||
| 127 | + | ||
| 128 | + # 3 if regex1/regex2 !empty concatenate they with $mustPartOfString | ||
| 129 | + if (isset($matches[0][0]) && isset($matches[1][0])) { | ||
| 130 | + # удаляем первый символ ( прим; $matches[0][0]='&sort=test_desc') | ||
| 131 | + # нам надо только текст без первого спецсимвола | ||
| 132 | + $matches[0][0] = substr($matches[0][0], 1); | ||
| 133 | + $mustPartOfstring = (isset($matches[0][0])) ? $mustPartOfstring . $firstConcatenateSymbol . $matches[0][0] : $mustPartOfstring; | ||
| 134 | + $matches[1][0] = substr($matches[1][0], 1); | ||
| 135 | + $mustPartOfstring = (isset($matches[1][0])) ? $mustPartOfstring . $secondConcatenateSymbol . $matches[1][0] : $mustPartOfstring; | ||
| 136 | + } # если найден только 1й regex | ||
| 137 | + elseif (isset($matches[0][0]) && !isset($matches[1][0])) { | ||
| 138 | + $matches[0][0] = substr($matches[0][0], 1); | ||
| 139 | + $mustPartOfstring = (isset($matches[0][0])) ? $mustPartOfstring . $firstConcatenateSymbol . $matches[0][0] : $mustPartOfstring; | ||
| 140 | + } # если найден 2й regex | ||
| 141 | + elseif (!isset($matches[0][0]) && isset($matches[1][0])) { | ||
| 142 | + $matches[1][0] = substr($matches[1][0], 1); | ||
| 143 | + $mustPartOfstring = (isset($matches[1][0])) ? $mustPartOfstring . $firstConcatenateSymbol . $matches[1][0] : $mustPartOfstring; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + return $mustPartOfstring; | ||
| 147 | + | ||
| 148 | + | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + | ||
| 152 | +} | ||
| 0 | \ No newline at end of file | 153 | \ No newline at end of file |
frontend/controllers/BlogController.php
| @@ -10,7 +10,8 @@ | @@ -10,7 +10,8 @@ | ||
| 10 | use yii\helpers\ArrayHelper; | 10 | use yii\helpers\ArrayHelper; |
| 11 | use yii\web\Controller; | 11 | use yii\web\Controller; |
| 12 | use yii\web\NotFoundHttpException; | 12 | use yii\web\NotFoundHttpException; |
| 13 | - | 13 | + |
| 14 | + | ||
| 14 | /** | 15 | /** |
| 15 | * Class BlogController | 16 | * Class BlogController |
| 16 | * | 17 | * |
| @@ -52,15 +53,17 @@ | @@ -52,15 +53,17 @@ | ||
| 52 | ->distinct(), | 53 | ->distinct(), |
| 53 | 'pagination' => [ | 54 | 'pagination' => [ |
| 54 | 'pageSize' => 6, | 55 | 'pageSize' => 6, |
| 56 | + | ||
| 55 | ], | 57 | ], |
| 56 | ] | 58 | ] |
| 57 | ); | 59 | ); |
| 58 | - | ||
| 59 | - return $this->render( | 60 | + |
| 61 | + return $this->render( | ||
| 60 | 'index', | 62 | 'index', |
| 61 | [ | 63 | [ |
| 62 | 'categories' => $data, | 64 | 'categories' => $data, |
| 63 | 'dataProvider' => $dataProvider, | 65 | 'dataProvider' => $dataProvider, |
| 66 | + | ||
| 64 | ] | 67 | ] |
| 65 | ); | 68 | ); |
| 66 | } | 69 | } |
frontend/controllers/ServiceController.php
| @@ -43,8 +43,8 @@ | @@ -43,8 +43,8 @@ | ||
| 43 | 43 | ||
| 44 | $layoutMicrodata=(count($model->prices)>1)? | 44 | $layoutMicrodata=(count($model->prices)>1)? |
| 45 | [ | 45 | [ |
| 46 | - '@context'=> 'http://schema.org/', | ||
| 47 | - '@type'=> 'Product', | 46 | + 'context' => 'http://schema.org/', |
| 47 | + 'type' => 'Product', | ||
| 48 | 'name'=> "'{$model->language->attributes['title']}'", | 48 | 'name'=> "'{$model->language->attributes['title']}'", |
| 49 | 'offers' => | 49 | 'offers' => |
| 50 | [ | 50 | [ |
| @@ -60,9 +60,12 @@ | @@ -60,9 +60,12 @@ | ||
| 60 | 'offers'=> [ | 60 | 'offers'=> [ |
| 61 | '@type'=> 'Offer', | 61 | '@type'=> 'Offer', |
| 62 | 'priceCurrency'=> 'UAH', | 62 | 'priceCurrency'=> 'UAH', |
| 63 | - 'Price'=> "'".max($prices)."'", | 63 | + |
| 64 | ] | 64 | ] |
| 65 | ]; | 65 | ]; |
| 66 | + if (count($model->prices) <= 1 && isset($prices)) { | ||
| 67 | + if (!empty($prices)) $layoutMicrodata['offers']['Price'] = "'" . max($prices) . "'"; | ||
| 68 | + } | ||
| 66 | 69 | ||
| 67 | 70 | ||
| 68 | $microdata=new MicrodataFabric(); | 71 | $microdata=new MicrodataFabric(); |
frontend/microdata/ProductMicrodata.php
| @@ -13,6 +13,7 @@ class ProductMicrodata extends Microdata | @@ -13,6 +13,7 @@ class ProductMicrodata extends Microdata | ||
| 13 | public $offers=null; | 13 | public $offers=null; |
| 14 | public $description=null; | 14 | public $description=null; |
| 15 | public $npm=null; | 15 | public $npm=null; |
| 16 | + public $type = null; | ||
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | 19 |
frontend/views/blog/_article.php
| @@ -27,7 +27,7 @@ $imageHeight=240; | @@ -27,7 +27,7 @@ $imageHeight=240; | ||
| 27 | 27 | ||
| 28 | <div itemtype="http://schema.org/Article" itemscope class="blog-list-wr"> | 28 | <div itemtype="http://schema.org/Article" itemscope class="blog-list-wr"> |
| 29 | 29 | ||
| 30 | - <div itemprop="logo" itemscope itemtype="https://schema.org/ImageObject" class="img-blog-list"> | 30 | + <div itemscope itemtype="https://schema.org/ImageObject" class="img-blog-list"> |
| 31 | 31 | ||
| 32 | <meta itemprop="url" content="<?=($model->image) ? $model->image->getPath() : null;?>"> | 32 | <meta itemprop="url" content="<?=($model->image) ? $model->image->getPath() : null;?>"> |
| 33 | <meta itemprop="height" content="<?=$imageWidth;?>"/> | 33 | <meta itemprop="height" content="<?=$imageWidth;?>"/> |
| @@ -48,8 +48,10 @@ $imageHeight=240; | @@ -48,8 +48,10 @@ $imageHeight=240; | ||
| 48 | </div> | 48 | </div> |
| 49 | 49 | ||
| 50 | <div class="blog-all-date-views"> | 50 | <div class="blog-all-date-views"> |
| 51 | - <metacontent="<?=date('d.m.Y', $model->created_at);?>"/> | ||
| 52 | - <div itemprop="datePublished" class="blog-date"><?=date('d.m.Y', $model->created_at)?></div> | 51 | + |
| 52 | + <metacontent | ||
| 53 | + ="<?= date('d-m-Y', $model->created_at); ?>"/> | ||
| 54 | + <div itemprop="datePublished" class="blog-date"><?= date('d-m-Y', $model->created_at) ?></div> | ||
| 53 | <div class="blog-views-comments-ico"> | 55 | <div class="blog-views-comments-ico"> |
| 54 | <div class="blog-comments-ico"><?=count($model->comments)?></div> | 56 | <div class="blog-comments-ico"><?=count($model->comments)?></div> |
| 55 | <div class="blog-views-ico"><?=$model->views?></div> | 57 | <div class="blog-views-ico"><?=$model->views?></div> |
| @@ -57,35 +59,32 @@ $imageHeight=240; | @@ -57,35 +59,32 @@ $imageHeight=240; | ||
| 57 | </div> | 59 | </div> |
| 58 | 60 | ||
| 59 | 61 | ||
| 60 | - | ||
| 61 | - | ||
| 62 | - | ||
| 63 | - | ||
| 64 | - | ||
| 65 | - <meta itemprop="headline" content="XXX"/> где ХХХ название статьи в H1 | 62 | + <meta itemprop="headline" content="XXX"/> <?= $model->title; ?> |
| 66 | 63 | ||
| 67 | <div itemprop="publisher" itemscope itemtype="https://schema.org/Organization"> | 64 | <div itemprop="publisher" itemscope itemtype="https://schema.org/Organization"> |
| 68 | 65 | ||
| 69 | 66 | ||
| 70 | - | ||
| 71 | - <meta itemprop="name" content="НАЗВАНИЕ САЙТА"> | 67 | + <meta itemprop="name" content="<?= \Yii::t('app', 'ABC short'); ?>"> |
| 68 | + <meta itemprop="logo" | ||
| 69 | + content="<?= 'https://as01.epimg.net/epik/imagenes/2018/03/10/portada/1520705351_010030_1520705450_noticia_normal.jpg'; ?>"> | ||
| 72 | 70 | ||
| 73 | </div> | 71 | </div> |
| 74 | 72 | ||
| 75 | <div itemprop="author" itemscope itemtype="https://schema.org/Person"> | 73 | <div itemprop="author" itemscope itemtype="https://schema.org/Person"> |
| 76 | 74 | ||
| 77 | - <meta itemprop="name" content="НАЗВАНИЕ САЙТА"/> | 75 | + <meta itemprop="name" content="<?= Url::home(true) ?>"/> |
| 78 | 76 | ||
| 79 | </div> | 77 | </div> |
| 80 | 78 | ||
| 81 | - <p itemprop="description">ОПИСАНИЕ</p> | 79 | + <p itemprop="description"><?= $model->body_preview; ?></p> |
| 82 | 80 | ||
| 83 | <div itemprop="image" itemscope itemtype="https://schema.org/ImageObject"> | 81 | <div itemprop="image" itemscope itemtype="https://schema.org/ImageObject"> |
| 84 | 82 | ||
| 85 | - <meta itemprop="url" content="КАРТИНКА"> | 83 | + <meta itemprop="url" |
| 84 | + content="<?= 'https://as01.epimg.net/epik/imagenes/2018/03/10/portada/1520705351_010030_1520705450_noticia_normal.jpg'; ?>"> | ||
| 86 | 85 | ||
| 87 | - <meta itemprop="height" content="675"/> | 86 | + <meta itemprop="height" content="<?= $imageHeight; ?>"/> |
| 88 | 87 | ||
| 89 | - <meta itemprop="width" content="900"/> | 88 | + <meta itemprop="width" content="<?= $imageWidth; ?>"/> |
| 90 | </div> | 89 | </div> |
| 91 | </div> | 90 | </div> |
| 92 | \ No newline at end of file | 91 | \ No newline at end of file |
frontend/views/blog/index.php
| @@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
| 6 | use yii\web\View; | 6 | use yii\web\View; |
| 7 | use yii\widgets\ActiveForm; | 7 | use yii\widgets\ActiveForm; |
| 8 | use yii\widgets\ListView; | 8 | use yii\widgets\ListView; |
| 9 | - | 9 | +use frontend\widgets\SeoLinks; |
| 10 | /** | 10 | /** |
| 11 | * @var View $this | 11 | * @var View $this |
| 12 | * @var ActiveDataProvider $dataProvider | 12 | * @var ActiveDataProvider $dataProvider |
| @@ -61,31 +61,43 @@ | @@ -61,31 +61,43 @@ | ||
| 61 | </div> | 61 | </div> |
| 62 | </div> | 62 | </div> |
| 63 | <div class="row blog-list-row"> | 63 | <div class="row blog-list-row"> |
| 64 | - <?= ListView::widget( | 64 | + <?= ListView::widget( |
| 65 | [ | 65 | [ |
| 66 | 'dataProvider' => $dataProvider, | 66 | 'dataProvider' => $dataProvider, |
| 67 | 'itemView' => '_article', | 67 | 'itemView' => '_article', |
| 68 | 'itemOptions' => [ | 68 | 'itemOptions' => [ |
| 69 | 'class' => 'col-xs-12 col-sm-4 col-md-4 blog-list-col', | 69 | 'class' => 'col-xs-12 col-sm-4 col-md-4 blog-list-col', |
| 70 | ], | 70 | ], |
| 71 | - 'layout' => '{items}{pager}', | 71 | + #'layout' => '{items}{pager}', |
| 72 | + 'layout' => '{items}', | ||
| 72 | ] | 73 | ] |
| 73 | ); ?> | 74 | ); ?> |
| 75 | + <?php | ||
| 76 | + #die(var_dump($dataProvider2)); | ||
| 77 | + | ||
| 78 | + ?> | ||
| 79 | + | ||
| 74 | 80 | ||
| 75 | <div class="col-xs-12 col-sm-12"> | 81 | <div class="col-xs-12 col-sm-12"> |
| 76 | <div class="style navi-c-a"> | 82 | <div class="style navi-c-a"> |
| 77 | - | ||
| 78 | - <?php echo \frontend\widgets\FrontendPager::widget( | ||
| 79 | - [ | ||
| 80 | - 'pagination' => $dataProvider->pagination, | ||
| 81 | - 'prevPageLabel' => 'previous', | ||
| 82 | - 'nextPageLabel' => 'next', | ||
| 83 | - 'maxButtonCount' => 5, | ||
| 84 | - 'lastPageLabel' => 'last_number', | ||
| 85 | - ] | ||
| 86 | - );?> | 83 | + |
| 84 | + <?php echo \frontend\widgets\FrontendPager::widget( | ||
| 85 | + [ | ||
| 86 | + 'pagination' => $dataProvider->pagination, | ||
| 87 | + 'prevPageLabel' => 'previous', | ||
| 88 | + 'nextPageLabel' => 'next', | ||
| 89 | + 'maxButtonCount' => 5, | ||
| 90 | + 'lastPageLabel' => 'last_number', | ||
| 91 | + ] | ||
| 92 | + ); ?> | ||
| 87 | </div> | 93 | </div> |
| 88 | </div> | 94 | </div> |
| 89 | </div> | 95 | </div> |
| 90 | </div> | 96 | </div> |
| 91 | -</section> | ||
| 92 | \ No newline at end of file | 97 | \ No newline at end of file |
| 98 | +</section> | ||
| 99 | +<?php SeoLinks::widget( | ||
| 100 | + [ | ||
| 101 | + 'pagination' => $dataProvider->pagination, | ||
| 102 | + 'seo' => $seo, | ||
| 103 | + ] | ||
| 104 | +) ?> | ||
| 93 | \ No newline at end of file | 105 | \ No newline at end of file |
frontend/views/layouts/main.php
| @@ -141,7 +141,7 @@ $this->registerMetaTag( | @@ -141,7 +141,7 @@ $this->registerMetaTag( | ||
| 141 | <!DOCTYPE html > | 141 | <!DOCTYPE html > |
| 142 | <html xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html" lang="<?= \Yii::$app->language ?>"> | 142 | <html xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html" lang="<?= \Yii::$app->language ?>"> |
| 143 | <head> | 143 | <head> |
| 144 | - | 144 | + |
| 145 | <script type="text/javascript"> | 145 | <script type="text/javascript"> |
| 146 | WebFontConfig = { | 146 | WebFontConfig = { |
| 147 | google: {families: [ 'Ubuntu:400,500,700' ]} | 147 | google: {families: [ 'Ubuntu:400,500,700' ]} |
| @@ -154,7 +154,7 @@ $this->registerMetaTag( | @@ -154,7 +154,7 @@ $this->registerMetaTag( | ||
| 154 | var s = document.getElementsByTagName('script')[ 0 ]; | 154 | var s = document.getElementsByTagName('script')[ 0 ]; |
| 155 | s.parentNode.insertBefore(wf, s); | 155 | s.parentNode.insertBefore(wf, s); |
| 156 | })(); </script> | 156 | })(); </script> |
| 157 | - | 157 | + |
| 158 | <script> | 158 | <script> |
| 159 | 159 | ||
| 160 | <!-- Global site tag (gtag.js) - Google Analytics --> | 160 | <!-- Global site tag (gtag.js) - Google Analytics --> |
| @@ -307,7 +307,7 @@ $this->registerMetaTag( | @@ -307,7 +307,7 @@ $this->registerMetaTag( | ||
| 307 | 'url' => Url::to(['package/index']), | 307 | 'url' => Url::to(['package/index']), |
| 308 | ]; | 308 | ]; |
| 309 | 309 | ||
| 310 | - | 310 | + |
| 311 | 311 | ||
| 312 | 312 | ||
| 313 | ?> | 313 | ?> |
| @@ -646,10 +646,11 @@ $this->registerMetaTag( | @@ -646,10 +646,11 @@ $this->registerMetaTag( | ||
| 646 | ], | 646 | ], |
| 647 | 647 | ||
| 648 | ]; | 648 | ]; |
| 649 | - if(isset($phones) && !empty($phones)){foreach ($phones as $key =>$phone) | ||
| 650 | - { | ||
| 651 | - $layoutMicrodata['contactPoint']['telephone'.$key]=$phone; | ||
| 652 | - }} | 649 | + |
| 650 | + if(isset($phones[0])) { | ||
| 651 | + $layoutMicrodata['contactPoint']['telephone'] = "+38" . $phones[0]; | ||
| 652 | + } | ||
| 653 | + | ||
| 653 | 654 | ||
| 654 | 655 | ||
| 655 | $settings->email; | 656 | $settings->email; |
frontend/widgets/FrontendPager.php
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | use function key_exists; | 5 | use function key_exists; |
| 6 | use yii\helpers\ArrayHelper; | 6 | use yii\helpers\ArrayHelper; |
| 7 | use yii\helpers\Html; | 7 | use yii\helpers\Html; |
| 8 | - | 8 | + use common\components\Substringer; |
| 9 | /** | 9 | /** |
| 10 | * Class FrontendPager | 10 | * Class FrontendPager |
| 11 | * | 11 | * |
| @@ -128,20 +128,33 @@ | @@ -128,20 +128,33 @@ | ||
| 128 | /** | 128 | /** |
| 129 | * @var \artbox\catalog\models\Filter $filter | 129 | * @var \artbox\catalog\models\Filter $filter |
| 130 | */ | 130 | */ |
| 131 | - $filter = \Yii::$app->get('filter')->filterObj; | ||
| 132 | - if (key_exists($link, $filter->getReplacedFilters())) { | ||
| 133 | - $link = $filter->getReplacedFilters()[ $link ]; | ||
| 134 | - } | 131 | +// $filter = \Yii::$app->get('filter')->filterObj; |
| 132 | +// if (key_exists($link, $filter->getReplacedFilters())) { | ||
| 133 | +// $link = $filter->getReplacedFilters()[ $link ]; | ||
| 134 | +// } | ||
| 135 | return Html::tag( | 135 | return Html::tag( |
| 136 | 'li', | 136 | 'li', |
| 137 | Html::a($label, $link, $linkOptions), | 137 | Html::a($label, $link, $linkOptions), |
| 138 | $options | 138 | $options |
| 139 | ); | 139 | ); |
| 140 | } | 140 | } |
| 141 | - if ($active) { | 141 | + |
| 142 | + | ||
| 143 | + if ($active) { | ||
| 142 | return Html::tag('li', Html::a($label, null, $linkOptions), $options); | 144 | return Html::tag('li', Html::a($label, null, $linkOptions), $options); |
| 143 | } else { | 145 | } else { |
| 144 | - return Html::tag('li', Html::a($label, $this->pagination->createUrl($page), $linkOptions), $options); | 146 | + # убираю весь мусор кроме прямой пагинации с ссылок |
| 147 | + $haystack = $this->pagination->createUrl($page); | ||
| 148 | + | ||
| 149 | + $regex1 = '/(\??|&?)page=\d{1,5}&per-page=\d{1,5}/'; | ||
| 150 | + $regex2 = '/(\?|&)sort=[a-zA-z_]+/'; | ||
| 151 | + $requiredDelimiter = '?'; | ||
| 152 | + $firstConcatenateSymbol = '?'; | ||
| 153 | + $secondConcatenateSymbol = '?'; | ||
| 154 | + $res = Substringer::changeStringByRegex($haystack, $regex1, $regex2, $firstConcatenateSymbol, $secondConcatenateSymbol, $requiredDelimiter); | ||
| 155 | + | ||
| 156 | + return Html::tag('li', Html::a($label, $res, $linkOptions), $options); | ||
| 157 | + #return Html::tag('li', Html::a($label, $this->pagination->createUrl($page), $linkOptions), $options); | ||
| 145 | } | 158 | } |
| 146 | 159 | ||
| 147 | } | 160 | } |
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * ====================================================================================================================| | ||
| 4 | + * @author artbox Khonko Alex | ||
| 5 | + * Виджет, полностью копирует \artbox\artbox-core\widgets\SeoWidget | ||
| 6 | + * Примечание: | ||
| 7 | + * Я не смог чисто унаследовать виджет, потому что в основу его ложится родительский вариант | ||
| 8 | + * SeoWidget::run -> parent::run | ||
| 9 | + * При наследовании у меня выдавалось по 2 одинаковых link prev/link next | ||
| 10 | + * Поэтому ядро виджета я вернул в исходное состояние, поменял use во всех местах на свой, мой является | ||
| 11 | + * как минимум на 50% дописанным/переписанным вариантом для линии | ||
| 12 | + * ====================================================================================================================| | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +namespace frontend\widgets; | ||
| 16 | + | ||
| 17 | +use Yii; | ||
| 18 | +use common\components\Substringer; | ||
| 19 | +use yii\helpers\Url; | ||
| 20 | +use yii\base\Widget; | ||
| 21 | +use yii\data\Pagination; | ||
| 22 | +use yii\helpers\VarDumper as d; | ||
| 23 | + | ||
| 24 | +class SeoLinks extends Widget | ||
| 25 | +{ | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * @var null | Pagination | ||
| 29 | + * @var null | \common\components\SeoComponent | ||
| 30 | + */ | ||
| 31 | + public $pagination = null; | ||
| 32 | + | ||
| 33 | + public $canonical = true; | ||
| 34 | + | ||
| 35 | + public $firstpageWithoutParameter = false; | ||
| 36 | + | ||
| 37 | + public $seo = null; | ||
| 38 | + /** | ||
| 39 | + * @inheritdoc | ||
| 40 | + */ | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * ============================================================================================================| | ||
| 44 | + * Правка от Саши | ||
| 45 | + * 1) Если есть параметры в урле, Canonical должен вести на страницу без параметров, | ||
| 46 | + * за исключением Пагинации и сортировки. И next/prev чтобы были без этих параметров | ||
| 47 | + * Пример страницы | ||
| 48 | + * https://www.linija-svitla.ua/catalog/ulichnoe-osveshchenie?page_num=3&fcatlist=3268%2C&sort=test_test&3269%2C3270%2C3272%2C3273%2C3274%2C3275&page=50&per-page=18 | ||
| 49 | + * ************************************************************************************************************ | ||
| 50 | + * 2) link prev со 2й страницы должен ссылатся на первую, НО , | ||
| 51 | + * a) там должна отсутствовать пагинация б) должна остатся сортировка | ||
| 52 | + * Прим | ||
| 53 | + * Было https://www.linija-svitla.ua/catalog/ulichnoe-osveshchenie?page=1&per=page=18&sort=title_asc | ||
| 54 | + * Стало https://www.linija-svitla.ua/catalog/ulichnoe-osveshchenie?sort=title_asc | ||
| 55 | + * ============================================================================================================| | ||
| 56 | + * 3) При 301 редирректе от НеЧПУ продуктам/фильтрам к ЧПУ, теги prev/next ссылаются на старые НеЧПУ | ||
| 57 | + * страницы | ||
| 58 | + * ============================================================================================================| | ||
| 59 | + */ | ||
| 60 | + public function run() | ||
| 61 | + { | ||
| 62 | + | ||
| 63 | + # 0 изменяем ссылку, оставляя в ней только пагинацию и сортировку | ||
| 64 | + $firstRegex = '/(\??|&?)page=\d{1,5}&per-page=\d{1,5}/'; | ||
| 65 | + $secondRegex = '/(\?|&)sort=[a-zA-z_]+/'; | ||
| 66 | + $requiredDelimiter = '?'; | ||
| 67 | + $firstConcatenateSymbol = '?'; | ||
| 68 | + $secondConcatenateSymbol = '&'; | ||
| 69 | + | ||
| 70 | + $links = $this->pagination->getLinks(); | ||
| 71 | + | ||
| 72 | + if ($this->canonical and ($this->seo->getRobots() != 'noindex,nofollow' and $this->seo->getRobots() != 'noindex,follow' and $this->seo->getRobots() != 'noindex, nofollow' and $this->seo->getRobots() != 'noindex, follow') | ||
| 73 | + ) { | ||
| 74 | + # 0 | ||
| 75 | + $cannonicalLink = Substringer::changeStringByRegex( | ||
| 76 | + Yii::$app->request->getAbsoluteUrl(), | ||
| 77 | + $firstRegex, | ||
| 78 | + $secondRegex, | ||
| 79 | + $requiredDelimiter, | ||
| 80 | + $firstConcatenateSymbol, | ||
| 81 | + $secondConcatenateSymbol | ||
| 82 | + ); | ||
| 83 | + # 1 В канониклах должна присутствовать только пагинация, удаляю всё, что не есть пагинацией | ||
| 84 | + if ((strpos($cannonicalLink, '?page'))) { | ||
| 85 | + $cannonicalLink = Substringer::simpleStringSubstring($cannonicalLink, '&sort'); | ||
| 86 | + } else { | ||
| 87 | + $cannonicalLink = Substringer::changeStringByRegex( | ||
| 88 | + Yii::$app->request->getAbsoluteUrl(), | ||
| 89 | + $firstRegex, | ||
| 90 | + $secondRegex, | ||
| 91 | + $requiredDelimiter, | ||
| 92 | + $firstConcatenateSymbol, | ||
| 93 | + $secondConcatenateSymbol | ||
| 94 | + ); | ||
| 95 | + $cannonicalLink = Substringer::simpleStringSubstring($cannonicalLink, '&sort'); | ||
| 96 | + /** | ||
| 97 | + * Сейчас ссылка имеет вид: www.siteName.com?page=X&per-page=X | ||
| 98 | + */ | ||
| 99 | + | ||
| 100 | + # 1.1 Если в результате у нас остается URL вида www.siteName.com? | ||
| 101 | + # обрезаем этот ? | ||
| 102 | + if (strpos($cannonicalLink, '?') && !strpos($cannonicalLink, '?page')) { | ||
| 103 | + $cannonicalLink = stristr($cannonicalLink, '?', true); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + # 1.2 если ссылка содержит в себе пагинацию, НО она по каким-то причинам не первая, | ||
| 107 | + # удаляем все GET параметры до неё, и заменяем & на ? | ||
| 108 | + if (strpos($cannonicalLink, '?page') !== false) { | ||
| 109 | + $cannonicalLinkRigth = stristr($cannonicalLink, '&page'); | ||
| 110 | + $cannonicalLinkRigth = substr($cannonicalLinkRigth, 1); | ||
| 111 | + $cannonicalLinkRigth = '?' . $cannonicalLinkRigth; | ||
| 112 | + | ||
| 113 | + $cannonicalLink = stristr($cannonicalLink, '?', true); | ||
| 114 | + $cannonicalLink .= $cannonicalLinkRigth; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + } | ||
| 118 | + # если нашем очищенном каноникле есть ? в конце(www.siteName.com?page=X&per-page=X?), убираем его | ||
| 119 | + $cannonicalLink = ($cannonicalLink[strlen($cannonicalLink) - 1] !== '?') ? $cannonicalLink : rtrim( | ||
| 120 | + $cannonicalLink, | ||
| 121 | + '?' | ||
| 122 | + ); | ||
| 123 | + | ||
| 124 | + # 1.3 в каноникле должна сохранятся очередность нужных GET параметров | ||
| 125 | + # берём финальную ссылку и если нужно, перерисовываем её | ||
| 126 | + $seoCuttedLink = $this->changeLinksToRequestView($cannonicalLink, Yii::$app->request->getAbsoluteUrl()); | ||
| 127 | + $this->view->registerLinkTag( | ||
| 128 | + [ | ||
| 129 | + 'rel' => 'canonical', | ||
| 130 | + 'href' => $cannonicalLink, | ||
| 131 | + ] | ||
| 132 | + ); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + /** | ||
| 136 | + * ========================================================================================================= | ||
| 137 | + * То же самое для тега next | ||
| 138 | + * ========================================================================================================= | ||
| 139 | + */ | ||
| 140 | + | ||
| 141 | + if (key_exists('next', $links)) { | ||
| 142 | + #2.1 Обрезаем ссылку справа по заданным GET regexp-ам | ||
| 143 | + $nextPageGetQueryString = stristr( | ||
| 144 | + Substringer::changeStringByRegex( | ||
| 145 | + $links['next'], | ||
| 146 | + $firstRegex, | ||
| 147 | + $secondRegex, | ||
| 148 | + $requiredDelimiter, | ||
| 149 | + $firstConcatenateSymbol, | ||
| 150 | + $secondConcatenateSymbol | ||
| 151 | + ), | ||
| 152 | + '?' | ||
| 153 | + ); | ||
| 154 | + # 2.2 сливаем левую и правую часть | ||
| 155 | + $nextLinkTitle = Substringer::simpleStringSubstring( | ||
| 156 | + Yii::$app->request->url, | ||
| 157 | + '?' | ||
| 158 | + ) . $nextPageGetQueryString; | ||
| 159 | + | ||
| 160 | + # 2.3 перестраиваем сслыку согласно входящему стилю | ||
| 161 | + $nextLinkTitle = $this->changeLinksToRequestView($nextLinkTitle, Yii::$app->request->url); | ||
| 162 | + | ||
| 163 | + $this->view->registerLinkTag( | ||
| 164 | + [ | ||
| 165 | + 'rel' => 'next', | ||
| 166 | + 'href' => $nextLinkTitle, | ||
| 167 | + ] | ||
| 168 | + ); | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + if ($this->firstpageWithoutParameter and $this->pagination->page == 1) { | ||
| 172 | + if (key_exists('prev', $links)) { | ||
| 173 | + $link = stristr(\Yii::$app->request->url, '?', true); | ||
| 174 | + /** | ||
| 175 | + * @var \artbox\catalog\models\Filter $filter | ||
| 176 | + */ | ||
| 177 | + $filter = \Yii::$app->get('filter')->filterObj; | ||
| 178 | + if (key_exists($link, $filter->getReplacedFilters())) { | ||
| 179 | + $link = $filter->getReplacedFilters()[$link]; | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + $seoCuttedLink = $this->changeLinksToRequestView($link, Yii::$app->request->url); | ||
| 183 | + $this->view->registerLinkTag( | ||
| 184 | + [ | ||
| 185 | + 'rel' => 'prev', | ||
| 186 | + 'href' => $seoCuttedLink, | ||
| 187 | + | ||
| 188 | + ] | ||
| 189 | + ); | ||
| 190 | + } | ||
| 191 | + } else { | ||
| 192 | + if (key_exists('prev', $links)) { | ||
| 193 | + | ||
| 194 | + # правка 3 Я не ломаю старых наработок, а просто прокидываю новый(если был редирект) URL prev для | ||
| 195 | + // предыдущих правок | ||
| 196 | + $prevPageGetQueryString = stristr( | ||
| 197 | + Substringer::changeStringByRegex( | ||
| 198 | + $links['prev'], | ||
| 199 | + $firstRegex, | ||
| 200 | + $secondRegex, | ||
| 201 | + $requiredDelimiter, | ||
| 202 | + $firstConcatenateSymbol, | ||
| 203 | + $secondConcatenateSymbol | ||
| 204 | + ), | ||
| 205 | + '?' | ||
| 206 | + ); | ||
| 207 | + $prevLinkTitle = Substringer::simpleStringSubstring( | ||
| 208 | + Yii::$app->request->url, | ||
| 209 | + '?' | ||
| 210 | + ) . $prevPageGetQueryString; | ||
| 211 | + # правка 2 | ||
| 212 | + $seoStringStart = $prevLinkTitle; | ||
| 213 | + $seoCuttedLink = $seoStringStart; | ||
| 214 | + $seoCuttedLink = Substringer::changeStringByRegex( | ||
| 215 | + $seoCuttedLink, | ||
| 216 | + $firstRegex, | ||
| 217 | + $secondRegex, | ||
| 218 | + $requiredDelimiter, | ||
| 219 | + $firstConcatenateSymbol, | ||
| 220 | + $secondConcatenateSymbol | ||
| 221 | + ); | ||
| 222 | + | ||
| 223 | + if (strpos($seoStringStart, '?page=1')) { | ||
| 224 | + | ||
| 225 | + /** | ||
| 226 | + * Правка для категории/блога | ||
| 227 | + * У них разное к-во страниц, поэтому на замену конкретной срезки URL(?page=1&per-page=18) как было раньше, | ||
| 228 | + * я буду автоматически пересматривать currentPageSizeParam для странички | ||
| 229 | + */ | ||
| 230 | + $perPageParam = false; | ||
| 231 | + | ||
| 232 | + # если в $seoCuttredLink уже есть пагинация, то паршу строку и достаю реальное к-во записей для страницы | ||
| 233 | + if (strpos($seoCuttedLink, 'per-page')) { | ||
| 234 | + $perPageParam = parse_str($seoCuttedLink, $params); | ||
| 235 | + $perPageParam = (isset ($params['per-page'])) ? $params['per-page'] : false; | ||
| 236 | + } | ||
| 237 | + # или же ставлю размер как в frontend/views/category, | ||
| 238 | + # потому что большая часть кода здесь заточена именно под currentPerPageSizeParam=18 | ||
| 239 | + $perPageParam = ($perPageParam === false) ? 18 : $perPageParam; | ||
| 240 | + $seoCuttedLink = str_replace('?page=1&per-page=' . $perPageParam, '?', $seoCuttedLink); | ||
| 241 | + $seoCuttedLink = str_replace('&', '', $seoCuttedLink); | ||
| 242 | + $strlen = mb_strlen($seoCuttedLink); | ||
| 243 | + if ($seoCuttedLink[$strlen - 1] == '?') { | ||
| 244 | + $seoCuttedLink = str_replace('?', '', $seoCuttedLink); | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + } else { | ||
| 248 | + $seoCuttedLink = $seoStringStart; | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + # правка 2 | ||
| 252 | + | ||
| 253 | + if (strpos($seoCuttedLink, '?sort')) { | ||
| 254 | + if (strpos($seoCuttedLink, '&page=1')) { | ||
| 255 | + $seoCuttedLink = Substringer::simpleStringSubstring($seoCuttedLink, '&page=1&per-page'); | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + $seoCuttedLink = Substringer::changeStringByRegex( | ||
| 261 | + $seoCuttedLink, | ||
| 262 | + $firstRegex, | ||
| 263 | + $secondRegex, | ||
| 264 | + $requiredDelimiter, | ||
| 265 | + $firstConcatenateSymbol, | ||
| 266 | + $secondConcatenateSymbol | ||
| 267 | + ); | ||
| 268 | + # поправляем URL выдачи, если он после всего имеет такой вид: <link href="/catName/subCatName?page=Xper-page=Xsort=param1_val1" rel="prev"> | ||
| 269 | + if (preg_match('/\d+sort=/', $seoCuttedLink) != false) { | ||
| 270 | + $seoCuttedLinkRigth = stristr($seoCuttedLink, 'sort='); | ||
| 271 | + $seoCuttedLink = stristr($seoCuttedLink, 'sort=', true) . '&' . $seoCuttedLinkRigth; | ||
| 272 | + } | ||
| 273 | + # то же самое, если в пагинации URL пропущен & ==> www.site.com?page=Xper-page=X | ||
| 274 | + if (preg_match('/\d+per-page=/', $seoCuttedLink) != false) { | ||
| 275 | + $seoCuttedLinkRigth = stristr($seoCuttedLink, 'per-page='); | ||
| 276 | + $seoCuttedLink = stristr($seoCuttedLink, 'per-page=', true) . '&' . $seoCuttedLinkRigth; | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + $seoCuttedLink = $this->changeLinksToRequestView($seoCuttedLink, Yii::$app->request->url); | ||
| 280 | + | ||
| 281 | + $this->view->registerLinkTag( | ||
| 282 | + [ | ||
| 283 | + 'rel' => 'prev', | ||
| 284 | + 'href' => $seoCuttedLink, | ||
| 285 | + ] | ||
| 286 | + ); | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + parent::run(); | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + /** | ||
| 294 | + * @param string $link | ||
| 295 | + * @param string $requestUrl | ||
| 296 | + * ========================================================================================================= | ||
| 297 | + * Метод, который берет строку(URL), и преобразовывает его в вид, в котором он поступал. Написан для тегов | ||
| 298 | + * next/prev/cannonical | ||
| 299 | + * ========================================================================================================= | ||
| 300 | + * К нам приходит сюда(в данный виджет) URL, из которого нужно сформировать данные 3 линка. По всем Саниным | ||
| 301 | + * правкам, они должны быть в одном из форматов: | ||
| 302 | + * + новенькийЧпу?page=X&per-page=X&sort=param_val | ||
| 303 | + * + новенькийЧпу?sort=param_val&page=X&per-page=X | ||
| 304 | + * Метод берет текущий URL, смотрит какая из 2 вариаций пришла, и не меняя уже написанной логики | ||
| 305 | + * возвращает обработанную конечтную строку,идентичную входящей | ||
| 306 | + *Если в текущем URL отсутствует погинация, НО присутствует сортировка, | ||
| 307 | + * делает ссылку типа www.siteName.com?sort=var_param&page=X&per-page=X | ||
| 308 | + * ========================================================================================================= | ||
| 309 | + * | ||
| 310 | + * @return string | ||
| 311 | + */ | ||
| 312 | + private function changeLinksToRequestView(string $link, string $requestUrl) | ||
| 313 | + { | ||
| 314 | + $positionSort = (strpos($requestUrl, 'sort=') !== false) ? strpos($requestUrl, 'sort=') : 0; | ||
| 315 | + $positionPagination = (strpos($requestUrl, 'page=') !== false) ? strpos($requestUrl, 'page=') : 0; | ||
| 316 | + | ||
| 317 | + $regex1 = '/(\??|&?)page=\d{1,5}&per-page=\d{1,5}/'; | ||
| 318 | + $regex2 = '/(\??|&)sort=[a-zA-z_]+&?/'; | ||
| 319 | + | ||
| 320 | + /* | ||
| 321 | + * У нас 5 вариантов: | ||
| 322 | + * sort>page ===> пагинация идёт первой | ||
| 323 | + * sort<page ===> перввая сортировка | ||
| 324 | + * !sort | ||
| 325 | + * !page | ||
| 326 | + * !sort !page | ||
| 327 | + */ | ||
| 328 | + $option = $positionSort - $positionPagination; | ||
| 329 | + if ($option > 0 && $positionPagination != 0)// первая пагинация | ||
| 330 | + { | ||
| 331 | + $link = Substringer::changeStringByRegex($link, $regex1, $regex2, '?', '?', '&'); | ||
| 332 | + } elseif ($option > 0 && $positionPagination == 0)//есть сортировка, но нету пагинации | ||
| 333 | + { | ||
| 334 | + $link = Substringer::changeStringByRegex($link, $regex2, $regex1, '?', '?', '&'); | ||
| 335 | + } elseif ($option < 0)// page>sort | ||
| 336 | + { | ||
| 337 | + $link = Substringer::changeStringByRegex($link, $regex2, $regex1, '?', '?', '&'); | ||
| 338 | + } else // нету ни сортировки, ни пагинации | ||
| 339 | + { | ||
| 340 | + $link = Substringer::changeStringByRegex($link, $regex2, $regex1, '?', '?', '&'); | ||
| 341 | + } | ||
| 342 | + $result = $link; | ||
| 343 | + return $result; | ||
| 344 | + } | ||
| 345 | +} | ||
| 346 | + |