Passed
Push — master ( 506e36...09aec9 )
by Robbie
03:05
created

BaseElement::forTemplate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace DNADesign\Elemental\Models;
4
5
use DNADesign\Elemental\Controllers\ElementController;
6
use DNADesign\Elemental\Forms\TextCheckboxGroupField;
7
use Exception;
8
use SilverStripe\CMS\Controllers\CMSPageEditController;
9
use SilverStripe\CMS\Model\SiteTree;
10
use SilverStripe\Control\Controller;
11
use SilverStripe\Control\Director;
12
use SilverStripe\Core\ClassInfo;
13
use SilverStripe\Core\Injector\Injector;
14
use SilverStripe\Forms\CheckboxField;
15
use SilverStripe\Forms\DropdownField;
16
use SilverStripe\Forms\FieldList;
17
use SilverStripe\Forms\HiddenField;
18
use SilverStripe\Forms\NumericField;
19
use SilverStripe\Forms\TextField;
20
use SilverStripe\ORM\DataObject;
21
use SilverStripe\ORM\FieldType\DBField;
22
use SilverStripe\ORM\FieldType\DBHTMLText;
23
use SilverStripe\Security\Member;
24
use SilverStripe\Security\Permission;
25
use SilverStripe\Versioned\Versioned;
26
use SilverStripe\VersionedAdmin\Forms\HistoryViewerField;
27
use SilverStripe\View\ArrayData;
28
use SilverStripe\View\Parsers\URLSegmentFilter;
29
use SilverStripe\View\Requirements;
30
31
/**
32
 * Class BaseElement
33
 * @package DNADesign\Elemental\Models
34
 *
35
 * @property string $Title
36
 * @property bool $ShowTitle
37
 * @property int $Sort
38
 * @property string $ExtraClass
39
 * @property string $Style
40
 *
41
 * @method ElementalArea Parent()
42
 */
43
class BaseElement extends DataObject
44
{
45
    /**
46
     * Override this on your custom elements to specify a CSS icon class
47
     *
48
     * @var string
49
     */
50
    private static $icon = 'font-icon-block-layout';
0 ignored issues
show
introduced by
The private property $icon is not used, and could be removed.
Loading history...
51
52
    /**
53
     * Describe the purpose of this element
54
     *
55
     * @config
56
     * @var string
57
     */
58
    private static $description = 'Base element class';
0 ignored issues
show
introduced by
The private property $description is not used, and could be removed.
Loading history...
59
60
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
61
        'Title' => 'Varchar(255)',
62
        'ShowTitle' => 'Boolean',
63
        'Sort' => 'Int',
64
        'ExtraClass' => 'Varchar(255)',
65
        'Style' => 'Varchar(255)'
66
    ];
67
68
    private static $has_one = [
0 ignored issues
show
introduced by
The private property $has_one is not used, and could be removed.
Loading history...
69
        'Parent' => ElementalArea::class
70
    ];
71
72
    private static $extensions = [
0 ignored issues
show
introduced by
The private property $extensions is not used, and could be removed.
Loading history...
73
        Versioned::class
74
    ];
75
76
    private static $versioned_gridfield_extensions = true;
0 ignored issues
show
introduced by
The private property $versioned_gridfield_extensions is not used, and could be removed.
Loading history...
77
78
    private static $table_name = 'Element';
0 ignored issues
show
introduced by
The private property $table_name is not used, and could be removed.
Loading history...
79
80
    /**
81
     * @var string
82
     */
83
    private static $controller_class = ElementController::class;
84
85
    /**
86
     * @var string
87
     */
88
    private static $controller_template = 'ElementHolder';
0 ignored issues
show
introduced by
The private property $controller_template is not used, and could be removed.
Loading history...
89
90
    /**
91
     * @var ElementController
92
     */
93
    protected $controller;
94
95
    private static $default_sort = 'Sort';
