Completed
Push — master ( 0ce281...62c0f2 )
by Andrew
01:43
created

updateCMSFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
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
39
        // Remove framework default metadata group
40
        $fields->removeByName(array('Metadata'));
41
42
        // Add to fields
43
        $fields->addFieldsToTab('Root.Metadata.SEO', $this->owner->getSEOFields());
44
45
        //// Full output
46
        // monospaced, HTML SEO output
47
        $fields->addFieldsToTab('Root.Metadata.FullOutput', $this->owner->getFullOutput());
48
    }
49
50
    /**
51
     * Gets SEO fields.
52
     *
53
     * @return array
54
     */
55
    public function getSEOFields()
56
    {
57
        // Variables
58
        $config = SiteConfig::current_site_config();
59
        $SEO = [];
60
61
        // Canonical
62
        if ($config->CanonicalEnabled()) {
63
            $SEO[] = ReadonlyField::create('ReadonlyMetaCanonical', 'link rel="canonical"', $this->owner->AbsoluteLink());
64
        }
65
66
        // Title
67
        if ($config->TitleEnabled()) {
68
            $SEO[] = TextField::create('MetaTitle', 'meta title')
69
                ->setAttribute('placeholder', $this->owner->GenerateTitle());
70
        }
71
72
        // Description
73
        $SEO[] = TextareaField::create('MetaDescription', 'meta description')
74
            ->setAttribute('placeholder', $this->owner->GenerateDescriptionFromContent());
75
76
        // ExtraMeta
77
        if ($config->ExtraMetaEnabled()) {
78
            $SEO[] = TextareaField::create('ExtraMeta', 'Custom Metadata');
79
        }
80
81
        return $SEO;
82
    }
83
84
    /**
85
     * Gets the full output.
86
     *
87
     * @return array
88
     */
89
    public function getFullOutput()
90
    {
91
        return array(
92
            LiteralField::create('HeaderMetadata', '<pre class="bold">$Metadata()</pre>'),
93
            LiteralField::create('LiteralMetadata', '<pre>' . nl2br(htmlentities(trim($this->owner->Metadata()), ENT_QUOTES)) . '</pre>')
94
        );
95
    }
96
97
    /**
98
     * Main function to format & output metadata as an HTML string.
99
     *
100
     * Use the `updateMetadata($config, $owner, $metadata)` update hook when extending `DataExtension`s.
101
     *
102
     * @return string
103
     */
104
    public function Metadata()
105
    {
106
        // variables
107
        $config = SiteConfig::current_site_config();
108
109
        // begin SEO
110
        $metadata = PHP_EOL . $this->owner->MarkupComment('SEO');
111
112
        // register extension update hook
113
        $this->owner->extend('updateMetadata', $config, $this->owner, $metadata);
114
115
        // end
116
        $metadata .= $this->owner->MarkupComment('END SEO');
117
118
        // return
119
        return $metadata;
120
    }
121
122
123
    /* Template Methods
124
    ------------------------------------------------------------------------------*/
125
126
    /**
127
     * Updates metadata fields.
128
     *
129
     * @param SiteConfig $config
130
     * @param SiteTree $owner
131
     * @param string $metadata
132
     *
133
     * @return void
134
     */
135
    public function updateMetadata(SiteConfig $config, SiteTree $owner, &$metadata)
136
    {
137
        // metadata
138
        $metadata .= $owner->MarkupComment('Metadata');
139
140
        // charset
141
        if ($config->CharsetEnabled()) {
142
            $metadata .= '<meta charset="' . $config->Charset() . '" />' . PHP_EOL;
143
        }
144
145
        // canonical
146
        if ($config->CanonicalEnabled()) {
147
            $metadata .= $owner->MarkupLink('canonical', $owner->AbsoluteLink());
148
        }
149
150
        // title
151
        if ($config->TitleEnabled()) {
152
            $metadata .= '<title>' . $owner->encodeContent($owner->GenerateTitle(), $config->Charset()) . '</title>' . PHP_EOL;
153
        }
154
155
        // description
156
        if ($description = $owner->GenerateDescription()) {
157
            $metadata .= $owner->MarkupMeta('description', $description, $config->Charset());
158
        }
159
160
        // extra metadata
161
        if ($config->ExtraMetaEnabled()) {
162
            $metadata .= $owner->MarkupComment('Extra Metadata');
163
            $metadata .= $owner->GenerateExtraMeta();
164
        }
165
    }
