Completed
Push — master ( 960f7b...2a24eb )
by Andrew
02:26
created

code/SEO_Icons_SiteConfig_DataExtension.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * @todo Description
5
 *
6
 * I called them Pinicons & Tabicons in keeping with the absolutely pointless name: Favicons.
7
 *
8
 * @package silverstripe-seo
9
 * @subpackage icons
10
 * @author Andrew Gerber <[email protected]>
11
 * @version 1.0.0
12
 *
13
 */
14
class SEO_Icons_SiteConfig_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
18
    /* Static Variables
19
    ------------------------------------------------------------------------------*/
20
21
    //
22
    private static $SEOIconsUpload = 'SEO/SiteConfig/Icons/';
23
24
    //
25
    const APPLE_ICON_DEFAULT_BACKGROUND = '000000';
26
27
28
    /* Overload Model
29
    ------------------------------------------------------------------------------*/
30
31
    private static $db = array(
32
        // Pinned Icon Title
33
        'PiniconTitle' => 'Varchar(128)',
34
        // Android Pinned Icon
35
        'AndroidPiniconThemeColor' => 'Varchar(6)',
36
        // MS Tile
37
        'WindowsPiniconBackgroundColor' => 'Varchar(6)',
38
        // Safari Pinned Tab
39
//		'SafariTabiconThemeColor' => 'Varchar(6)', // @todo maybe implement
40
    );
41
    private static $has_one = array(
42
        // Favicon
43
//		'HTML4Favicon' => 'Image', // @todo maybe implement
44
        'HTML5Favicon' => 'Image',
45
        // Apple Pinned Icon
46
        'IOSPinicon' => 'Image',
47
        // Android Pinned Icon
48
        'AndroidPinicon' => 'Image',
49
        // Windows Pinned Icon
50
        'WindowsPinicon' => 'Image',
51
        // Safari Pinned Tab
52
//		'SafariTabiconDefault' => 'Image', // @todo maybe implement
53
//		'SafariTabiconWide' => 'Image', // @todo maybe implement
54
//		'SafariTabiconLarge' => 'Image', // @todo maybe implement
55
    );
56
57
58
    /* Overload Methods
59
    ------------------------------------------------------------------------------*/
60
61
    /**
62
     * Adds tabs & fields to the CMS.
63
     *
64
     * @param FieldList $fields
65
     */
66
    public function updateCMSFields(FieldList $fields)