0 ignored issues
show
introduced by
The private property $default_sort is not used, and could be removed.
Loading history...
96
97
    private static $singular_name = 'block';
0 ignored issues
show
introduced by
The private property $singular_name is not used, and could be removed.
Loading history...
98
99
    private static $plural_name = 'blocks';
0 ignored issues
show
introduced by
The private property $plural_name is not used, and could be removed.
Loading history...
100
101
    private static $summary_fields = [
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
102
        'EditorPreview' => 'Summary'
103
    ];
104
105
    /**
106
     * @config
107
     * @var array
108
     */
109
    private static $styles = [];
0 ignored issues
show
introduced by
The private property $styles is not used, and could be removed.
Loading history...
110
111
    private static $searchable_fields = [
0 ignored issues
show
introduced by
The private property $searchable_fields is not used, and could be removed.
Loading history...
112
        'ID' => [
113
            'field' => NumericField::class,
114
        ],
115
        'Title',
116
        'LastEdited'
117
    ];
118
119
    /**
120
     * Enable for backwards compatibility
121
     *
122
     * @var boolean
123
     */
124
    private static $disable_pretty_anchor_name = false;
125
126
    /**
127
     * Store used anchor names, this is to avoid title clashes
128
     * when calling 'getAnchor'
129
     *
130
     * @var array
131
     */
132
    protected static $used_anchors = [];
133
134
    /**
135
     * For caching 'getAnchor'
136
     *
137
     * @var string
138
     */
139
    protected $anchor = null;
140
141
    /**
142
     * Basic permissions, defaults to page perms where possible.
143
     *
144
     * @param Member $member
145
     * @return boolean
146
     */
147
    public function canView($member = null)
148
    {
149
        $extended = $this->extendedCan(__FUNCTION__, $member);
150
        if ($extended !== null) {
151
            return $extended;
152
        }
153
154
        if ($this->hasMethod('getPage')) {
155
            if ($page = $this->getPage()) {
156
                return $page->canView($member);
157
            }
158
        }
159
160
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
161
    }
162
163
    /**
164
     * Basic permissions, defaults to page perms where possible.
165
     *
166
     * @param Member $member
167
     *
168
     * @return boolean
169
     */
170
    public function canEdit($member = null)
171
    {
172
        $extended = $this->extendedCan(__FUNCTION__, $member);
173
        if ($extended !== null) {
174
            return $extended;
175
        }
176
177
        if ($this->hasMethod('getPage')) {
178
            if ($page = $this->getPage()) {
179
                return $page->canEdit($member);
180
            }
181
        }
182
183
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
184
    }
185
186
    /**
187
     * Basic permissions, defaults to page perms where possible.
188
     *
189
     * Uses archive not delete so that current stage is respected i.e if a
190
     * element is not published, then it can be deleted by someone who doesn't
191
     * have publishing permissions.
192
     *
193
     * @param Member $member
194
     *
195
     * @return boolean
196
     */
197
    public function canDelete($member = null)
198
    {
199
        $extended = $this->extendedCan(__FUNCTION__, $member);
200
        if ($extended !== null) {
201
            return $extended;
202
        }
203
204
        if ($this->hasMethod('getPage')) {
205
            if ($page = $this->getPage()) {
206
                return $page->canArchive($member);
207
            }
208
        }
209
210
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
211
    }
212
213
    /**
214
     * Basic permissions, defaults to page perms where possible.
215
     *
216
     * @param Member $member
217
     * @param array $context
218
     *
219
     * @return boolean
220
     */
221
    public function canCreate($member = null, $context = array())
222
    {
223
        $extended = $this->extendedCan(__FUNCTION__, $member);
224
        if ($extended !== null) {
225
            return $extended;
226
        }
227
228
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
229
    }
230
231
    /**
232
     * @throws \SilverStripe\ORM\ValidationException
233
     */
234
    public function onBeforeWrite()
