Completed
Push — master ( b22b65...b3a19e )
by Andrew
01:40
created

GenerateExtraMeta()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
/**
3
 * Extends SiteTree with basic metadata fields, as well as the main `Metadata()` method.
4
 *
5
 * @package silverstripe-seo
6
 * @subpackage metadata
7
 * @author Andrew Gerber <[email protected]>
8
 * @version 1.0.0
9
 */
10
11
/**
12
 * Class SEO_Metadata_SiteTree_DataExtension
13
 */
14
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...
15
{
16
17
    /* Overload Model
18
    ------------------------------------------------------------------------------*/
19
20
    /**
21
     * Database attributes.
22
     *
23
     * @var array $db
24
     */
25
    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...
26
        'MetaTitle' => 'Varchar(128)',
27
        'MetaDescription' => 'Text', // redundant, but included for backwards-compatibility
28
        'ExtraMeta' => 'HTMLText', // redundant, but included for backwards-compatibility
29
    );
30
31
32
    /* Overload Methods
33
    ------------------------------------------------------------------------------*/
34
35
    // @todo @inheritdoc ?? or does it happen automagically as promised?
36
    public function updateCMSFields(FieldList $fields)
37
    {
38
        // Variables
39
        $config = SiteConfig::current_site_config();
40
        $owner = $this->owner;
41
        // Remove framework default metadata group
42
        $fields->removeByName(array('Metadata'));
43
        //// Metadata
44
        $tab = 'Root.Metadata.SEO';
45
        // Canonical
46
        if ($config->CanonicalEnabled()) {
47
            $fields->addFieldsToTab($tab, array(
48
                ReadonlyField::create('ReadonlyMetaCanonical', 'link rel="canonical"', $owner->AbsoluteLink())
49
            ));
50
        }
51
        // Title
52
        if ($config->TitleEnabled()) {
53
            $fields->addFieldsToTab($tab, array(
54
                TextField::create('MetaTitle', 'meta title')
55
                    ->setAttribute('placeholder', $owner->GenerateTitle())
56
            ));
57
        }
58
        // Description
59
        $fields->addFieldsToTab($tab, array(
60
            TextareaField::create('MetaDescription', 'meta description')
61
                ->setAttribute('placeholder', $owner->GenerateDescriptionFromContent())
62
        ));
63
        // ExtraMeta
64
        if ($config->ExtraMetaEnabled()) {
65
            $fields->addFieldsToTab($tab, array(
66
                TextareaField::create('ExtraMeta', 'Custom Metadata')
67
            ));
68
        }
69
        //// Full Output
70
        $tab = 'Root.Metadata.FullOutput';
71
        // monospaced, HTML SEO output
72
        $fields->addFieldsToTab($tab, array(
73
            LiteralField::create('HeaderMetadata', '<pre class="bold">$Metadata()</pre>'),
74
            LiteralField::create('LiteralMetadata', '<pre>' . nl2br(htmlentities(trim($owner->Metadata()), ENT_QUOTES)) . '</pre>')
75
        ));
76
    }
77
78
    /**
79
     * Main function to format & output metadata as an HTML string.
80
     *
81
     * Use the `updateMetadata($config, $owner, $metadata)` update hook when extending `DataExtension`s.
82
     *
83
     * @return string
84
     */
85
    public function Metadata()
86
    {
87
        // variables
88
        $config = SiteConfig::current_site_config();
89
        $owner = $this->owner;
90
91
        // begin SEO
92
        $metadata = PHP_EOL . $owner->MarkupComment('SEO');
93
94
        // register extension update hook
95
        $owner->extend('updateMetadata', $config, $owner, $metadata);
96
97
        // end
98
        $metadata .= $owner->MarkupComment('END SEO');
99
100
        // return
101
        return $metadata;
102
    }
103
104
105
    /* Template Methods
106
    ------------------------------------------------------------------------------*/
107
108
    /**
109
     * Updates metadata fields.
110
     *
111
     * @param SiteConfig $config
112
     * @param SiteTree $owner
113
     * @param string $metadata
114
     *
115
     * @return void
116
     */
117
    public function updateMetadata(SiteConfig $config, SiteTree $owner, &$metadata)