67
    {
68
69
        //// Favicons Tab
70
71
        $tab = 'Root.Metadata.Favicons';
72
73
        //// Favicon
74
75
        $fields->addFieldsToTab($tab, array(
76
            LabelField::create('FaviconDescription', 'Favicons are `favourite icons` used by browsers in a number of ways whenever an icon is necessary e.g. tabs, history, bookmarks, dashboards.<br />@ <a href="https://en.wikipedia.org/wiki/Favicon" target="_blank">Favicon - Wikipedia, the free encyclopedia</a>')
77
                ->addExtraClass('information')
78
        ));
79
80
        //// HTML4 Favicon
81
82
        // check favicon.ico & set status
83
        $icoStatus = ReadonlyField::create('HTML4FaviconStatus', 'Favicon ICO<pre>type: ico</pre><pre>size: (multiple)<br />16x16 & 32x32 & 64x64 px</pre>', 'favicon.ico error');
84
        if (Director::fileExists('favicon.ico')) {
85
            $icoStatus
86
                ->setValue('favicon.ico found')
87
                ->addExtraClass('success favicon');
88
        } else {
89
            $icoStatus
90
                ->setValue('favicon.ico not found')
91
                ->addExtraClass('error');
92
        }
93
94
        // header & fields
95
        $fields->addFieldsToTab($tab, array(
96
            HeaderField::create('HTML4FaviconHeader', 'HTML4 <span class="aka">( favicon.ico )</span>'),
97
            LabelField::create('HTML4FaviconDescription', 'It is recommended you simply have a `favicon.ico` file in the webroot.')
98
                ->addExtraClass('information'),
99
            $icoStatus
100
        ));
101
102
        //// HTML5 Favicon
103
104
        // header & fields
105
        $fields->addFieldsToTab($tab, array(
106
            HeaderField::create('HTML5FaviconHeader', 'HTML5 <span class="aka">( favicon.png )</span>'),
107
            LabelField::create('HTML5FaviconDescription', '@todo Description')
108
                ->addExtraClass('information'),
109
            UploadField::create('HTML5Favicon', 'Favicon PNG<pre>type: png</pre><pre>size: 192x192 px</pre>')
110
                ->setAllowedExtensions(array('png'))
111
                ->setFolderName(self::$SEOIconsUpload)
112
        ));
113
114
        //// Pinned Icons Tab
115
116
        $tab = 'Root.Metadata.PinnedIcons';
117
118
        //// Pinned Icons Information
119
120
        $fields->addFieldsToTab($tab, array(
121
            LabelField::create('PiniconDescription', 'Pinned icons are OS-specific desktop shortcuts to pages on your website, they allow you to configure additional theming options to make pages appear more `native` / `web-app-y` within the OS.<br />Given they are OS-specific, they (obviously!) have a different format for each one :(')
122
                ->addExtraClass('information')
123
        ));
124
125
        //// Pinned Icon Title
126
127
        // CMS fields
128
        $fields->addFieldsToTab($tab, array(
129
            // header
130
            HeaderField::create('PiniconTitleHeader', 'Pinned Icon Title <span class="aka">( a.k.a. App Name )</span>'),
131
            // description
132
            LabelField::create('PiniconTitleDescription', 'When adding a link to the home screen, the user can choose a caption. By default, this is the bookmarked page title, which is usually fine. However, iOS and Windows 8 let you override this default value.')
133
                ->addExtraClass('information'),
134
            TextField::create('PiniconTitle', 'Application Title')
135
                ->setAttribute('placeholder', 'default: page title')
136
        ));
137
138
        //// iOS Pinned Icon
139
140
        // CMS fields
141
        $fields->addFieldsToTab($tab, array(
142
            // header
143
            HeaderField::create('IOSPiniconHeader', 'iOS Pinned Icon <span class="aka">( a.k.a. Touch Icons, Web Clips )</span>'),
144
            // information
145
            LabelField::create('IOSPiniconDescription', 'iPhone and iPad users can pin your web site on their home screen. The link looks like a native app.<br />@ <a href="https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html" target="_blank">Configuring Web Applications - iOS Developer Library</a>')
146
                ->addExtraClass('information'),
147
            // icon
148
            UploadField::create('IOSPinicon', 'iOS Icon<pre>type: png</pre><pre>size: 192x192 px</pre>')
149
                ->setAllowedExtensions(array('png'))
150
                ->setFolderName(self::$SEOIconsUpload)
151
                ->setDescription('iOS will fill the transparent regions with black by default, so put your own background in!')
152
        ));
153
154
        //// Android Pinned Icon
155
156
        // CMS fields
157
        $fields->addFieldsToTab($tab, array(
158
            // header
159
            HeaderField::create('AndroidPiniconHeader', 'Android Pinned Icon <span class="aka">( a.k.a. Android Chrome Icons, Launcher Icons )</span>'),
160
            // information
161
            LabelField::create('AndroidPiniconDescription', 'Add to Homescreen is a also a feature of Android Chrome. Your visitors can mix their natives apps and web bookmarks.<br />@ <a href="https://developer.chrome.com/multidevice/android/installtohomescreen" target="_blank">Add to Homescreen - Google Chrome</a>')
162
                ->addExtraClass('information'),
163
            // icon
164
            UploadField::create('AndroidPinicon', 'Android Icon<pre>type: png</pre><pre>size: 192x192 px</pre>')
165
                ->setAllowedExtensions(array('png'))
166
                ->setFolderName(self::$SEOIconsUpload),
167
            // background
168
            TextField::create('AndroidPiniconThemeColor', 'Theme Color<pre>type: hex triplet</pre>')
169
                ->setAttribute('placeholder', 'none')
170
                ->setAttribute('size', 6)
171
                ->setMaxLength(6)
172
                ->setDescription('Starting with Android Lollipop, you can customize the color of the task bar in the switcher.')
173
        ));
174
175
        //// Windows Pinned Icon
176
177
        // CMS fields
178
        $fields->addFieldsToTab($tab, array(
179
            // header
180
            HeaderField::create('WindowsShortcutHeader', 'Windows Pinned Icon <span class="aka">( a.k.a. Windows 8 / Metro Tiles )</span>'),
181
            // information
182
            LabelField::create('WindowsShortcutDescription', 'Windows 8 users can pin your web site on their desktop. Your site appears as a tile, just like a native Windows 8 app.<br />@ <a href="https://msdn.microsoft.com/en-us/library/dn455106" target="_blank">Creating custom tiles for IE11 websites (Windows)</a>')
183
                ->addExtraClass('information'),
184
            // icon
185
            UploadField::create('WindowsPinicon', 'Windows Icon<pre>type: png</pre><pre>size: 192x192 px</pre>')
186
                ->setAllowedExtensions(array('png'))
187
                ->setFolderName(self::$SEOIconsUpload),
188
            // background
189
            TextField::create('WindowsPiniconBackgroundColor', 'Background ( Tile ) Color<pre>type: hex triplet</pre>')
190
                ->setAttribute('placeholder', 'none')
191
                ->setAttribute('size', 6)
192
                ->setMaxLength(6)
193
        ));
194
195
        // @todo Safari Pinned Tab ~ maybe ??
196
197
    }
