Completed
Push — master ( b42f51...80b671 )
by Robbie
01:20 queued 01:17
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 10
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
     * Increment the sort order if one hasn't been already defined. This ensures that new elements are created
233
     * at the end of the list by default.
234
     *
235
     * {@inheritDoc}
236
     */
237
    public function onBeforeWrite()
238
    {
239
        parent::onBeforeWrite();
240
241
        if (!$this->Sort) {
242
            $this->Sort = static::get()->max('Sort') + 1;
243
        }
244
    }
245
246
    public function getCMSFields()
247
    {
248
        $this->beforeUpdateCMSFields(function (FieldList $fields) {
249
            // Remove relationship fields
250
            $fields->removeByName('ParentID');
251
            $fields->removeByName('Sort');
252
253
            $fields->addFieldToTab(
254
                'Root.Settings',
255
                TextField::create('ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
256
                    ->setAttribute(
257
                        'placeholder',
258
                        _t(__CLASS__ . '.ExtraCssClassesPlaceholder', 'my_class another_class')
259
                    )
260
            );
261
262
            // Add a combined field for "Title" and "Displayed" checkbox in a Bootstrap input group
263
            $fields->removeByName('ShowTitle');
264
            $fields->replaceField(
265
                'Title',
266
                TextCheckboxGroupField::create(
267
                    TextField::create('Title', _t(__CLASS__ . '.TitleLabel', 'Title (displayed if checked)')),
268
                    CheckboxField::create('ShowTitle', _t(__CLASS__ . '.ShowTitleLabel', 'Displayed'))
269
                )
270
                    ->setName('TitleAndDisplayed')
271
            );
272
273
            // Rename the "Main" tab
274
            $fields->fieldByName('Root.Main')
275
                ->setTitle(_t(__CLASS__ . '.MainTabLabel', 'Content'));
276
277
            $fields->addFieldsToTab('Root.Main', [
278
                HiddenField::create('AbsoluteLink', false, Director::absoluteURL($this->PreviewLink())),
279
                HiddenField::create('LiveLink', false, Director::absoluteURL($this->Link())),
280
                HiddenField::create('StageLink', false, Director::absoluteURL($this->PreviewLink())),
281
            ]);
282
283
            $styles = $this->config()->get('styles');
284
285
            if ($styles && count($styles) > 0) {
286
                $styleDropdown = DropdownField::create('Style', _t(__CLASS__.'.STYLE', 'Style variation'), $styles);
287
288
                $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

288
                $fields->insertBefore($styleDropdown, /** @scrutinizer ignore-type */ 'ExtraClass');
Loading history...
289
290
                $styleDropdown->setEmptyString(_t(__CLASS__.'.CUSTOM_STYLES', 'Select a style..'));
291
            } else {
292
                $fields->removeByName('Style');
293
            }
294
295
            // Support for new history viewer in SS 4.2+
296
            if (class_exists(HistoryViewerField::class)) {
297
                Requirements::javascript('dnadesign/silverstripe-elemental:client/dist/js/bundle.js');
298
299
                $historyViewer = HistoryViewerField::create('ElementHistory');
300
                $fields->addFieldToTab('Root.History', $historyViewer);
301
302
                $fields->fieldByName('Root.History')
303
                    ->addExtraClass('elemental-block__history-tab tab--history-viewer');
304
            }
305
        });
306
307
        return parent::getCMSFields();
308
    }
309
310
    /**
311
     * Get the type of the current block, for use in GridField summaries, block
312
     * type dropdowns etc. Examples are "Content", "File", "Media", etc.
313
     *
314
     * @return string
315
     */
316
    public function getType()
317
    {
318
        return _t(__CLASS__ . '.BlockType', 'Block');
319
    }
320
321
    /**
322
     * @param ElementController $controller
323
     *
324
     * @return $this
325
     */
326
    public function setController($controller)
327
    {
328
        $this->controller = $controller;
329
330
        return $this;
331
    }
332
333
    /**
334
     * @throws Exception If the specified controller class doesn't exist
335
     *
336
     * @return ElementController
337
     */
338
    public function getController()
339
    {
340
        if ($this->controller) {
341
            return $this->controller;
342
        }
343
344
        $controllerClass = self::config()->controller_class;
345
346
        if (!class_exists($controllerClass)) {
347
            throw new Exception(
348
                'Could not find controller class ' . $controllerClass . ' as defined in ' . static::class
349
            );
350
        }
351
352
        $this->controller = Injector::inst()->create($controllerClass, $this);
353
        $this->controller->doInit();
354
355
        return $this->controller;
356
    }
357
358
    /**
359
     * @return Controller
360
     */
361
    public function Top()
362
    {
363
        return (Controller::has_curr()) ? Controller::curr() : null;
364
    }
365
366
    /**
367
     * Default way to render element in templates. Note that all blocks should
368
     * be rendered through their {@link ElementController} class as this
369
     * contains the holder styles.
370
     *
371
     * @return string|null HTML
372
     */
373
    public function forTemplate($holder = true)
374
    {
375
        $templates = $this->getRenderTemplates();
376
377
        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...
378
            return $this->renderWith($templates);
379
        }
380
381
        return null;
382
    }