118
    {
119
        // metadata
120
        $metadata .= $owner->MarkupComment('Metadata');
121
122
        // charset
123
        if ($config->CharsetEnabled()) {
124
            $metadata .= '<meta charset="' . $config->Charset() . '" />' . PHP_EOL;
125
        }
126
127
        // canonical
128
        if ($config->CanonicalEnabled()) {
129
            $metadata .= $owner->MarkupLink('canonical', $owner->AbsoluteLink());
130
        }
131
132
        // title
133
        if ($config->TitleEnabled()) {
134
            $metadata .= '<title>' . $owner->encodeContent($owner->GenerateTitle(), $config->Charset()) . '</title>' . PHP_EOL;
135
        }
136
137
        // description
138
        if ($description = $owner->GenerateDescription()) {
139
            $metadata .= $owner->MarkupMeta('description', $description, $config->Charset());
140
        }
141
142
        // extra metadata
143
        if ($config->ExtraMetaEnabled()) {
144
            $metadata .= $owner->MarkupComment('Extra Metadata');
145
            $metadata .= $owner->GenerateExtraMeta();
146
        }
147
    }
148
149
150
    /* Markup Methods
151
    ------------------------------------------------------------------------------*/
152
153
    /**
154
     * Returns a given string as a HTML comment.
155
     *
156
     * @var string $comment
157
     *
158
     * @return string
159
     */
160
    public function MarkupComment($comment)
161
    {
162
        return '<!-- ' . $comment . ' -->' . PHP_EOL;
163
    }
164
165
    /**
166
     * Returns markup for a HTML meta element. Can be flagged for encoding.
167
     *
168
     * @var string $name
169
     * @var string $content
170
     * @var bool $encode
171
     *
172
     * @return string
173
     */
174
    public function MarkupMeta($name, $content, $encode = false)
175
    {
176
        if ($encode) {
177
            return '<meta name="' . $name . '" content="' . $this->encodeContent($content, $encode) . '" />' . PHP_EOL;
0 ignored issues
show
Documentation introduced by
$encode is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
178
        } else {
179
            return '<meta name="' . $name . '" content="' . $content . '" />' . 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
    /* Generation Methods
213
    ------------------------------------------------------------------------------*/
214
215
    /**
216
     * Generates HTML title based on configuration settings.
217
     *
218
     * @return string|null
219
     */
220
    public function GenerateTitle()
221
    {
222
        if ($this->owner->MetaTitle) {
223
            return $this->owner->MetaTitle;
224
        } else {
225
            return SiteConfig::current_site_config()->GenerateTitle($this->owner->Title);
226
        }
227
    }
228
229
    /**
230
     * Generates description from the page `MetaDescription`, or the first paragraph of the `Content` attribute.
231
     *
232
     * @return string|null
233
     */
234
    public function GenerateDescription()
235
    {
236
        if ($this->owner->MetaDescription) {
237
            return $this->owner->MetaDescription;
238
        } else {
239
            return $this->owner->GenerateDescriptionFromContent();
240
        }
241
    }
242
243
    /**
244
     * Generates description from the first paragraph of the `Content` attribute.
245
     *
246
     * @return string|null
247
     */
248
    public function GenerateDescriptionFromContent()
249
    {
250
        // check for content
251
        if ($content = trim($this->owner->Content)) {
252
            // pillage first paragraph from page content
253
            if (preg_match('/<p>(.*?)<\/p>/i', $content, $match)) {
254
                // is HTML
255
                $content = $match[0];
256
            } else {
257
                // is plain text
258
                $content = explode(PHP_EOL, $content);
259
                $content = $content[0];
260
            }
261
            // decode (no harm done) & return
262
            return trim(html_entity_decode(strip_tags($content)));
263
        } else {
264
            return null;
265
        }
266
    }
267
268
    /**
269
     * Generates extra metadata.
270
     *
271
     * return string
272
     */
273
    public function GenerateExtraMeta()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
274
    {
275
        if ($this->owner->ExtraMeta) {
276
            return $this->owner->ExtraMeta . PHP_EOL;
277
        } else {
278
            return $this->owner->MarkupComment('none');
279
        }
280
    }
281
282
283
    /* Utility Methods
284
    --------------------------------------------------------------------------*/
285
286
    /**
287
     * Returns a plain or HTML-encoded string according to the current charset & encoding settings.
288
     *
289
     * @param string $content
290
     * @param string $charset
291
     *
292
     * @return string
293
     */
294
    public function encodeContent($content, $charset) {
295
        return htmlentities($content, ENT_QUOTES, $charset);
296
    }
297
298
}
299