Passed
Pull Request — master (#221)
by Ingo
03:53
created

BaseElement::getAnchor()   C

Complexity

Conditions 8
Paths 17

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 33
rs 5.3846
cc 8
eloc 19
nc 17
nop 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 = array();
399
400
        foreach ($classes as $key => $value) {
401
            if ($value == BaseElement::class) {
402
                continue;
403
            }
404
405
            if ($value == DataObject::class) {
406
                break;
407
            }
408
409
            $templates[] = $value . $suffix . '_'. $this->getAreaRelationName();
410
            $templates[] = $value . $suffix;
411
        }
412
413
        return $templates;
414
    }
415
416
    /**
417
     * Strip all namespaces from class namespace.
418
     *
419
     * @param string $classname e.g. "\Fully\Namespaced\Class"
420
     *
421
     * @return string following the param example, "Class"
422
     */
423
    protected function stripNamespacing($classname)
424
    {
425
        $classParts = explode('\\', $classname);
426
        return array_pop($classParts);
427
    }
428
429
    /**
430
     * @return string
431
     */
432
    public function getSimpleClassName()
433
    {
434
        return strtolower($this->sanitiseClassName($this->ClassName, '__'));
435
    }
436
437
    /**
438
     * @return null|DataObject
439
     * @throws \Psr\Container\NotFoundExceptionInterface
440
     * @throws \SilverStripe\ORM\ValidationException
441
     */
442
    public function getPage()
443
    {
444
        $area = $this->Parent();
445
446
        if ($area instanceof ElementalArea && $area->exists()) {
447
            return $area->getOwnerPage();
448
        }
449
450
        return null;
451
    }
452
453
    /**
454
     * Get a unique anchor name
455
     *
456
     * @return string
457
     */
458
    public function getAnchor()
459
    {
460
        if ($this->anchor !== null) {
461
            return $this->anchor;
462
        }
463
464
        $anchorTitle = '';
465
466
        if (!$this->config()->disable_pretty_anchor_name) {
467
            if ($this->hasMethod('getAnchorTitle')) {
468
                $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

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

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

707
                if ($this->/** @scrutinizer ignore-call */ isOnDraftOnly()) {
Loading history...
708
                    $data->VersionState = 'draft';
709
                    $data->VersionStateTitle = _t(
710
                        'SilverStripe\\Versioned\\VersionedGridFieldState\\VersionedGridFieldState.ADDEDTODRAFTHELP',
711
                        'Item has not been published yet'
712
                    );
713
                } 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

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