Passed
Push — master ( 9e1011...5100b7 )
by Anton
02:08
created

MetaTagsWidget::registerCanonical()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 7
c 1
b 0
f 1
dl 0
loc 10
rs 10
cc 3
nc 3
nop 2
1
<?php
2
3
namespace kovenant\seo;
4
5
use Yii;
6
use yii\base\Component;
7
use yii\base\InvalidConfigException;
8
use yii\base\Widget;
9
use yii\helpers\ArrayHelper;
10
use yii\web\View;
11
12
/**
13
 * Class MetaTagsWidget
14
 * @package kovenant\seo
15
 * @author Anton Berezin <[email protected]>
16
 */
17
class MetaTagsWidget extends Widget
18
{
19
    /** @var Component */
20
    public $component;
21
22
    /** @var string */
23
    public $templateH1 = '{text}';
24
    /** @var string */
25
    public $templateTitle = '{text}{pager} | {appName}';
26
    /** @var string */
27
    public $templateKeywords = '{text}';
28
    /** @var string */
29
    public $templateDescription = '{text}{pager}';
30
    /** @var string */
31
    public $templatePager = ' - {pageText} {pageValue}';
32
    /** @var string */
33
    public $pageParam = 'page';
34
    /** @var string */
35
    public $pageText = 'Page';
36
37
    /**
38
     * @var array
39
     */
40
    public $metaTags = [];
41
42
    /** @var string */
43
    public $componentNameAttribute = 'name';
44
45
    /** @var string */
46
    public $viewH1Attribute;
47
    /** @var string */
48
    public $componentH1Attribute;
49
50
    /** @var string */
51
    public $viewTitleAttribute = 'title';
52
    /** @var string */
53
    public $componentTitleAttribute;
54
55
    /** @var string */
56
    public $componentKeywordsAttribute;
57
58
    /** @var string */
59
    public $componentDescriptionAttribute;
60
61
    /** @var string */
62
    public $absoluteUrlMethod;
63
64
    /**
65
     * @throws InvalidConfigException
66
     */
67
    public function init()
68
    {
69
        if (!$this->component instanceof Component) {
0 ignored issues
show
introduced by kovenant
$this->component is always a sub-type of yii\base\Component.
Loading history...
70
            throw new InvalidConfigException('component attribute must be instance of yii\base\Component');
71
        }
72
73
        if (empty($this->componentNameAttribute)) {
74
            throw new InvalidConfigException('componentNameAttribute is required');
75
        }
76
77
        parent::init();
78
    }
79
80
    /**
81
     * {@inheritDoc}
82
     * @throws \Exception
83
     */
84
    public function run()
85
    {
86
        $view = $this->view;
87
        $component = $this->component;
88
89
        $defaultTitle = $component->{$this->componentNameAttribute};
90
91
        if ($this->viewH1Attribute) {
92
            if (!empty($this->componentH1Attribute) && !empty($component->{$this->componentH1Attribute})) {
93
                $defaultTitle = $component->{$this->componentH1Attribute};
94
            }
95
96
            $view->{$this->viewH1Attribute} = $this->setPlaceholders($defaultTitle, $this->templateH1);
97
        }
98
99
        if (!empty($this->componentTitleAttribute) && !empty($component->{$this->componentTitleAttribute})) {
100
            $defaultTitle = $component->{$this->componentTitleAttribute};
101
        }
102
103
        $view->{$this->viewTitleAttribute} = $this->setPlaceholders($defaultTitle, $this->templateTitle);
104
105
        $this->setKeywords($component);
106
        $this->setDescription($defaultTitle, $component);
107
        $this->registerMetaTags($view);
108
        $this->registerCanonical($component, $view);
109
    }
110
111
    /**
112
     * @param string $content
113
     * @param string $template
114
     * @return string
115
     * @throws \Exception
116
     */
117
    protected function setPlaceholders($content, $template)
118
    {
119
        $content = str_replace('{text}', $content, $template);
120
121
        return preg_replace_callback('/{([^}]+)}/', function ($matches) {
122
            $name = $matches[1];
123
124
            try {
125
                $attribute = ArrayHelper::getValue($this, $name);
126
127
                if (is_string($attribute) || is_numeric($attribute)) {
128
                    return $attribute;
129
                }
130
            } catch (\yii\base\UnknownPropertyException $e) {
131
                Yii::error($e);
132
            }
133
134
            return $matches[0];
135
136
        }, $content);
137
    }
138
139
    /**
140
     * @param Component $component
141
     * @param View $view
142
     */
143
    protected function registerCanonical(Component $component, View $view)
144
    {
145
        if ($this->absoluteUrlMethod) {
146
            $url = Yii::$app->request->getAbsoluteUrl();
147
148
            if ($url !== $component->{$this->absoluteUrlMethod}()) {
149
                $view->registerLinkTag([
150
                    'rel' => 'canonical',
151
                    'href' => $component->{$this->absoluteUrlMethod}()
152
                ], 'canonical');
153
            }
154
        }
155
    }
156
157
    /**
158
     * @param View $view
159
     */
160
    protected function registerMetaTags(View $view)
161
    {
162
        foreach ($this->metaTags as $name => $content) {
163
            $view->registerMetaTag([
164
                'name' => $name,
165
                'content' => $content
166
            ], $name);
167
        }
168
    }
169
170
    /**
171
     * @param Component $component
172
     * @throws \Exception
173
     */
174
    protected function setKeywords(Component $component)
175
    {
176
        if (!empty($this->componentKeywordsAttribute) && !empty($component->{$this->componentKeywordsAttribute})) {
177
            $keywords = $component->{$this->componentKeywordsAttribute};
178
179
            $this->metaTags['keywords'] = $this->setPlaceholders($keywords, $this->templateKeywords);
180
        }
181
    }
182
183
    /**
184
     * @param $defaultTitle
185
     * @param Component $component
186
     * @throws \Exception
187
     */
188
    protected function setDescription($defaultTitle, Component $component)
189
    {
190
        if (!empty($this->componentDescriptionAttribute)) {
191
            $metaDescription = $component->{$this->componentDescriptionAttribute};
192
        }
193
194
        if (empty($metaDescription)) {
195
            $metaDescription = $defaultTitle;
196
        }
197
198
        $this->metaTags['description'] = $this->setPlaceholders($metaDescription, $this->templateDescription);
199
    }
200
201
    /**
202
     * Use {pager} in templates
203
     * @return string
204
     */
205
    protected function getPager()
206
    {
207
        $pageValue = (int)Yii::$app->request->getQueryParam($this->pageParam, 0);
208
209
        if ($pageValue === 0) {
210
            return '';
211
        }
212
213
        return str_replace([
214
            '{pageText}',
215
            '{pageValue}',
216
        ], [
217
            $this->pageText,
218
            $pageValue
219
        ], $this->templatePager);
220
    }
221
222
    /**
223
     * Use {appName} in templates
224
     * @return string
225
     */
226
    protected function getAppName()
227
    {
228
        return Yii::$app->name;
229
    }
230
}