Passed
Pull Request — master (#7)
by Dante
01:59
created

HtmlHelper   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 344
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 100
dl 0
loc 344
rs 9.52
c 0
b 0
f 0
wmc 36

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getMetaString() 0 10 3
A metaGenerator() 0 18 5
A metaAll() 0 31 3
A metaTwitter() 0 14 3
A metaOpenGraph() 0 14 3
A metaCss() 0 14 3
A metaDescription() 0 11 3
A title() 0 14 4
A getMetaArray() 0 10 3
A metaAuthor() 0 14 3
A __construct() 0 10 3
1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2018 ChannelWeb Srl, Chialab Srl
5
 *
6
 * This file is part of BEdita: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
12
 */
13
14
namespace BEdita\WebTools\View\Helper;
15
16
use Cake\Core\Configure;
17
use Cake\Utility\Inflector;
18
use Cake\View\Helper\HtmlHelper as CakeHtmlHelper;
19
use Cake\View\View;
20
21
/**
22
 * Html helper.
23
 * It extends {@see \Cake\View\Helper\HtmlHelper} Cake Html Helper
24
 */
25
class HtmlHelper extends CakeHtmlHelper
26
{
27
28
    /**
29
     * Meta data for helper
30
     */
31
    protected $meta = [
32
        'description' => '',
33
        'author' => '',
34
        'viewport' => '',
35
        'msapplication-TileColor' => '',
36
        'theme-color' => '',
37
        'docType' => '',
38
        'project' => [
39
            'name' => '',
40
            'version' => '',
41
        ],
42
    ];
43
44
    /**
45
     * Construct the meta data
46
     * Merge data to $this->meta from configure 'Meta', if set
47
     * Merge data to $this->meta from $config['meta'], if set
48
     *
49
     * @param \Cake\View\View $View The View this helper is being attached to.
50
     * @param array $config Configuration settings for the helper.
51
     */
52
    public function __construct(View $View, array $config = [])
53
    {
54
        if ($meta = Configure::read('Meta')) {
55
            $this->meta += $meta;
56
        }
57
        if (isset($config['meta'])) {
58
            $this->meta = $config['meta'] + $this->meta;
59
            unset($config['meta']);
60
        }
61
        parent::__construct($View, $config);
62
    }
63
64
    /**
65
     * Title for template pages
66
     * If `_title` view var is set, return it
67
     * Otherwise return controller name (and action name if set)
68
     *
69
     * @return string
70
     */
71
    public function title() : string
72
    {
73
        if (isset($this->getView()->viewVars['_title'])) {
74
            return $this->getView()->viewVars['_title'];
75
        }
76
        $title = Inflector::humanize($this->getView()->request->getParam('controller', ''));
77
        $suffix = Inflector::humanize($this->getView()->request->getParam('action', ''));
78
        if (empty($title)) {
79
            $title = $suffix;
80
        } elseif (!empty($suffix)) {
81
            $title .= sprintf(' - %s', $suffix);
82
        }
83
84
        return $title;
85
    }
86
87
    /**
88
     * Html meta
89
     * Possible meta data:
90
     *
91
     *  - description
92
     *  - author
93
     *  - viewport
94
     *  - msapplication-TileColor
95
     *  - theme-color
96
     *  - docType
97
     *  - project.name
98
     *  - project.version
99
     *
100
     * @param array $data Data for meta: 'description', 'author', 'viewport', 'msapplication-TileColor', 'theme-color', 'docType', 'project' (['name' => '...', 'version' => '...'])
101
     * @return string
102
     * @see HtmlHelper
103
     */
104
    public function metaAll(array $data) : string
105
    {
106
        $html = '';
107
108
        // description
109
        $description = $this->getMetaString($data, 'description', '');
110
        $html .= $this->metaDescription($description);
111
112
        // author
113
        $author = $this->getMetaString($data, 'author', '');
114
        $html .= $this->metaAuthor($author);
115
116
        // viewport, msapplication-TileColor, theme-color
117
        foreach (['viewport', 'msapplication-TileColor', 'theme-color'] as $attribute) {
118
            if (!empty($data[$attribute])) {
119
                $html .= $this->meta([
120
                    'name' => $attribute,
121
                    'content' => $data[$attribute],
122
                ]);
123
            }
124
        }
125
126
        // css
127
        $docType = $this->getMetaString($data, 'docType', 'xhtml-strict');
128
        $html .= $this->metaCss($docType);
129
130
        // generator
131
        $project = $this->getMetaArray($data, 'project', []);
132
        $html .= $this->metaGenerator($project);
133
134
        return $html;
135
    }
136
137
    /**
138
     * Return html meta description tag for passed description argument
139
     *
140
     * @param string|null $description The description
141
     * @return string
142
     */
143
    public function metaDescription($description) : string
144
    {
145
        if (empty($description)) {
146
            return '';
147
        }
148
        $html = $this->meta('description', h(strip_tags($description)));
149
        if ($html === null) {
150
            $html = '';
151
        }
152
153
        return $html;
154
    }
155
156
    /**
157
     * Return html meta author tag for passed creator argument
158
     *
159
     * @param string|null $creator The content creator
160
     * @return string
161
     */
162
    public function metaAuthor(?string $creator) : string
163
    {
164
        if (empty($creator)) {
165
            return '';
166
        }
167
        $html = $this->meta([
168
            'name' => 'author',
169
            'content' => h($creator),
170
        ]);
171
        if ($html === null) {
172
            $html = '';
173
        }
174
175
        return $html;
176
    }
177
178
    /**
179
     * Return html meta css tag for passed doc type
180
     *
181
     * @param string $docType The doc type
182
     * @return string
183
     */
184
    public function metaCss(string $docType) : string
185
    {
186
        if ($docType === 'html5') {
187
            return '';
188
        }
189
        $html = $this->meta([
190
            'http-equiv' => 'Content-Style-Type',
191
            'content' => 'text/css',
192
        ]);
193
        if ($html === null) {
194
            $html = '';
195
        }
196
197
        return $html;
198
    }
199
200
    /**
201
     * Return html meta for generator by project name and version passed
202
     *
203
     * @param array $project The project data ('name', 'version')
204
     * @return string
205
     */
206
    public function metaGenerator(array $project) : string
207
    {
208
        if (empty($project) || empty($project['name'])) {
209
            return '';
210
        }
211
        $version = '';
212
        if (!empty($project['version'])) {
213
            $version = $project['version'];
214
        }
215
        $html = $this->meta([
216
            'name' => 'generator',
217
            'content' => trim(sprintf('%s %s', $project['name'], $version)),
218
        ]);
219
        if ($html === null) {
220
            $html = '';
221
        }
222
223
        return $html;
224
    }
225
226
    /**
227
     * Return html meta for opengraph / facebook
228
     * OG fields:
229
     *
230
     *  - og:title
231
     *  - og:type
232
     *  - og:url
233
     *  - og:image
234
     *
235
     * OG optional fields:
236
     *
237
     *  - og:audio
238
     *  - og:description
239
     *  - og:determiner
240
     *  - og:locale
241
     *  - og:locale:alternate
242
     *  - og:site_name
243
     *  - og:video
244
     *
245
     * OG structured fields:
246
     *
247
     *  - og:image:url // identical to og:image
248
     *  - og:image:secure_url
249
     *  - og:image:type
250
     *  - og:image:width
251
     *  - og:image:height
252
     *  - og:image:alt
253
     *  - og:video:url // identical to og:video
254
     *  - og:video:secure_url
255
     *  - og:video:type
256
     *  - og:video:width
257
     *  - og:video:height
258
     *  - og:audio
259
     *  - og:secure_url
260
     *  - og:type
261
     *
262
     * For details @see http://ogp.me
263
     *
264
     * @param array $data The data ('title', 'type', 'image', 'url')
265
     * @return string
266
     */
267
    public function metaOpenGraph(array $data) : string
268
    {
269
        $html = '';
270
        foreach ($data as $attribute => $val) {
271
            $tmp = $this->meta([
272
                'property' => sprintf('og:%s', $attribute),
273
                'content' => $val,
274
            ]);
275
            if ($tmp !== null) {
276
                $html .= $tmp;
277
            }
278
        }
279
280
        return $html;
281
    }
282
283
    /**
284
     * Return html meta for twitter
285
     * twitter fields:
286
     *
287
     *  - twitter:card
288
     *  - twitter:site
289
     *  - twitter:site:id
290
     *  - twitter:creator
291
     *  - twitter:creator:id
292
     *  - twitter:description
293
     *  - twitter:title
294
     *  - twitter:image
295
     *  - twitter:image:alt
296
     *  - twitter:player
297
     *  - twitter:player:width
298
     *  - twitter:player:height
299
     *  - twitter:player:stream
300
     *  - twitter:app:name:iphone
301
     *  - twitter:app:id:iphone
302
     *  - twitter:app:url:iphone
303
     *  - twitter:app:name:ipad
304
     *  - twitter:app:id:ipad
305
     *  - twitter:app:url:ipad
306
     *  - twitter:app:name:googleplay
307
     *  - twitter:app:id:googleplay
308
     *  - twitter:app:url:googleplay
309
     *
310
     * For details @see https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/markup.html
311
     *
312
     * @param array $data The data ('card', 'site', 'creator', 'title', 'description', 'image')
313
     * @return string
314
     */
315
    public function metaTwitter(array $data) : string
316
    {
317
        $html = '';
318
        foreach ($data as $attribute => $val) {
319
            $tmp = $this->meta([
320
                'property' => sprintf('twitter:%s', $attribute),
321
                'content' => $val,
322
            ]);
323
            if ($tmp !== null) {
324
                $html .= $tmp;
325
            }
326
        }
327
328
        return $html;
329
    }
330
331
    /**
332
     * Return meta by data and field
333
     *
334
     * @param array $data The data
335
     * @param string $field The field
336
     * @param string $defaultVal The default val
337
     * @return string
338
     */
339
    public function getMetaString(array $data, string $field, ?string $defaultVal) : string
340
    {
341
        if (isset($data[$field])) {
342
            return $data[$field];
343
        }
344
        if (isset($this->meta[$field])) {
345
            return $this->meta[$field];
346
        }
347
348
        return (string)$defaultVal;
349
    }
350
351
    /**
352
     * Return meta by data and field
353
     *
354
     * @param array $data The data
355
     * @param string $field The field
356
     * @param array|null $defaultVal The default val
357
     * @return array
358
     */
359
    public function getMetaArray(array $data, string $field, ?array $defaultVal) : array
360
    {
361
        if (isset($data[$field])) {
362
            return $data[$field];
363
        }
364
        if (isset($this->meta[$field])) {
365
            return $this->meta[$field];
366
        }
367
368
        return (array)$defaultVal;
369
    }
370
}
371