383
384
    /**
385
     * @param string $suffix
386
     *
387
     * @return array
388
     */
389
    public function getRenderTemplates($suffix = '')
390
    {
391
        $classes = ClassInfo::ancestry($this->ClassName);
392
        $classes[static::class] = static::class;
393
        $classes = array_reverse($classes);
394
        $templates = [];
395
396
        foreach ($classes as $key => $class) {
397
            if ($class == BaseElement::class) {
398
                continue;
399
            }
400
401
            if ($class == DataObject::class) {
402
                break;
403
            }
404
405
            if ($style = $this->Style) {
406
                $templates[$class][] = $class . $suffix . '_'. $this->getAreaRelationName() . '_' . $style;
407
                $templates[$class][] = $class . $suffix . '_' . $style;
408
            }
409
            $templates[$class][] = $class . $suffix . '_'. $this->getAreaRelationName();
410
            $templates[$class][] = $class . $suffix;
411
        }
412
413
        $this->extend('updateRenderTemplates', $templates, $suffix);
414
415
        $templateFlat = [];
416
        foreach ($templates as $class => $variations) {
417
            $templateFlat = array_merge($templateFlat, $variations);
418
        }
419
420
        return $templateFlat;
421
    }
422
423
    /**
424
     * Strip all namespaces from class namespace.
425
     *
426
     * @param string $classname e.g. "\Fully\Namespaced\Class"
427
     *
428
     * @return string following the param example, "Class"
429
     */
430
    protected function stripNamespacing($classname)
431
    {
432
        $classParts = explode('\\', $classname);
433
        return array_pop($classParts);
434
    }
435
436
    /**
437
     * @return string
438
     */
439
    public function getSimpleClassName()
440
    {
441
        return strtolower($this->sanitiseClassName($this->ClassName, '__'));
442
    }
443
444
    /**
445
     * @return null|DataObject
446
     * @throws \Psr\Container\NotFoundExceptionInterface
447
     * @throws \SilverStripe\ORM\ValidationException
448
     */
449
    public function getPage()
450
    {
451
        $area = $this->Parent();
452
453
        if ($area instanceof ElementalArea && $area->exists()) {
454
            return $area->getOwnerPage();
455
        }
456
457
        return null;
458
    }
459
460
    /**
461
     * Get a unique anchor name
462
     *
463
     * @return string
464
     */
465
    public function getAnchor()
466
    {
467
        if ($this->anchor !== null) {
468
            return $this->anchor;
469
        }
470
471
        $anchorTitle = '';
472
473
        if (!$this->config()->disable_pretty_anchor_name) {
474
            if ($this->hasMethod('getAnchorTitle')) {
475
                $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

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

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

723
                if ($this->/** @scrutinizer ignore-call */ isOnDraftOnly()) {
Loading history...
724
                    $data->VersionState = 'draft';
725
                    $data->VersionStateTitle = _t(
726
                        'SilverStripe\\Versioned\\VersionedGridFieldState\\VersionedGridFieldState.ADDEDTODRAFTHELP',
727
                        'Item has not been published yet'
728
                    );
729
                } 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

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