235
    {
236
        parent::onBeforeWrite();
237
238
        if ($areaID = $this->ParentID) {
0 ignored issues
show
Bug Best Practice introduced by
The property ParentID does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __get, consider adding a @property annotation.
Loading history...
239
            if ($elementalArea = ElementalArea::get()->byID($areaID)) {
240
                $elementalArea->write();
241
            }
242
        }
243
244
        if (!$this->Sort) {
245
            $parentID = ($this->ParentID) ? $this->ParentID : 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $parentID is dead and can be removed.
Loading history...
246
247
            $this->Sort = static::get()->max('Sort') + 1;
248
        }
249
    }
250
251
    public function getCMSFields()
252
    {
253
        $this->beforeUpdateCMSFields(function (FieldList $fields) {
254
            // Remove relationship fields
255
            $fields->removeByName('ParentID');
256
            $fields->removeByName('Sort');
257
258
            $fields->addFieldToTab(
259
                'Root.Settings',
260
                TextField::create('ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
261
                    ->setAttribute(
262
                        'placeholder',
263
                        _t(__CLASS__ . '.ExtraCssClassesPlaceholder', 'my_class another_class')
264
                    )
265
            );
266
267
            // Add a combined field for "Title" and "Displayed" checkbox in a Bootstrap input group
268
            $fields->removeByName('ShowTitle');
269
            $fields->replaceField(
270
                'Title',
271
                TextCheckboxGroupField::create(
272
                    TextField::create('Title', _t(__CLASS__ . '.TitleLabel', 'Title (displayed if checked)')),
273
                    CheckboxField::create('ShowTitle', _t(__CLASS__ . '.ShowTitleLabel', 'Displayed'))
274
                )
275
                    ->setName('TitleAndDisplayed')
276
            );
277
278
            // Rename the "Main" tab
279
            $fields->fieldByName('Root.Main')
280
                ->setTitle(_t(__CLASS__ . '.MainTabLabel', 'Content'));
281
282
            $fields->addFieldsToTab('Root.Main', [
283
                HiddenField::create('AbsoluteLink', false, Director::absoluteURL($this->PreviewLink())),
284
                HiddenField::create('LiveLink', false, Director::absoluteURL($this->Link())),
285
                HiddenField::create('StageLink', false, Director::absoluteURL($this->PreviewLink())),
286
            ]);
287
288
            $styles = $this->config()->get('styles');
289
290
            if ($styles && count($styles) > 0) {
291
                $styleDropdown = DropdownField::create('Style', _t(__CLASS__.'.STYLE', 'Style variation'), $styles);
292
293
                $fields->insertBefore($styleDropdown, 'ExtraClass');
0 ignored issues
show
Bug introduced by
'ExtraClass' of type string is incompatible with the type SilverStripe\Forms\FormField expected by parameter $item of SilverStripe\Forms\FieldList::insertBefore(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

293
                $fields->insertBefore($styleDropdown, /** @scrutinizer ignore-type */ 'ExtraClass');
Loading history...
294
295
                $styleDropdown->setEmptyString(_t(__CLASS__.'.CUSTOM_STYLES', 'Select a style..'));
296
            } else {
297
                $fields->removeByName('Style');
298
            }
299
300
            // Support for new history viewer in SS 4.2+
301
            if (class_exists(HistoryViewerField::class)) {
302
                Requirements::javascript('dnadesign/silverstripe-elemental:client/dist/js/bundle.js');
303
304
                $historyViewer = HistoryViewerField::create('ElementHistory');
305
                $fields->addFieldToTab('Root.History', $historyViewer);
306
307
                $fields->fieldByName('Root.History')->addExtraClass('elemental-block__history-tab');
308
            }
309
        });
310
311
        return parent::getCMSFields();
312
    }
313
314
    /**
315
     * Get the type of the current block, for use in GridField summaries, block
316
     * type dropdowns etc. Examples are "Content", "File", "Media", etc.
317
     *
318
     * @return string
319
     */
320
    public function getType()
321
    {
322
        return _t(__CLASS__ . '.BlockType', 'Block');
323
    }
324
325
    /**
326
     * @param ElementController $controller
327
     *
328
     * @return $this
329
     */
330
    public function setController($controller)
331
    {
332
        $this->controller = $controller;
333
334
        return $this;
335
    }
336
337
    /**
338
     * @throws Exception If the specified controller class doesn't exist
339
     *
340
     * @return ElementController
341
     */
342
    public function getController()
343
    {
344
        if ($this->controller) {
345
            return $this->controller;
346
        }
347
348
        $controllerClass = self::config()->controller_class;
349
350
        if (!class_exists($controllerClass)) {
351
            throw new Exception(
352
                'Could not find controller class ' . $controllerClass . ' as defined in ' . static::class
353
            );
354
        }
355
356
        $this->controller = Injector::inst()->create($controllerClass, $this);
357
        $this->controller->doInit();
358
359
        return $this->controller;
360
    }
361
362
    /**
363
     * @return Controller
364
     */
365
    public function Top()
366
    {
367
        return (Controller::has_curr()) ? Controller::curr() : null;
368
    }
369
370
    /**
371
     * Default way to render element in templates. Note that all blocks should
372
     * be rendered through their {@link ElementController} class as this
373
     * contains the holder styles.
374
     *
375
     * @return string|null HTML
376
     */
377
    public function forTemplate($holder = true)
378
    {
379
        $templates = $this->getRenderTemplates();
380
381
        if ($templates) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $templates of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
382
            return $this->renderWith($templates);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->renderWith($templates) returns the type SilverStripe\ORM\FieldType\DBHTMLText which is incompatible with the documented return type null|string.
Loading history...
383
        }
384
385
        return null;
386
    }
387
388
    /**
389
     * @param string $suffix
390
     *
391
     * @return array
392
     */
393
    public function getRenderTemplates($suffix = '')
394
    {
395
        $classes = ClassInfo::ancestry($this->ClassName);
396
        $classes[static::class] = static::class;
397
        $classes = array_reverse($classes);
398
        $templates = [];
399
400
        foreach ($classes as $key => $class) {
401
            if ($class == BaseElement::class) {
402
                continue;
403
            }
404
405
            if ($class == DataObject::class) {
406
                break;
407
            }
408
409
            if ($style = $this->Style) {
410
                $templates[$class][] = $class . $suffix . '_'. $this->getAreaRelationName() . '_' . $style;
411
                $templates[$class][] = $class . $suffix . '_' . $style;
412
            }
413
            $templates[$class][] = $class . $suffix . '_'. $this->getAreaRelationName();
414
            $templates[$class][] = $class . $suffix;
415
        }
416
417
        $this->extend('updateRenderTemplates', $templates, $suffix);
418
419
        $templateFlat = [];
420
        foreach ($templates as $class => $variations) {
421
            $templateFlat = array_merge($templateFlat, $variations);
422
        }
423
424
        return $templateFlat;
425
    }
426
427
    /**
428
     * Strip all namespaces from class namespace.
429
     *
430
     * @param string $classname e.g. "\Fully\Namespaced\Class"
431
     *
432
     * @return string following the param example, "Class"
433
     */
434
    protected function stripNamespacing($classname)
435
    {
436
        $classParts = explode('\\', $classname);
437
        return array_pop($classParts);
438
    }
439
440
    /**
441
     * @return string
442
     */
443
    public function getSimpleClassName()
444
    {
445
        return strtolower($this->sanitiseClassName($this->ClassName, '__'));
446
    }
447
448
    /**
449
     * @return null|DataObject
450
     * @throws \Psr\Container\NotFoundExceptionInterface
451
     * @throws \SilverStripe\ORM\ValidationException
452
     */
453
    public function getPage()
454
    {
455
        $area = $this->Parent();
456
457
        if ($area instanceof ElementalArea && $area->exists()) {
458
            return $area->getOwnerPage();
459
        }
460
461
        return null;
462
    }
463
464
    /**
465
     * Get a unique anchor name
466
     *
467
     * @return string
468
     */
469
    public function getAnchor()
470
    {
471
        if ($this->anchor !== null) {
472
            return $this->anchor;
473
        }
474
475
        $anchorTitle = '';
476
477
        if (!$this->config()->disable_pretty_anchor_name) {
478
            if ($this->hasMethod('getAnchorTitle')) {
479
                $anchorTitle = $this->getAnchorTitle();
0 ignored issues
show
Bug introduced by
The method getAnchorTitle() does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

479
                /** @scrutinizer ignore-call */ 
480
                $anchorTitle = $this->getAnchorTitle();
Loading history...
480
            } elseif ($this->config()->enable_title_in_template) {
481
                $anchorTitle = $this->getField('Title');
482
            }
483
        }
484
485
        if (!$anchorTitle) {
486
            $anchorTitle = 'e'.$this->ID;
487
        }
488
489
        $filter = URLSegmentFilter::create();
490
        $titleAsURL = $filter->filter($anchorTitle);
491
492
        // Ensure that this anchor name isn't already in use
493
        // ie. If two elemental blocks have the same title, it'll append '-2', '-3'
494
        $result = $titleAsURL;
495
        $count = 1;
496
        while (isset(self::$used_anchors[$result]) && self::$used_anchors[$result] !== $this->ID) {
497
            ++$count;
498
            $result = $titleAsURL . '-' . $count;
499
        }
500
        self::$used_anchors[$result] = $this->ID;
501
        return $this->anchor = $result;
502
    }
503
504
    /**
505
     * @param string|null $action
506
     * @return string|null
507
     * @throws \Psr\Container\NotFoundExceptionInterface
508
     * @throws \SilverStripe\ORM\ValidationException
509
     */
510
    public function AbsoluteLink($action = null)
511
    {
512
        if ($page = $this->getPage()) {
513
            $link = $page->AbsoluteLink($action) . '#' . $this->getAnchor();
514
515
            return $link;
516
        }
517
518
        return null;
519
    }
520
521
    /**
522
     * @param string|null $action
523
     * @return string
524
     * @throws \Psr\Container\NotFoundExceptionInterface
525
     * @throws \SilverStripe\ORM\ValidationException
526
     */
527
    public function Link($action = null)
528
    {
529
        if ($page = $this->getPage()) {
530
            $link = $page->Link($action) . '#' . $this->getAnchor();
531
532
            $this->extend('updateLink', $link);
533
534
            return $link;
535
        }
536
537
        return null;
538
    }
539
540
    /**
541
     * @param string|null $action
542
     * @return string
543
     * @throws \Psr\Container\NotFoundExceptionInterface
544
     * @throws \SilverStripe\ORM\ValidationException
545
     */
546
    public function PreviewLink($action = null)
547
    {
548
        $action = $action . '?ElementalPreview=' . mt_rand();
549
        $link = $this->Link($action);
550
        $this->extend('updatePreviewLink', $link);
551
552
        return $link;
553
    }
554
555
    /**
556
     * @return boolean
557
     */
558
    public function isCMSPreview()
559
    {
560
        if (Controller::has_curr()) {
561
            $controller = Controller::curr();
562
563
            if ($controller->getRequest()->requestVar('CMSPreview')) {
564
                return true;
565
            }
566
        }
567
568
        return false;
569
    }
570
571
    /**
572
     * @return null|string
573
     * @throws \Psr\Container\NotFoundExceptionInterface
574
     * @throws \SilverStripe\ORM\ValidationException
575
     */
576
    public function CMSEditLink()
577
    {
578
        $relationName = $this->getAreaRelationName();
579
        $page = $this->getPage(true);
0 ignored issues
show
Unused Code introduced by
The call to DNADesign\Elemental\Models\BaseElement::getPage() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

579
        /** @scrutinizer ignore-call */ 
580
        $page = $this->getPage(true);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
580
581
        if (!$page) {
582
            return null;
583
        }
584
585
        $editLinkPrefix = '';
586
        if (!$page instanceof SiteTree && method_exists($page, 'CMSEditLink')) {
587
            $editLinkPrefix = Controller::join_links($page->CMSEditLink(), 'ItemEditForm');
588
        } else {
589
            $editLinkPrefix = Controller::join_links(
590
                singleton(CMSPageEditController::class)->Link('EditForm'),
591
                $page->ID
592
            );
593
        }
594
595
        $link = Controller::join_links(
596
            $editLinkPrefix,
597
            'field/' . $relationName . '/item/',
598
            $this->ID
599
        );
600
601
        $link = Controller::join_links(
602
            $link,
603
            'edit'
604
        );
605
606
        $this->extend('updateCMSEditLink', $link);
607
608
        return $link;
609
    }
610
611
    /**
612
     * Retrieve a elemental area relation for creating cms links
613
     *
614
     * @return int|string The name of a valid elemental area relation
615
     * @throws \Psr\Container\NotFoundExceptionInterface
616
     * @throws \SilverStripe\ORM\ValidationException
617
     */
618
    public function getAreaRelationName()
619
    {
620
        $page = $this->getPage();
621
622
        if ($page) {
623
            $has_one = $page->config()->get('has_one');
624
            $area = $this->Parent();
625
626
            foreach ($has_one as $relationName => $relationClass) {
627
                if ($page instanceof BaseElement && $relationName === 'Parent') {
628
                    continue;
629
                }
630
                if ($relationClass === $area->ClassName && $page->{$relationName}()->ID === $area->ID) {
631
                    return $relationName;
632
                }
633
            }
634
        }
635
636
        return 'ElementalArea';
637
    }
638
639
    /**
640
     * Sanitise a model class' name for inclusion in a link.
641
     *
642
     * @return string
643
     */
644
    public function sanitiseClassName($class, $delimiter = '-')
645
    {
646
        return str_replace('\\', $delimiter, $class);
647
    }
648
649
    public function unsanitiseClassName($class, $delimiter = '-')
650
    {
651
        return str_replace($delimiter, '\\', $class);
652
    }
653
654
    /**
655
     * @return null|string
656
     * @throws \Psr\Container\NotFoundExceptionInterface
657
     * @throws \SilverStripe\ORM\ValidationException
658
     */
659
    public function getEditLink()
660
    {
661
        return $this->CMSEditLink();
662
    }
663
664
    /**
665
     * @return DBField|null
666
     * @throws \Psr\Container\NotFoundExceptionInterface
667
     * @throws \SilverStripe\ORM\ValidationException
668
     */
669
    public function PageCMSEditLink()
670
    {
671
        if ($page = $this->getPage()) {
672
            return DBField::create_field('HTMLText', sprintf(
673
                '<a href="%s">%s</a>',
674
                $page->CMSEditLink(),
675
                $page->Title
676
            ));
677
        }
678
679
        return null;
680
    }
681
682
    /**
683
     * @return string
684
     */
685
    public function getMimeType()
686
    {
687
        return 'text/html';
688
    }
689
690
    /**
691
     * This can be overridden on child elements to create a summary for display
692
     * in GridFields.
693
     *
694
     * @return string
695
     */
696
    public function getSummary()
697
    {
698
        return '';
699
    }
700
701
702
    /**
703
     * Generate markup for element type icons suitable for use in GridFields.
704
     *
705
     * @return null|DBHTMLText
706
     */
707
    public function getIcon()
708
    {
709
        $data = ArrayData::create([]);
710
711
        $iconClass = $this->config()->get('icon');
712
        if ($iconClass) {
713
            $data->IconClass = $iconClass;
714
715
            // Add versioned states (rendered as a circle over the icon)
716
            if ($this->hasExtension(Versioned::class)) {
717
                $data->IsVersioned = true;
718
                if ($this->isOnDraftOnly()) {
0 ignored issues
show
Bug introduced by
The method isOnDraftOnly() does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

718
                if ($this->/** @scrutinizer ignore-call */ isOnDraftOnly()) {
Loading history...
719
                    $data->VersionState = 'draft';
720
                    $data->VersionStateTitle = _t(
721
                        'SilverStripe\\Versioned\\VersionedGridFieldState\\VersionedGridFieldState.ADDEDTODRAFTHELP',
722
                        'Item has not been published yet'
723
                    );
724
                } elseif ($this->isModifiedOnDraft()) {
0 ignored issues
show
Bug introduced by
The method isModifiedOnDraft() does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

724
                } elseif ($this->/** @scrutinizer ignore-call */ isModifiedOnDraft()) {
Loading history...
725
                    $data->VersionState = 'modified';
726
                    $data->VersionStateTitle = $data->VersionStateTitle = _t(
727
                        'SilverStripe\\Versioned\\VersionedGridFieldState\\VersionedGridFieldState.MODIFIEDONDRAFTHELP',
728
                        'Item has unpublished changes'
729
                    );
730
                }
731
            }
732
733
            return $data->renderWith(__CLASS__ . '/PreviewIcon');
734
        }
735
736
        return null;
737
    }
738
739
    /**
740
     * Get a description for this content element, if available
741
     *
742
     * @return string
743
     */
744
    public function getDescription()
745
    {
746
        $description = $this->config()->uninherited('description');
747
        if ($description) {
748
            return _t(__CLASS__ . '.Description', $description);
749
        }
750
        return '';
751
    }
752
753
    /**
754
     * Generate markup for element type, with description suitable for use in
755
     * GridFields.
756
     *
757
     * @return DBField
758
     */
759
    public function getTypeNice()
760
    {
761
        $description = $this->getDescription();
762
        $desc = ($description) ? ' <span class="element__note"> &mdash; ' . $description . '</span>' : '';
763
764
        return DBField::create_field(
765
            'HTMLVarchar',
766
            $this->getType() . $desc
767
        );
768
    }
769
770
    /**
771
     * @return \SilverStripe\ORM\FieldType\DBHTMLText
772
     */
773
    public function getEditorPreview()
774
    {
775
        $templates = $this->getRenderTemplates('_EditorPreview');
776
        $templates[] = BaseElement::class . '_EditorPreview';
777
778
        return $this->renderWith($templates);
779
    }
780
781
    /**
782
     * @return Member
783
     */
784
    public function getAuthor()
785
    {
786
        if ($this->AuthorID) {
0 ignored issues
show
Bug Best Practice introduced by
The property AuthorID does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __get, consider adding a @property annotation.
Loading history...
787
            return Member::get()->byId($this->AuthorID);
788
        }
789
790
        return null;
791
    }
792
793
    /**
794
     * Get a user defined style variant for this element, if available
795
     *
796
     * @return string
797
     */
798
    public function getStyleVariant()
799
    {
800
        $style = $this->Style;
801
        $styles = $this->config()->get('styles');
802
803
        if (isset($styles[$style])) {
804
            $style = strtolower($style);
805
        } else {
806
            $style = '';
807
        }
808
809
        $this->extend('updateStyleVariant', $style);
810
811
        return $style;
812
    }
813
814
    /**
815
     * @return mixed|null
816
     * @throws \Psr\Container\NotFoundExceptionInterface
817
     * @throws \SilverStripe\ORM\ValidationException
818
     */
819
    public function getPageTitle()
820
    {
821
        $page = $this->getPage();
822
823
        if ($page) {
824
            return $page->Title;
825
        }
826
827
        return null;
828
    }
829
}
830