Commit 622f41fdfed151bacb63f30e90673fbd7f84a08f

Authored by Anastasia
2 parents 7f892874 4fcaa96c

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	frontend/controllers/ServiceController.php
common/components/Substringer.php 0 → 100644
  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 153 \ No newline at end of file
... ...
frontend/controllers/BlogController.php
... ... @@ -10,7 +10,8 @@
10 10 use yii\helpers\ArrayHelper;
11 11 use yii\web\Controller;
12 12 use yii\web\NotFoundHttpException;
13   -
  13 +
  14 +
14 15 /**
15 16 * Class BlogController
16 17 *
... ... @@ -52,15 +53,17 @@
52 53 ->distinct(),
53 54 'pagination' => [
54 55 'pageSize' => 6,
  56 +
55 57 ],
56 58 ]
57 59 );
58   -
59   - return $this->render(
  60 +
  61 + return $this->render(
60 62 'index',
61 63 [
62 64 'categories' => $data,
63 65 'dataProvider' => $dataProvider,
  66 +
64 67 ]
65 68 );
66 69 }
... ...
frontend/controllers/ServiceController.php
... ... @@ -84,44 +84,45 @@
84 84 }
85 85  
86 86 }
87   -
88   - $layoutMicrodata = ( count($model->prices) > 1 ) ? [
89   - '@context' => 'http://schema.org/',
90   - '@type' => 'Product',
91   - 'name' => "'{$model->language->attributes['title']}'",
92   - 'offers' => [
93   - '@type' => 'AggregateOffer',
94   - 'lowPrice' => "'" . min($prices) . "'",
95   - 'highPrice' => "'" . max($prices) . "'",
96   - 'priceCurrency' => 'UAH',
97   - ],
98   - ] : [
99   - 'type' => 'Product',
100   - 'name' => "'{$model->language->attributes['title']}'",
101   - 'offers' => [
102   - '@type' => 'Offer',
103   - 'priceCurrency' => 'UAH',
104   - 'Price' => "'" . max($prices) . "'",
105   - ],
106   - ];
107   -
108   - $microdata = new MicrodataFabric();
109   - $pageMicrodata = $microdata::createJsonFromProduct($layoutMicrodata)
110   - ->toJson();
111   -
112   - $model->body = str_replace(
113   - '[[prices]]',
114   - $this->renderPartial('_prices', [ 'prices' => $model->prices ]),
115   - $model->body
116   - );
117   - return $this->render(
118   - 'view',
  87 +
  88 + $layoutMicrodata=(count($model->prices)>1)?
119 89 [
120   - 'model' => $model,
121   - 'others' => $others,
122   - 'microdata' => $pageMicrodata,
  90 + 'context' => 'http://schema.org/',
  91 + 'type' => 'Product',
  92 + 'name'=> "'{$model->language->attributes['title']}'",
  93 + 'offers' =>
  94 + [
  95 + '@type'=> 'AggregateOffer',
  96 + 'lowPrice'=> "'".min($prices)."'",
  97 + 'highPrice'=> "'".max($prices)."'",
  98 + 'priceCurrency'=> 'UAH'
  99 + ]
123 100 ]
124   - );
  101 + :[
  102 + 'type'=>'Product',
  103 + 'name'=> "'{$model->language->attributes['title']}'",
  104 + 'offers'=> [
  105 + '@type'=> 'Offer',
  106 + 'priceCurrency'=> 'UAH',
  107 +
  108 + ]
  109 + ];
  110 + if (count($model->prices) <= 1 && isset($prices)) {
  111 + if (!empty($prices)) $layoutMicrodata['offers']['Price'] = "'" . max($prices) . "'";
  112 + }
  113 +
  114 +
  115 + $microdata=new MicrodataFabric();
  116 + $pageMicrodata=$microdata::createJsonFromProduct($layoutMicrodata)->toJson();
  117 +
  118 +
  119 +
  120 + $model->body = str_replace('[[prices]]', $this->renderPartial('_prices', ['prices' => $model->prices]), $model->body);
  121 + return $this->render('view', [
  122 + 'model' => $model,
  123 + 'others'=> $others,
  124 + 'microdata'=>$pageMicrodata
  125 + ]);
125 126 }
126 127  
127 128 public function findModel($id)
... ...
frontend/microdata/ProductMicrodata.php
... ... @@ -13,6 +13,7 @@ class ProductMicrodata extends Microdata
13 13 public $offers=null;
14 14 public $description=null;
15 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 27  
28 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 32 <meta itemprop="url" content="<?=($model->image) ? $model->image->getPath() : null;?>">
33 33 <meta itemprop="height" content="<?=$imageWidth;?>"/>
... ... @@ -48,8 +48,10 @@ $imageHeight=240;
48 48 </div>
49 49  
50 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 55 <div class="blog-views-comments-ico">
54 56 <div class="blog-comments-ico"><?=count($model->comments)?></div>
55 57 <div class="blog-views-ico"><?=$model->views?></div>
... ... @@ -57,35 +59,32 @@ $imageHeight=240;
57 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 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 71 </div>
74 72  
75 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 77 </div>
80 78  
81   - <p itemprop="description">ОПИСАНИЕ</p>
  79 + <p itemprop="description"><?= $model->body_preview; ?></p>
82 80  
83 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 89 </div>
91 90 </div>
92 91 \ No newline at end of file
... ...
frontend/views/blog/index.php
... ... @@ -6,7 +6,7 @@
6 6 use yii\web\View;
7 7 use yii\widgets\ActiveForm;
8 8 use yii\widgets\ListView;
9   -
  9 +use frontend\widgets\SeoLinks;
10 10 /**
11 11 * @var View $this
12 12 * @var ActiveDataProvider $dataProvider
... ... @@ -61,31 +61,43 @@
61 61 </div>
62 62 </div>
63 63 <div class="row blog-list-row">
64   - <?= ListView::widget(
  64 + <?= ListView::widget(
65 65 [
66 66 'dataProvider' => $dataProvider,
67 67 'itemView' => '_article',
68 68 'itemOptions' => [
69 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 81 <div class="col-xs-12 col-sm-12">
76 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 93 </div>
88 94 </div>
89 95 </div>
90 96 </div>
91   -</section>
92 97 \ No newline at end of file
  98 +</section>
  99 +<?php SeoLinks::widget(
  100 + [
  101 + 'pagination' => $dataProvider->pagination,
  102 + 'seo' => $seo,
  103 + ]
  104 +) ?>
93 105 \ No newline at end of file
... ...
frontend/views/layouts/main.php
... ... @@ -141,7 +141,7 @@ $this-&gt;registerMetaTag(
141 141 <!DOCTYPE html >
142 142 <html xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html" lang="<?= \Yii::$app->language ?>">
143 143 <head>
144   -
  144 +
145 145 <script type="text/javascript">
146 146 WebFontConfig = {
147 147 google: {families: [ 'Ubuntu:400,500,700' ]}
... ... @@ -154,7 +154,7 @@ $this-&gt;registerMetaTag(
154 154 var s = document.getElementsByTagName('script')[ 0 ];
155 155 s.parentNode.insertBefore(wf, s);
156 156 })(); </script>
157   -
  157 +
158 158 <script>
159 159  
160 160 <!-- Global site tag (gtag.js) - Google Analytics -->
... ... @@ -307,7 +307,7 @@ $this-&gt;registerMetaTag(
307 307 'url' => Url::to(['package/index']),
308 308 ];
309 309  
310   -
  310 +
311 311  
312 312  
313 313 ?>
... ... @@ -646,10 +646,11 @@ $this-&gt;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 656 $settings->email;
... ...
frontend/views/site/index.php
... ... @@ -98,8 +98,9 @@ JS;
98 98 <!--263x146px-->
99 99 <?=ImageHelper::set($service->image->getPath())
100 100 ->cropResize(263, 146)
101   - ->quality(82)
102   - ->renderImage()?>
  101 + ->quality(84)
  102 + ->renderImage(['alt'=>ucfirst($service->title).' - Консультация врача и лечение заболеваний',
  103 + 'title'=>ucfirst($service->title).' - Консультация врача и лечение заболеваний'])?>
103 104 </div>
104 105 <div class="style categories-home-links-wr">
105 106 <div class="style categories-home-links-title">
... ...
frontend/widgets/FrontendPager.php
... ... @@ -5,7 +5,7 @@
5 5 use function key_exists;
6 6 use yii\helpers\ArrayHelper;
7 7 use yii\helpers\Html;
8   -
  8 + use common\components\Substringer;
9 9 /**
10 10 * Class FrontendPager
11 11 *
... ... @@ -128,20 +128,33 @@
128 128 /**
129 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 135 return Html::tag(
136 136 'li',
137 137 Html::a($label, $link, $linkOptions),
138 138 $options
139 139 );
140 140 }
141   - if ($active) {
  141 +
  142 +
  143 + if ($active) {
142 144 return Html::tag('li', Html::a($label, null, $linkOptions), $options);
143 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 }
... ...
frontend/widgets/SeoLinks.php 0 → 100644
  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 +
... ...