Issues (23)

src/Extensions/CWPSiteConfigExtension.php (6 issues)

1
<?php
2
3
namespace CWP\AgencyExtensions\Extensions;
4
5
use CWP\AgencyExtensions\Forms\ColorPickerField;
6
use CWP\AgencyExtensions\Forms\FontPickerField;
7
use SilverStripe\Assets\File;
8
use SilverStripe\Assets\Image;
9
use SilverStripe\Core\Injector\Injector;
10
use SilverStripe\Forms\DropdownField;
11
use SilverStripe\Forms\FieldList;
12
use SilverStripe\Forms\FileHandleField;
13
use SilverStripe\Forms\TextField;
14
use SilverStripe\ORM\DataExtension;
15
use SilverStripe\Versioned\Versioned;
16
use SilverStripe\View\Requirements;
17
18
/**
19
 * Class CWPCleanupSiteConfigExtension
20
 */
21
class CWPSiteConfigExtension extends DataExtension
22
{
23
    private static $db = array(
0 ignored issues
show
The private property $db is not used, and could be removed.
Loading history...
24
        'FooterLogoLink' => 'Varchar(255)',
25
        'FooterLogoDescription' => 'Varchar(255)',
26
        'FooterLogoSecondaryLink' => 'Varchar(255)',
27
        'FooterLogoSecondaryDescription' => 'Varchar(255)',
28
        'EmptySearch' => 'Varchar(255)',
29
        'NoSearchResults' => 'Varchar(255)',
30
        'MainFontFamily' => 'Varchar(50)',
31
        'HeaderBackground' => 'Varchar(50)',
32
        'NavigationBarBackground' => 'Varchar(50)',
33
        'CarouselBackground' => 'Varchar(50)',
34
        'FooterBackground' => 'Varchar(50)',
35
        'AccentColor' => 'Varchar(50)',
36
        'TextLinkColor' => 'Varchar(50)',
37
    );
38
39
    private static $has_one = array(
0 ignored issues
show
The private property $has_one is not used, and could be removed.
Loading history...
40
        'Logo' => Image::class,
41
        'LogoRetina' => Image::class,
42
        'FooterLogo' => Image::class,
43
        'FooterLogoRetina' => Image::class,
44
        'FooterLogoSecondary' => Image::class,
45
        'FavIcon' => File::class,
46
        'AppleTouchIcon144' => File::class,
47
        'AppleTouchIcon114' => File::class,
48
        'AppleTouchIcon72' => File::class,
49
        'AppleTouchIcon57' => File::class
50
    );
51
52
    private static $owns = [
0 ignored issues
show
The private property $owns is not used, and could be removed.
Loading history...
53
        'Logo',
54
        'LogoRetina',
55
        'FooterLogo',
56
        'FooterLogoRetina',
57
        'FooterLogoSecondary',
58
        'FavIcon',
59
        'AppleTouchIcon144',
60
        'AppleTouchIcon114',
61
        'AppleTouchIcon72',
62
        'AppleTouchIcon57'
63
    ];
64
65
    /**
66
     * Defines if the theme colour picker is enabled in the CMS
67
     *
68
     * @config
69
     * @var boolean
70
     */
71
    private static $enable_theme_color_picker = false;
0 ignored issues
show
The private property $enable_theme_color_picker is not used, and could be removed.
Loading history...
72
73
    /**
74
     * Defines the theme fonts that can be selected via the CMS
75
     *
76
     * @config
77
     * @var array
78
     */
79
    private static $theme_fonts = [
0 ignored issues
show
The private property $theme_fonts is not used, and could be removed.
Loading history...
80
        'nunito-sans' => 'Nunito Sans',
81
        'fira-sans' => 'Fira Sans',
82
        'merriweather' => 'Merriweather',
83
    ];
84
85
    /**
86
     * Defines the theme colours that can be selected via the CMS
87
     *
88
     * @config
89
     * @var array
90
     */
91
    private static $theme_colors = [
0 ignored issues
show
The private property $theme_colors is not used, and could be removed.
Loading history...
92
        'default-accent' => [
93
            'Title' => 'Default',
94
            'CSSClass' => 'default-accent',
95
            'Color' => '#0F7EB2',
96
        ],
97
        'default-background' => [
98
            'Title' => 'Default',
99
            'CSSClass' => 'default-background',
100
            'Color' => '#001F2C',
101
        ],
102
        'red' => [
103
            'Title' => 'Red',
104
            'CSSClass' => 'red',
105
            'Color' => '#E51016',
106
        ],
107
        'dark-red' => [
108
            'Title' => 'Dark red',
109
            'CSSClass' => 'dark-red',
110
            'Color' => '#AD161E',
111
        ],
112
        'pink' => [
113
            'Title' => 'Pink',
114
            'CSSClass' => 'pink',
115
            'Color' => '#B32A95',
116
        ],
117
        'purple' => [
118
            'Title' => 'Purple',
119
            'CSSClass' => 'purple',
120
            'Color' => '#6239C8',
121
        ],
122
        'blue' => [
123
            'Title' => 'Blue',
124
            'CSSClass' => 'blue',
125
            'Color' => '#1F6BFE',
126
        ],
127
        'dark-blue' => [
128
            'Title' => 'Dark blue',
129
            'CSSClass' => 'dark-blue',
130
            'Color' => '#123581',
131
        ],
132
        'teal' => [
133
            'Title' => 'Teal',
134
            'CSSClass' => 'teal',
135
            'Color' => '#00837A',
136
        ],
137
        'green' => [
138
            'Title' => 'Green',
139
            'CSSClass' => 'green',
140
            'Color' => '#298436',
141
        ],
142
        'dark-orange' => [
143
            'Title' => 'Dark orange',
144
            'CSSClass' => 'dark-orange',
145
            'Color' => '#D34300',
146
        ],
147
        'dark-ochre' => [
148
            'Title' => 'Dark ochre',
149
            'CSSClass' => 'dark-ochre',
150
            'Color' => '#947200',
151
        ],
152
        'black' => [
153
            'Title' => 'Black',
154
            'CSSClass' => 'black',
155
            'Color' => '#111111',
156
        ],
157
        'dark-grey' => [
158
            'Title' => 'Dark grey',
159
            'CSSClass' => 'dark-grey',
160
            'Color' => '#555555',
161
        ],
162
        'light-grey' => [
163
            'Title' => 'Light grey',
164
            'CSSClass' => 'light-grey',
165
            'Color' => '#EAEAEA',
166
        ],
167
        'white' => [
168
            'Title' => 'White',
169
            'CSSClass' => 'white',
170
            'Color' => '#FFFFFF',
171
        ],
172
    ];
173
174
    /**
175
     * @param FieldList $fields
176
     */
177
    public function updateCMSFields(FieldList $fields)
178
    {
179
        $this
180
            ->addLogosAndIcons($fields)
181
            ->addSearchOptions($fields)
182
            ->addThemeColorPicker($fields);
183
    }
184
185
    /**
186
     * Add fields for logo and icon uploads
187
     *
188
     * @param  FieldList $fields
189
     * @return $this
190
     */
191
    protected function addLogosAndIcons(FieldList $fields)
192
    {
193
        $logoTypes = array('jpg', 'jpeg', 'png', 'gif');
194
        $iconTypes = array('ico');
195
        $appleTouchTypes = array('png');
196
197
        $fields->findOrMakeTab(
198
            'Root.LogosIcons',
199
            _t(__CLASS__ . '.LogosIconsTab', 'Logos/Icons')
200
        );
201
202
        $fields->addFieldToTab(
203
            'Root.LogosIcons',
204
            $logoField = Injector::inst()->create(
205
                FileHandleField::class,
206
                'Logo',
207
                _t(__CLASS__ . '.LogoUploadField', 'Logo, to appear in the top left')
208
            )
209
        );
210
        $logoField->getValidator()->setAllowedExtensions($logoTypes);
211
212
        $fields->addFieldToTab(
213
            'Root.LogosIcons',
214
            $logoRetinaField = Injector::inst()->create(
215
                FileHandleField::class,
216
                'LogoRetina',
217
                _t(
218
                    'CwpConfig.LogoRetinaUploadField',
219
                    'High resolution logo, to appear in the top left ' .
220
                    '(recommended to be twice the height and width of the standard logo)'
221
                )
222
            )
223
        );
224
        $logoRetinaField->getValidator()->setAllowedExtensions($logoTypes);
225
226
        $fields->addFieldToTab(
227
            'Root.LogosIcons',
228
            $footerLogoField = Injector::inst()->create(
229
                FileHandleField::class,
230
                'FooterLogo',
231
                _t(__CLASS__ . '.FooterLogoField', 'Footer logo, to appear in the footer')
232
            )
233
        );
234
        $footerLogoField->getValidator()->setAllowedExtensions($logoTypes);
235
236
        $fields->addFieldToTab(
237
            'Root.LogosIcons',
238
            $footerLogoRetinaField = Injector::inst()->create(
239
                FileHandleField::class,
240
                'FooterLogoRetina',
241
                _t(
242
                    'CwpConfig.FooterLogoRetinaField',
243
                    'High resolution footer logo (recommended twice the height and width of the standard footer logo)'
244
                )
245
            )
246
        );
247
        $footerLogoRetinaField->getValidator()->setAllowedExtensions($logoTypes);
248
249
        $fields->addFieldToTab(
250
            'Root.LogosIcons',
251
            $footerLink = TextField::create(
252
                'FooterLogoLink',
253
                _t(__CLASS__ . '.FooterLogoLinkField', 'Footer Logo link')
254
            )
255
        );
256
        $footerLink->setRightTitle(
257
            _t(
258
                'CwpConfig.FooterLogoLinkDesc',
259
                'Please include the protocol (ie, http:// or https://) unless it is an internal link.'
260
            )
261
        );
262
263
        $fields->addFieldToTab(
264
            'Root.LogosIcons',
265
            TextField::create(
266
                'FooterLogoDescription',
267
                _t(__CLASS__ . '.FooterLogoDescField', 'Footer Logo description')
268
            )
269
        );
270
271
        $fields->addFieldToTab(
272
            'Root.LogosIcons',
273
            $footerLogoSecondaryField = Injector::inst()->create(
274
                FileHandleField::class,
275
                'FooterLogoSecondary',
276
                _t(__CLASS__ . '.FooterLogoSecondaryField', 'Secondary Footer Logo, to appear in the footer.')
277
            )
278
        );
279
        $footerLogoSecondaryField->getValidator()->setAllowedExtensions($logoTypes);
280
281
        $fields->addFieldToTab('Root.LogosIcons', $footerSecondaryLink = TextField::create(
282
            'FooterLogoSecondaryLink',
283
            _t(__CLASS__ . '.FooterLogoSecondaryLinkField', 'Secondary Footer Logo link.')
284
        ));
285
        $footerSecondaryLink->setRightTitle(_t(
286
            'CwpConfig.FooterLogoSecondaryLinkDesc',
287
            'Please include the protocol (ie, http:// or https://) unless it is an internal link.'
288
        ));
289
        $fields->addFieldToTab('Root.LogosIcons', TextField::create(
290
            'FooterLogoSecondaryDescription',
291
            _t(__CLASS__ . '.FooterLogoSecondaryDescField', 'Secondary Footer Logo description')
292
        ));
293
294
        $fields->addFieldToTab(
295
            'Root.LogosIcons',
296
            $favIconField = Injector::inst()->create(
297
                FileHandleField::class,
298
                'FavIcon',
299
                _t(__CLASS__ . '.FavIconField', 'Favicon, in .ico format, dimensions of 16x16, 32x32, or 48x48')
300
            )
301
        );
302
        $favIconField->getValidator()->setAllowedExtensions($iconTypes);
303
304
        $fields->addFieldToTab(
305
            'Root.LogosIcons',
306
            $atIcon144 = Injector::inst()->create(
307
                FileHandleField::class,
308
                'AppleTouchIcon144',
309
                _t(
310
                    'CwpConfig.AppleIconField144',
311
                    'Apple Touch Web Clip and Windows 8 Tile Icon (dimensions of 144x144, PNG format)'
312
                )
313
            )
314
        );
315
        $atIcon144->getValidator()->setAllowedExtensions($appleTouchTypes);
316
317
        $fields->addFieldToTab(
318
            'Root.LogosIcons',
319
            $atIcon114 = Injector::inst()->create(
320
                FileHandleField::class,
321
                'AppleTouchIcon114',
322
                _t(__CLASS__ . '.AppleIconField114', 'Apple Touch Web Clip Icon (dimensions of 114x114, PNG format)')
323
            )
324
        );
325
        $atIcon114->getValidator()->setAllowedExtensions($appleTouchTypes);
326
327
        $fields->addFieldToTab(
328
            'Root.LogosIcons',
329
            $atIcon72 = Injector::inst()->create(
330
                FileHandleField::class,
331
                'AppleTouchIcon72',
332
                _t(__CLASS__ . '.AppleIconField72', 'Apple Touch Web Clip Icon (dimensions of 72x72, PNG format)')
333
            )
334
        );
335
        $atIcon72->getValidator()->setAllowedExtensions($appleTouchTypes);
336
337
        $fields->addFieldToTab(
338
            'Root.LogosIcons',
339
            $atIcon57 = Injector::inst()->create(
340
                FileHandleField::class,
341
                'AppleTouchIcon57',
342
                _t(__CLASS__ . '.AppleIconField57', 'Apple Touch Web Clip Icon (dimensions of 57x57, PNG format)')
343
            )
344
        );
345
        $atIcon57->getValidator()->setAllowedExtensions($appleTouchTypes);
346
347
        return $this;
348
    }
349
350
    /**
351
     * Add user configurable search field labels
352
     *
353
     * @param  FieldList $fields
354
     * @return $this
355
     */
356
    protected function addSearchOptions(FieldList $fields)
357
    {
358
        $fields->findOrMakeTab('Root.SearchOptions');
359
360
        $fields->addFieldToTab(
361
            'Root.SearchOptions',
362
            TextField::create(
363
                'EmptySearch',
364
                _t(
365
                    'CWP.SITECONFIG.EmptySearch',
366
                    'Text to display when there is no search query'
367
                )
368
            )
369
        );
370
        $fields->addFieldToTab(
371
            'Root.SearchOptions',
372
            TextField::create(
373
                'NoSearchResults',
374
                _t(
375
                    'CWP.SITECONFIG.NoResult',
376
                    'Text to display when there are no results'
377
                )
378
            )
379
        );
380
381
        return $this;
382
    }
383
384
    /**
385
     * Add fields for selecting the font theme colour for different areas of the site.
386
     *
387
     * @param  FieldList $fields
388
     * @return $this
389
     */
390
    protected function addThemeColorPicker(FieldList $fields)
391
    {
392
        // Only show theme colour selector if enabled
393
        if (!$this->owner->config()->get('enable_theme_color_picker')) {
394
            return $this;
395
        }
396
397
        $fonts = $this->owner->config()->get('theme_fonts');
398
399
        // Import each font via the google fonts api to render font preview
400
        foreach ($fonts as $fontTitle) {
401
            $fontFamilyName = str_replace(' ', '+', $fontTitle);
402
            Requirements::css("//fonts.googleapis.com/css?family=$fontFamilyName");
403
        }
404
405
        $fields->addFieldsToTab(
406
            'Root.ThemeOptions',
407
            [
408
                FontPickerField::create(
409
                    'MainFontFamily',
410
                    _t(
411
                        __CLASS__ . '.MainFontFamily',
412
                        'Main font family'
413
                    ),
414
                    $fonts
415
                ),
416
                 ColorPickerField::create(
417
                     'HeaderBackground',
418
                     _t(
419
                         __CLASS__ . '.HeaderBackground',
420
                         'Header background'
421
                     ),
422
                     $this->getThemeOptionsExcluding([
423
                         'default-accent',
424
                     ])
425
                 ),
426
                 ColorPickerField::create(
427
                     'NavigationBarBackground',
428
                     _t(
429
                         __CLASS__ . '.NavigationBarBackground',
430
                         'Navigation bar background'
431
                     ),
432
                     $this->getThemeOptionsExcluding([
433
                         'default-accent',
434
                     ])
435
                 ),
436
                 ColorPickerField::create(
437
                     'CarouselBackground',
438
                     _t(
439
                         __CLASS__ . '.CarouselBackground',
440
                         'Carousel background'
441
                     ),
442
                     $this->getThemeOptionsExcluding([
443
                         'default-accent',
444
                     ])
445
                 )->setDescription(
446
                     _t(
447
                         __CLASS__ . '.CarouselBackgroundDescription',
448
                         'The background colour of the carousel when there is no image set.'
449
                     )
450
                 ),
451
                 ColorPickerField::create(
452
                     'FooterBackground',
453
                     _t(
454
                         __CLASS__ . '.FooterBackground',
455
                         'Footer background'
456
                     ),
457
                     $this->getThemeOptionsExcluding([
458
                         'light-grey',
459
                         'white',
460
                         'default-accent',
461
                     ])
462
                 ),
463
                 ColorPickerField::create(
464
                     'AccentColor',
465
                     _t(
466
                         __CLASS__ . '.AccentColor',
467
                         'Accent colour'
468
                     ),
469
                     $this->getThemeOptionsExcluding([
470
                         'light-grey',
471
                         'white',
472
                         'default-background',
473
                     ])
474
                 )->setDescription(
475
                     _t(
476
                         __CLASS__ . '.AccentColorDescription',
477
                         'Affects colour of buttons, current navigation items, etc. '.
478
                         'Please ensure sufficient contrast with background colours.'
479
                     )
480
                 ),
481
                 ColorPickerField::create(
482
                     'TextLinkColor',
483
                     _t(
484
                         __CLASS__ . '.TextLinkColor',
485
                         'Text link colour'
486
                     ),
487
                     $this->getThemeOptionsExcluding([
488
                         'black',
489
                         'light-grey',
490
                         'dark-grey',
491
                         'white',
492
                         'default-background',
493
                     ])
494
                 ),
495
            ]
496
        );
497
498
        return $this;
499
    }
500
501
    /**
502
     * Returns theme_colors used for ColorPickerField.
503
     *
504
     * @param  array  $excludedColors list of colours to exclude from the returned options
505
     *                                based on the theme colour's 'CSSClass' value
506
     * @return array
507
     */
508
    public function getThemeOptionsExcluding($excludedColors = [])
509
    {
510
        $themeColors = $this->owner->config()->get('theme_colors');
511
        $options = [];
512
513
        foreach ($themeColors as $themeColor) {
514
            if (in_array($themeColor['CSSClass'], $excludedColors)) {
515
                continue;
516
            }
517
518
            $options[] = $themeColor;
519
        }
520
521
        return $options;
522
    }
523
524
    /**
525
     * Auto-publish any images attached to the SiteConfig object if it's not versioned. Versioned objects will
526
     * handle their related objects via the "owns" API by default.
527
     */
528
    public function onAfterWrite()
529
    {
530
        if (!$this->owner->hasExtension(Versioned::class)) {
531
            $this->owner->publishRecursive();
532
        }
533
    }
534
535
    /**
536
     * If HeaderBackground is not set, assume no theme colours exist and populate some defaults if the colour
537
     * picker is enabled. We don't use populateDefaults() because we don't want SiteConfig to re-populate its own
538
     * defaults.
539
     */
540
    public function onBeforeWrite()
541
    {
542
        $colorPickerEnabled = $this->owner->config()->get('enable_theme_color_picker');
543
544
        if ($colorPickerEnabled && !$this->owner->HeaderBackground) {
545
            $this->owner->update([
546
                'MainFontFamily' => FontPickerField::DEFAULT_VALUE,
547
                'HeaderBackground' => 'default-background',
548
                'NavigationBarBackground' => 'default-background',
549
                'CarouselBackground' => 'default-background',
550
                'FooterBackground' => 'default-background',
551
                'AccentColor' => 'default-accent',
552
                'TextLinkColor' => 'default-accent',
553
            ]);
554
        }
555
    }
556
}
557