1515use skeeks \cms \helpers \StringHelper ;
1616use skeeks \cms \seo \assets \CmsSeoAsset ;
1717use skeeks \cms \seo \vendor \CanUrl ;
18+ use skeeks \yii2 \form \elements \HtmlColBegin ;
19+ use skeeks \yii2 \form \elements \HtmlColEnd ;
20+ use skeeks \yii2 \form \elements \HtmlRowBegin ;
21+ use skeeks \yii2 \form \elements \HtmlRowEnd ;
1822use skeeks \yii2 \form \fields \BoolField ;
1923use skeeks \yii2 \form \fields \FieldSet ;
2024use skeeks \yii2 \form \fields \HtmlBlock ;
3034use yii \grid \GridView ;
3135use yii \helpers \ArrayHelper ;
3236use yii \helpers \Html ;
37+ use yii \helpers \Json ;
3338use yii \helpers \Url ;
3439use yii \web \Application ;
3540use yii \web \Controller ;
@@ -107,6 +112,27 @@ class CmsSeoComponent extends Component implements BootstrapInterface
107112 */
108113 public $ is_webp = 0 ;
109114
115+ /**
116+ * @var int Выводить микроразметку событий?
117+ */
118+ public $ is_sale_event = 1 ;
119+
120+ public $ sale_event_1_name = "" ;
121+ public $ sale_event_1_description = "" ;
122+ public $ sale_event_1_streetAddress = "" ;
123+ public $ sale_event_1_addressLocality = "" ;
124+
125+ public $ sale_event_2_name = "" ;
126+ public $ sale_event_2_description = "" ;
127+ public $ sale_event_2_streetAddress = "" ;
128+ public $ sale_event_2_addressLocality = "" ;
129+
130+ public $ sale_event_3_name = "" ;
131+ public $ sale_event_3_description = "" ;
132+ public $ sale_event_3_streetAddress = "" ;
133+ public $ sale_event_3_addressLocality = "" ;
134+
135+
110136 /**
111137 * @var int
112138 */
@@ -229,7 +255,23 @@ public function rules()
229255 ['sitemap_min_date ' , 'integer ' ],
230256 ['title_append ' , 'string ' ],
231257 ['is_webp ' , 'integer ' ],
258+ ['is_sale_event ' , 'integer ' ],
232259 ['is_mobile_webp ' , 'integer ' ],
260+
261+ ['sale_event_1_name ' , 'string ' ],
262+ ['sale_event_1_description ' , 'string ' ],
263+ ['sale_event_1_streetAddress ' , 'string ' ],
264+ ['sale_event_1_addressLocality ' , 'string ' ],
265+
266+ ['sale_event_2_name ' , 'string ' ],
267+ ['sale_event_2_description ' , 'string ' ],
268+ ['sale_event_2_streetAddress ' , 'string ' ],
269+ ['sale_event_2_addressLocality ' , 'string ' ],
270+
271+ ['sale_event_3_name ' , 'string ' ],
272+ ['sale_event_3_description ' , 'string ' ],
273+ ['sale_event_3_streetAddress ' , 'string ' ],
274+ ['sale_event_3_addressLocality ' , 'string ' ],
233275 ]);
234276 }
235277
@@ -250,6 +292,25 @@ public function attributeLabels()
250292 'sitemap_min_date ' => \Yii::t ('skeeks/seo ' , 'Минимальная дата обновления ссылки ' ),
251293 'treeTypeIds ' => \Yii::t ('skeeks/seo ' , 'Types of tree ' ),
252294 'is_webp ' => \Yii::t ('skeeks/seo ' , 'Использовать .webp сжатие картинок? ' ),
295+
296+ 'is_sale_event ' => \Yii::t ('skeeks/seo ' , 'Включить микроразметку событий? ' ),
297+
298+ 'sale_event_1_name ' => \Yii::t ('skeeks/seo ' , 'Название ' ),
299+ 'sale_event_1_description ' => \Yii::t ('skeeks/seo ' , 'Описание ' ),
300+ 'sale_event_1_streetAddress ' => \Yii::t ('skeeks/seo ' , 'Адрес ' ),
301+ 'sale_event_1_addressLocality ' => \Yii::t ('skeeks/seo ' , 'Город ' ),
302+
303+
304+ 'sale_event_2_name ' => \Yii::t ('skeeks/seo ' , 'Название ' ),
305+ 'sale_event_2_description ' => \Yii::t ('skeeks/seo ' , 'Описание ' ),
306+ 'sale_event_2_streetAddress ' => \Yii::t ('skeeks/seo ' , 'Адрес ' ),
307+ 'sale_event_2_addressLocality ' => \Yii::t ('skeeks/seo ' , 'Город ' ),
308+
309+ 'sale_event_3_name ' => \Yii::t ('skeeks/seo ' , 'Название ' ),
310+ 'sale_event_3_description ' => \Yii::t ('skeeks/seo ' , 'Описание ' ),
311+ 'sale_event_3_streetAddress ' => \Yii::t ('skeeks/seo ' , 'Адрес ' ),
312+ 'sale_event_3_addressLocality ' => \Yii::t ('skeeks/seo ' , 'Город ' ),
313+
253314 'is_mobile_webp ' => \Yii::t ('skeeks/seo ' , 'Использовать .webp сжатие картинок в мобильном телефоне? ' ),
254315 ]);
255316 }
@@ -267,11 +328,27 @@ public function attributeHints()
267328 'robotsContent ' => \Yii::t ('skeeks/seo ' , 'Содержимое файла robots.txt ' ),
268329 'contentIds ' => \Yii::t ('skeeks/seo ' , 'If nothing is selected, then all ' ),
269330 'treeTypeIds ' => \Yii::t ('skeeks/seo ' , 'If nothing is selected, then all ' ),
270- 'is_webp ' => \Yii::t ('skeeks/seo ' ,
271- 'Опция для компьютеров. Внимание в старых safari не работает! Если выбрана эта опция, то все изображения на сайте будут преобразовываться и ужиматься в .webp формат ' ),
331+ 'is_webp ' => \Yii::t ('skeeks/seo ' , 'Опция для компьютеров. Внимание в старых safari не работает! Если выбрана эта опция, то все изображения на сайте будут преобразовываться и ужиматься в .webp формат ' ),
272332 'is_mobile_webp ' => \Yii::t ('skeeks/seo ' , 'Опция работает в мобильном телефоне. Если выбрана эта опция, то все изображения на сайте будут преобразовываться и ужиматься в .webp формат ' ),
273333 'sitemap_min_date ' => \Yii::t ('skeeks/seo ' , 'Если будет задан этот параметр, то ни в одной ссылке не будет указано даты обновления меньше этой. Используется для переиндексации всех страниц. ' ),
274334
335+ 'is_sale_event ' => \Yii::t ('skeeks/seo ' , 'Если включена микроразметка событий, то в результатах выдачи google появится дополнительный блок ' ),
336+
337+ 'sale_event_1_name ' => \Yii::t ('skeeks/seo ' , 'Пример: 🌿 Качественные материалы ' ),
338+ 'sale_event_1_description ' => \Yii::t ('skeeks/seo ' , 'Пример: Качественные материалы ' ),
339+ 'sale_event_1_streetAddress ' => \Yii::t ('skeeks/seo ' , 'Возьмется из настроек сайта если не будет задан ' ),
340+ 'sale_event_1_addressLocality ' => \Yii::t ('skeeks/seo ' , 'Возьмется из настроек сайта если не будет задан ' ),
341+
342+ 'sale_event_2_name ' => \Yii::t ('skeeks/seo ' , 'Пример: ❤ Большой выбор ' ),
343+ 'sale_event_2_description ' => \Yii::t ('skeeks/seo ' , 'Пример: Большой выбор ' ),
344+ 'sale_event_2_streetAddress ' => \Yii::t ('skeeks/seo ' , 'Возьмется из настроек сайта если не будет задан ' ),
345+ 'sale_event_2_addressLocality ' => \Yii::t ('skeeks/seo ' , 'Возьмется из настроек сайта если не будет задан ' ),
346+
347+ 'sale_event_3_name ' => \Yii::t ('skeeks/seo ' , 'Пример: 🔔 Скидка на первый заказ ' ),
348+ 'sale_event_3_description ' => \Yii::t ('skeeks/seo ' , 'Пример: Скидка на первый заказ ' ),
349+ 'sale_event_3_streetAddress ' => \Yii::t ('skeeks/seo ' , 'Возьмется из настроек сайта если не будет задан ' ),
350+ 'sale_event_3_addressLocality ' => \Yii::t ('skeeks/seo ' , 'Возьмется из настроек сайта если не будет задан ' ),
351+
275352 ]);
276353 }
277354
@@ -376,6 +453,101 @@ public function getConfigFormFields()
376453 ],
377454 ],
378455 ],
456+
457+ 'saleEvent ' => [
458+ 'class ' => FieldSet::class,
459+ 'name ' => \Yii::t ('skeeks/seo ' , 'Микроразметка SaleEvent ' ),
460+ 'elementOptions ' => [
461+ 'isOpen ' => false ,
462+ ],
463+ 'fields ' => [
464+ 'is_sale_event ' => [
465+ 'class ' => BoolField::class,
466+ 'allowNull ' => false ,
467+ ],
468+
469+
470+ [
471+ 'class ' => HtmlBlock::class,
472+ 'content ' => <<<HTML
473+ <div class="col" style="margin-top: 20px;">
474+ <h3>Событие 1</h3>
475+ </div>
476+ HTML
477+ ],
478+
479+
480+
481+ ['class ' => HtmlRowBegin::class, 'noGutters ' => true ],
482+ ['class ' => HtmlColBegin::class],
483+ 'sale_event_1_name ' => [],
484+ ['class ' => HtmlColEnd::class],
485+ ['class ' => HtmlColBegin::class],
486+ 'sale_event_1_description ' => [],
487+ ['class ' => HtmlColEnd::class],
488+ ['class ' => HtmlColBegin::class],
489+ 'sale_event_1_streetAddress ' => [],
490+ ['class ' => HtmlColEnd::class],
491+ ['class ' => HtmlColBegin::class],
492+ 'sale_event_1_addressLocality ' => [],
493+ ['class ' => HtmlColEnd::class],
494+ ['class ' => HtmlRowEnd::class],
495+
496+ [
497+ 'class ' => HtmlBlock::class,
498+ 'content ' => <<<HTML
499+ <div class="col" style="margin-top: 20px;">
500+ <h3>Событие 2</h3>
501+ </div>
502+ HTML
503+ ],
504+
505+
506+
507+ ['class ' => HtmlRowBegin::class, 'noGutters ' => true ],
508+ ['class ' => HtmlColBegin::class],
509+ 'sale_event_2_name ' => [],
510+ ['class ' => HtmlColEnd::class],
511+ ['class ' => HtmlColBegin::class],
512+ 'sale_event_2_description ' => [],
513+ ['class ' => HtmlColEnd::class],
514+ ['class ' => HtmlColBegin::class],
515+ 'sale_event_2_streetAddress ' => [],
516+ ['class ' => HtmlColEnd::class],
517+ ['class ' => HtmlColBegin::class],
518+ 'sale_event_2_addressLocality ' => [],
519+ ['class ' => HtmlColEnd::class],
520+ ['class ' => HtmlRowEnd::class],
521+
522+
523+ [
524+ 'class ' => HtmlBlock::class,
525+ 'content ' => <<<HTML
526+ <div class="col" style="margin-top: 20px;">
527+ <h3>Событие 3</h3>
528+ </div>
529+ HTML
530+ ],
531+
532+
533+
534+ ['class ' => HtmlRowBegin::class, 'noGutters ' => true ],
535+ ['class ' => HtmlColBegin::class],
536+ 'sale_event_3_name ' => [],
537+ ['class ' => HtmlColEnd::class],
538+ ['class ' => HtmlColBegin::class],
539+ 'sale_event_3_description ' => [],
540+ ['class ' => HtmlColEnd::class],
541+ ['class ' => HtmlColBegin::class],
542+ 'sale_event_3_streetAddress ' => [],
543+ ['class ' => HtmlColEnd::class],
544+ ['class ' => HtmlColBegin::class],
545+ 'sale_event_3_addressLocality ' => [],
546+ ['class ' => HtmlColEnd::class],
547+ ['class ' => HtmlRowEnd::class],
548+ ],
549+ ],
550+
379551 'keywords ' => [
380552 'class ' => FieldSet::class,
381553 'name ' => \Yii::t ('skeeks/seo ' , 'Keywords ' ),
@@ -556,6 +728,122 @@ public function bootstrap($application)
556728 return ;
557729 }
558730 }
731+
732+ if ($ this ->is_sale_event && ($ this ->sale_event_1_name || $ this ->sale_event_2_name || $ this ->sale_event_3_name )) {
733+ if (in_array (\Yii::$ app ->controller ->action ->uniqueId , ["cms/tree/view " , "cms/content-element/view " , "cms/saved-filter/view " ])) {
734+ $ date1 = date ("Y-m-01 " , strtotime ("+1 month " ));
735+ $ date2 = date ("Y-m-t " , strtotime ("+1 month " ));
736+
737+ $ startDate = \Yii::$ app ->formatter ->asDatetime (strtotime ($ date1 ), "php:c " );
738+ $ endDate = \Yii::$ app ->formatter ->asDatetime (strtotime ($ date2 ), "php:c " );
739+
740+ $ projectName = \Yii::$ app ->skeeks ->site ->name ;
741+ $ address = \Yii::$ app ->skeeks ->site ->cmsSiteAddress ;
742+ $ addressString = "" ;
743+ if ($ address ) {
744+ $ addressString = $ address ->value ;
745+ }
746+
747+ $ saleEvents = "" ;
748+ if ($ this ->sale_event_1_name ) {
749+ $ eventData = [
750+ '@context ' => 'https://schema.org ' ,
751+ '@type ' => 'SaleEvent ' ,
752+ 'name ' => $ this ->sale_event_1_name ,
753+ 'description ' => $ this ->sale_event_1_description ? $ this ->sale_event_1_description : $ this ->sale_event_1_name ,
754+ 'startDate ' => $ startDate ,
755+ 'endDate ' => $ endDate ,
756+ 'location ' => [
757+ '@context ' => "https://schema.org " ,
758+ '@type ' => "Place " ,
759+ 'name ' => $ projectName ,
760+ 'address ' => [
761+ "@type " => "PostalAddress " ,
762+ "streetAddress " => $ this ->sale_event_1_streetAddress ? $ this ->sale_event_1_streetAddress : $ addressString ,
763+ ],
764+ ],
765+ ];
766+
767+ if ($ this ->sale_event_1_addressLocality ) {
768+ $ eventData ["location " ]["address " ]["addressLocality " ] = $ this ->sale_event_1_addressLocality ;
769+ }
770+
771+ $ eventDataString = Json::encode ($ eventData );
772+
773+ $ saleEvents .= <<<HTML
774+ <script type="application/ld+json">
775+ {$ eventDataString }
776+ </script>
777+ HTML ;
778+ }
779+
780+ if ($ this ->sale_event_2_name ) {
781+ $ eventData = [
782+ '@context ' => 'https://schema.org ' ,
783+ '@type ' => 'SaleEvent ' ,
784+ 'name ' => $ this ->sale_event_2_name ,
785+ 'description ' => $ this ->sale_event_2_description ? $ this ->sale_event_2_description : $ this ->sale_event_2_name ,
786+ 'startDate ' => $ startDate ,
787+ 'endDate ' => $ endDate ,
788+ 'location ' => [
789+ '@context ' => "https://schema.org " ,
790+ '@type ' => "Place " ,
791+ 'name ' => $ projectName ,
792+ 'address ' => [
793+ "@type " => "PostalAddress " ,
794+ "streetAddress " => $ this ->sale_event_2_streetAddress ? $ this ->sale_event_2_streetAddress : $ addressString ,
795+ ],
796+ ],
797+ ];
798+
799+ if ($ this ->sale_event_2_addressLocality ) {
800+ $ eventData ["location " ]["address " ]["addressLocality " ] = $ this ->sale_event_2_addressLocality ;
801+ }
802+
803+ $ eventDataString = Json::encode ($ eventData );
804+
805+ $ saleEvents .= <<<HTML
806+ <script type="application/ld+json">
807+ {$ eventDataString }
808+ </script>
809+ HTML ;
810+ }
811+
812+ if ($ this ->sale_event_3_name ) {
813+ $ eventData = [
814+ '@context ' => 'https://schema.org ' ,
815+ '@type ' => 'SaleEvent ' ,
816+ 'name ' => $ this ->sale_event_3_name ,
817+ 'description ' => $ this ->sale_event_3_description ? $ this ->sale_event_3_description : $ this ->sale_event_3_name ,
818+ 'startDate ' => $ startDate ,
819+ 'endDate ' => $ endDate ,
820+ 'location ' => [
821+ '@context ' => "https://schema.org " ,
822+ '@type ' => "Place " ,
823+ 'name ' => $ projectName ,
824+ 'address ' => [
825+ "@type " => "PostalAddress " ,
826+ "streetAddress " => $ this ->sale_event_3_streetAddress ? $ this ->sale_event_3_streetAddress : $ addressString ,
827+ ],
828+ ],
829+ ];
830+
831+ if ($ this ->sale_event_3_addressLocality ) {
832+ $ eventData ["location " ]["address " ]["addressLocality " ] = $ this ->sale_event_3_addressLocality ;
833+ }
834+
835+ $ eventDataString = Json::encode ($ eventData );
836+
837+ $ saleEvents .= <<<HTML
838+ <script type="application/ld+json">
839+ {$ eventDataString }
840+ </script>
841+ HTML ;
842+ }
843+
844+ \Yii::$ app ->seo ->countersContent = \Yii::$ app ->seo ->countersContent . $ saleEvents ;
845+ }
846+ }
559847 });
560848
561849 $ application ->on (Application::EVENT_AFTER_REQUEST , function ($ e ) {
0 commit comments