166
167
168
    /* Markup Methods
169
    ------------------------------------------------------------------------------*/
170
171
    /**
172
     * Returns a given string as a HTML comment.
173
     *
174
     * @var string $comment
175
     *
176
     * @return string
177
     */
178
    public function MarkupComment($comment)
179
    {
180
        return '<!-- ' . $comment . ' -->' . PHP_EOL;
181
    }
182
183
    /**
184
     * Returns markup for a HTML meta element. Can be flagged for encoding.
185
     *
186
     * @param string $name
187
     * @param string $content
188
     * @param string|null $encode
189
     *
190
     * @return string
191
     */
192
    public function MarkupMeta($name, $content, $encode = null)
193
    {
194
        if ($encode !== null) {
195
            return '<meta name="' . $name . '" content="' . $this->encodeContent($content, $encode) . '" />' . PHP_EOL;
196
        } else {
197
            return '<meta name="' . $name . '" content="' . $content . '" />' . PHP_EOL;
198
        }
199
    }
200
201
    /**
202
     * Returns markup for a HTML link element.
203
     *
204
     * @param string $rel
205
     * @param string $href
206
     * @param string $type
207
     * @param string $sizes
208
     *
209
     * @return string
210
     */
211
    public function MarkupLink($rel, $href, $type = '', $sizes = '')
212
    {
213
        // start fragment
214
        $return = '<link rel="' . $rel . '" href="' . $href . '"';
215
        // if type
216
        if ($type) {
217
            $return .= ' type="' . $type . '"';
218
        }
219
        // if sizes
220
        if ($sizes) {
221
            $return .= ' sizes="' . $sizes . '"';
222
        }
223
        // end fragment
224
        $return .= ' />' . PHP_EOL;
225
        // return
226
        return $return;
227
    }
228
229
230
    /* Generation Methods
231
    ------------------------------------------------------------------------------*/
232
233
    /**
234
     * Generates HTML title based on configuration settings.
235
     *
236
     * @return string|null
237
     */
238
    public function GenerateTitle()
239
    {
240
        if ($this->owner->MetaTitle) {
241
            return $this->owner->MetaTitle;
242
        } else {
243
            return SiteConfig::current_site_config()->GenerateTitle($this->owner->Title);
244
        }
245
    }
246
247
    /**
248
     * Generates description from the page `MetaDescription`, or the first paragraph of the `Content` attribute.
249
     *
250
     * @return string|null
251
     */
252
    public function GenerateDescription()
253
    {
254
        if ($this->owner->MetaDescription) {
255
            return $this->owner->MetaDescription;
256
        } else {
257
            return $this->owner->GenerateDescriptionFromContent();
258
        }
259
    }
260
261
    /**
262
     * Generates description from the first paragraph of the `Content` attribute.
263
     *
264
     * @return string|null
265
     */
266
    public function GenerateDescriptionFromContent()
267
    {
268
        // check for content
269
        if ($content = trim($this->owner->Content)) {
270
            // pillage first paragraph from page content
271
            if (preg_match('/<p>(.*?)<\/p>/i', $content, $match)) {
272
                // is HTML
273
                $content = $match[0];
274
            } else {
275
                // is plain text
276
                $content = explode(PHP_EOL, $content);
277
                $content = $content[0];
278
            }
279
            // decode (no harm done) & return
280
            return trim(html_entity_decode(strip_tags($content)));
281
        } else {
282
            return null;
283
        }
284
    }
285
286
    /**
287
     * Generates extra metadata.
288
     *
289
     * @return string
290
     */
291
    public function GenerateExtraMeta()
292
    {
293
        if ($this->owner->ExtraMeta) {
294
            return $this->owner->ExtraMeta . PHP_EOL;
295
        } else {
296
            return $this->owner->MarkupComment('none');
297
        }
298
    }
299
300
301
    /* Utility Methods
302
    --------------------------------------------------------------------------*/
303
304
    /**
305
     * Returns a plain or HTML-encoded string according to the current charset & encoding settings.
306
     *
307
     * @param string $content
308
     * @param string $charset
309
     *
310
     * @return string
311
     */
312
    public function encodeContent($content, $charset)
313
    {
314
        return htmlentities($content, ENT_QUOTES, $charset);
315
    }
316
317
}
318