Completed
Push — master ( 2ce857...1017c9 )
by Andrew
02:01
created

encodeContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
3
/**
4
 * Extends SiteTree with basic metadata fields, as well as the main `Metadata()` method.
5
 *
6
 * @package silverstripe-seo
7
 * @subpackage metadata
8
 * @author Andrew Gerber <[email protected]>
9
 * @version 1.0.0
10
 *
11
 */
12
class SEO_Metadata_SiteTree_DataExtension extends DataExtension
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
13
{
14
15
16
    /* Overload Model
17
    ------------------------------------------------------------------------------*/
18
19
    private static $db = array(
0 ignored issues
show
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
20
        'MetaTitle' => 'Varchar(128)',
21
        'MetaDescription' => 'Text', // redundant, but included for backwards-compatibility
22
        'ExtraMeta' => 'HTMLText', // redundant, but included for backwards-compatibility
23
    );
24
25
26
    /* Overload Methods
27
    ------------------------------------------------------------------------------*/
28
29
    // CMS Fields
30
    public function updateCMSFields(FieldList $fields)
31
    {
32
33
        // Variables
34
        $config = SiteConfig::current_site_config();
35
        $owner = $this->owner;
36
37
        // Remove framework default metadata group
38
        $fields->removeByName(array('Metadata'));
39
40
        //// Metadata
41
        $tab = 'Root.Metadata.SEO';
42
43
        // Canonical
44
        if ($config->CanonicalEnabled()) {
45
            $fields->addFieldsToTab($tab, array(
46
                ReadonlyField::create('ReadonlyMetaCanonical', 'link rel="canonical"', $owner->AbsoluteLink())
47
            ));
48
        }
49
50
        // Title
51
        if ($config->TitleEnabled()) {
52
            $fields->addFieldsToTab($tab, array(
53
                TextField::create('MetaTitle', 'meta title')
54
                    ->setAttribute('placeholder', $owner->GenerateTitle())
55
            ));
56
        }
57
58
        // Description
59
        $fields->addFieldsToTab($tab, array(
60
            TextareaField::create('MetaDescription', 'meta description')
61
                ->setAttribute('placeholder', $owner->GenerateDescriptionFromContent())
62
        ));
63
64
        // ExtraMeta
65
        if ($config->ExtraMetaEnabled()) {
66
            $fields->addFieldsToTab($tab, array(
67
                TextareaField::create('ExtraMeta', 'Custom Metadata')
68
            ));
69
        }
70
71
        //// Full Output
72
73
        $tab = 'Root.Metadata.FullOutput';
74
75
        // monospaced, HTML SEO output
76
        $fields->addFieldsToTab($tab, array(
77
            LiteralField::create('HeaderMetadata', '<pre class="bold">$Metadata()</pre>'),
78
            LiteralField::create('LiteralMetadata', '<pre>' . nl2br(htmlentities(trim($owner->Metadata()), ENT_QUOTES)) . '</pre>')
79
        ));
80
81
    }
82
83
    /**
84
     * Main function to format & output metadata as an HTML string.
85
     *
86
     * Use the `updateMetadata($config, $owner, $metadata)` update hook when extending `DataExtension`s.
87
     *
88
     * @return string
89
     */
90
    public function Metadata()
91
    {
92
93
        // variables
94
        $config = SiteConfig::current_site_config();
95
        $owner = $this->owner;
96
97
        // begin SEO
98
        $metadata = PHP_EOL . $owner->MarkupComment('SEO');
99
100
        // metadata
101
        $metadata .= $owner->MarkupComment('Metadata');
102
103
        // charset
104
        if ($config->CharsetEnabled()) {
105
            $metadata .= '<meta charset="' . $config->Charset() . '" />' . PHP_EOL;
106
        }
107
108
        // canonical
109
        if ($config->CanonicalEnabled()) {
110
            $metadata .= $owner->MarkupLink('canonical', $owner->AbsoluteLink());
111
        }
112
113
        // title
114
        if ($config->TitleEnabled()) {
115
116
            // ternary operation
117
            // @todo Check what is going here ?!
118
            $title = ($owner->MetaTitle) ? $owner->MetaTitle : $owner->GenerateTitle();
119
            //
120
            $metadata .= '<title>' . htmlentities($title, ENT_QUOTES, $config->Charset()) . '</title>' . PHP_EOL;
121
122
        }
123
124
        // description
125
        $metadata .= $owner->MarkupMeta('description', $owner->GenerateDescription(), true, $config->Charset());
126
127
        //// ExtraMeta
128
129
        if ($config->ExtraMetaEnabled()) {
130
            if ($extraMeta = $owner->ExtraMeta != '') {
0 ignored issues
show
Unused Code introduced by
$extraMeta is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
131
                $metadata .= $owner->MarkupComment('Extra Metadata');
132
                $metadata .= $owner->ExtraMeta . PHP_EOL;
133
            }
134
        }
135
136
        //// extension update hook
137
        $owner->extend('updateMetadata', $config, $owner, $metadata);
138
139
        // end
140
        $metadata .= $owner->MarkupComment('END SEO');
141
142
        // return
143
        return $metadata;
144
145
    }
146
147
148
    /* Helper Methods
149
    ------------------------------------------------------------------------------*/
150
151
    /**
152
     * Returns a given string as a HTML comment.
153
     *
154
     * @var string $comment
155
     *
156
     * @return string
157
     */
158
    public function MarkupComment($comment)
159
    {
160
161
        // return
162
        return '<!-- ' . $comment . ' -->' . PHP_EOL;
163
164
    }
165
166
    /**
167
     * Returns markup for a HTML meta element.
168
     *
169
     * @var string $name
170
     * @var string $content
171
     * @var bool $encode
172
     *
173
     * @return string
174
     */
175 View Code Duplication
    public function MarkupMeta($name, $content, $encode = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
    {
177
178
        // return
179
        return '<meta name="' . $name . '" content="' . $this->encodeContent($content, $encode) . '" />' . PHP_EOL;
180
181
    }
182
183
    /**
184
     * Returns markup for a HTML link element.
185
     *
186
     * @param string $rel
187
     * @param string $href
188
     * @param string $type
189
     * @param string $sizes
190
     *
191
     * @return string
192
     */
193
    public function MarkupLink($rel, $href, $type = '', $sizes = '')
194
    {
195
        // start fragment
196
        $return = '<link rel="' . $rel . '" href="' . $href . '"';
197
        // if type
198
        if ($type) {
199
            $return .= ' type="' . $type . '"';
200
        }
201
        // if sizes
202
        if ($sizes) {
203
            $return .= ' sizes="' . $sizes . '"';
204
        }
205
        // end fragment
206
        $return .= ' />' . PHP_EOL;
207
        // return
208
        return $return;
209
    }
210
211
    /**
212
     * Returns markup for an Open Graph meta element.
213
     *
214
     * @var string $property
215
     * @var string $content
216
     * @var bool $encode
217
     *
218
     * @return string
219
     */
220 View Code Duplication
    public function MarkupFacebook($property, $content, $encode = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
    {
222
223
        // format & return
224
        return '<meta property="' . $property . '" content="' . $this->encodeContent($content, $encode) . '" />' . PHP_EOL;
225
226
    }
227
228
    /**
229
     * Returns markup for a Twitter Cards meta element.
230
     *
231
     * @var string $name
232
     * @var string $content
233
     * @var bool $encode
234
     *
235
     * @return string
236
     */
237 View Code Duplication
    public function MarkupTwitter($name, $content, $encode = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
238
    {
239
240
        // format & return
241
        return '<meta name="' . $name . '" content="' . $this->encodeContent($content, $encode) . '" />' . PHP_EOL;
242
243
    }
244
245
    /**
246
     * Returns markup for a Schema.org meta element.
247
     *
248
     * @var string $itemprop
249
     * @var string $content
250
     * @var bool $encode
251
     *
252
     * @return string
253
     */
254 View Code Duplication
    public function MarkupSchema($itemprop, $content, $encode = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
    {
256
257
        // format & return
258
        return '<meta itemprop="' . $itemprop . '" content="' . $this->encodeContent($content, $encode) . '" />' . PHP_EOL;
259
260
    }
261
262
263
    /* Meta Methods
264
    ------------------------------------------------------------------------------*/
265
266
    /**
267
     * Generates HTML title based on configuration settings.
268
     *
269
     * @return bool|string
270
     */
271
    public function GenerateTitle()
272
    {
273
274
        // return SEO title or false
275
        return SiteConfig::current_site_config()->GenerateTitle($this->owner->Title);
276
277
    }
278
279
    /**
280
     * Returns description from the page `MetaDescription`, or the first paragraph of the `Content` attribute.
281
     *
282
     * @return bool|string
283
     */
284
    public function GenerateDescription()
285
    {
286
287
        if ($this->owner->MetaDescription) {
288
            return $this->owner->MetaDescription;
289
        } else {
290
            return $this->owner->GenerateDescriptionFromContent();
291
        }
292
293
    }
294
295
    /**
296
     * Generates description from the first paragraph of the `Content` attribute.
297
     *
298
     * @return bool|string
299
     */
300
    public function GenerateDescriptionFromContent()
301
    {
302
303
        if ($content = trim($this->owner->Content)) {
304
305
            // pillage first paragraph from page content
306
            if (preg_match('/<p>(.*?)<\/p>/i', $content, $match)) {
307
                // is HTML
308
                $content = $match[0];
309
            } else {
310
                // is plain text
311
                $content = explode("\n", $content);
312
                $content = $content[0];
313
            }
314
315
            // decode (no harm done) & return
316
            return trim(html_entity_decode(strip_tags($content)));
317
318
        } else {
319
            // none
320
            return false;
321
        }
322
323
    }
324
325
    /**
326
     * Returns a plain or HTML-encoded string according to the current charset & encoding settings.
327
     *
328
     * @param string $content
329
     * @param bool $encode
330
     *
331
     * @return string
332
     */
333
    public function encodeContent($content, $encode = true) {
334
        if ($encode) {
335
            return htmlentities($content, ENT_QUOTES, $this->owner->Charset);
336
        } else {
337
            return $content;
338
        }
339
    }
340
341
}
342