198
199
    /**
200
     * Generates the Android manifest.json file.
201
     *
202
     * @todo Information about permissions
203
     *
204
     * @return void
205
     */
206
    public function onAfterWrite()
207
    {
208
209
        // parent
210
        parent::onAfterWrite();
211
212
        // @todo Add success & error states + messages
213
        $this->generateAndroidManifest();
214
215
    }
216
217
218
    /* Custom Methods
219
    ------------------------------------------------------------------------------*/
220
221
    //// Fetch functions
222
223
    /**
224
     * Fetches the pinicon title.
225
     *
226
     * @return bool|string
227
     */
228
    public function fetchPiniconTitle()
229
    {
230
231
        if ($this->owner->PiniconTitle) {
232
            // return pinicon title
233
            return $this->owner->PiniconTitle;
234
        } else {
235
            // default
236
            return false;
237
        }
238
239
    }
240
241
    /**
242
     * Fetches the Android pinicon theme color.
243
     *
244
     * @return string|false
245
     */
246
    public function fetchAndroidPiniconThemeColor()
247
    {
248
249
        if ($this->owner->AndroidPiniconThemeColor) {
250
            return '#' . $this->owner->AndroidPiniconThemeColor;
251
        } else {
252
            return false;
253
        }
254
255
    }
256
257
    /**
258
     * Fetches the Windows pinicon background color.
259
     *
260
     * @return string|false
261
     */
262
    public function fetchWindowsPiniconBackgroundColor()
263
    {
264
265
        if ($this->owner->WindowsPiniconBackgroundColor) {
266
            return '#' . $this->owner->WindowsPiniconBackgroundColor;
267
        } else {
268
            return false;
269
        }
270
271
    }
272
273
    //// Generate functions
274
275
    /**
276
     * Generates the android manifest
277
     *
278
     * @todo check this is working 100%
279
     *
280
     * @return bool
281
     */
282
    public function generateAndroidManifest()
283
    {
284
285
        //// Android Pinicon Manifest
286
287
        $pinicon = $this->owner->AndroidPinicon();
288
289
        if ($pinicon->exists()) {
290
291
            //
292
            $manifest = new stdClass();
293
294
            //
295
            $manifest->name = $this->owner->PiniconTitle;
296
//			$manifest->start_url = null; @todo Maybe implement
297
//			$manifest->display = null; @todo Maybe implement
298
//			$manifest->orientation = null; @todo Maybe implement
299
            $manifest->icons = array();
300
301
            // 0.75x density icon
302
            array_push($manifest->icons, array(
303
                'src' => $pinicon->Fill(36, 36)->getAbsoluteURL(),
304
                'sizes' => '36x36',
305
                'type' => 'image/png',
306
                'density' => 0.75
307
            ));
308
309
            // 1x density icon
310
            array_push($manifest->icons, array(
311
                'src' => $pinicon->Fill(48, 48)->getAbsoluteURL(),
312
                'sizes' => '48x48',
313
                'type' => 'image/png',
314
                'density' => 1
315
            ));
316
317
            // 1.5x density icon
318
            array_push($manifest->icons, array(
319
                'src' => $pinicon->Fill(72, 72)->getAbsoluteURL(),
320
                'sizes' => '72x72',
321
                'type' => 'image/png',
322
                'density' => 1.5
323
            ));
324
325
            // 2x density icon
326
            array_push($manifest->icons, array(
327
                'src' => $pinicon->Fill(96, 96)->getAbsoluteURL(),
328
                'sizes' => '96x96',
329
                'type' => 'image/png',
330
                'density' => 2
331
            ));
332
333
            // 3x density icon
334
            array_push($manifest->icons, array(
335
                'src' => $pinicon->Fill(144, 144)->getAbsoluteURL(),
336
                'sizes' => '144x144',
337
                'type' => 'image/png',
338
                'density' => 3
339
            ));
340
341
            // 4x density icon
342
            array_push($manifest->icons, array(
343
                'src' => $pinicon->Fill(192, 192)->getAbsoluteURL(),
344
                'sizes' => '192x192',
345
                'type' => 'image/png',
346
                'density' => 4
347
            ));
348
349
            // create file
350
            $bytes = file_put_contents(Director::baseFolder() . '/manifest.json', json_encode($manifest));
351
352
            //
353
            if ($bytes !== false) {
354
                // success
355
                return true;
356
            }
357
358
        }
359
360
        // default return
361
        return false;
362
363
    }
364
365
}
366