Completed
Push — master ( 5c66f6...d96a4f )
by Robbie
10s
created

BaseElement::getCMSFields()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 57
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 33
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 57
rs 9.0309

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace DNADesign\Elemental\Models;
4
5
use Exception;
6
use DNADesign\Elemental\Forms\ElementalGridFieldHistoryButton;
7
use DNADesign\Elemental\Forms\HistoricalVersionedGridFieldItemRequest;
8
use DNADesign\Elemental\Forms\TextCheckboxGroupField;
9
use DNADesign\Elemental\Controllers\ElementController;
10
use SilverStripe\CMS\Controllers\CMSPageEditController;
11
use SilverStripe\Control\Controller;
12
use SilverStripe\Control\Director;
13
use SilverStripe\Core\ClassInfo;
14
use SilverStripe\Core\Config\Config;
15
use SilverStripe\Core\Injector\Injector;
16
use SilverStripe\Forms\CheckboxField;
17
use SilverStripe\Forms\DropdownField;
18
use SilverStripe\Forms\FieldList;
19
use SilverStripe\Forms\HiddenField;
20
use SilverStripe\Forms\NumericField;
21
use SilverStripe\Forms\ReadonlyField;
22
use SilverStripe\Forms\TextField;
23
use SilverStripe\Forms\GridField\GridField;
24
use SilverStripe\Forms\GridField\GridFieldConfig_RecordViewer;
25
use SilverStripe\Forms\GridField\GridFieldDataColumns;
26
use SilverStripe\Forms\GridField\GridFieldDetailForm;
27
use SilverStripe\Forms\GridField\GridFieldPageCount;
28
use SilverStripe\Forms\GridField\GridFieldSortableHeader;
29
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
30
use SilverStripe\Forms\GridField\GridFieldVersionedState;
31
use SilverStripe\Forms\GridField\GridFieldViewButton;
32
use SilverStripe\ORM\ArrayList;
33
use SilverStripe\ORM\CMSPreviewable;
34
use SilverStripe\ORM\DataObject;
35
use SilverStripe\ORM\DB;
36
use SilverStripe\ORM\FieldType\DBField;
37
use SilverStripe\ORM\Search\SearchContext;
38
use SilverStripe\Security\Permission;
39
use SilverStripe\Security\Member;
40
use SilverStripe\SiteConfig\SiteConfig;
41
use SilverStripe\Versioned\Versioned;
42
use SilverStripe\View\Parsers\URLSegmentFilter;
43
use SilverStripe\View\Requirements;
44
use SilverStripe\View\SSViewer;
45
use Symbiote\GridFieldExtensions\GridFieldTitleHeader;
46
47
class BaseElement extends DataObject implements CMSPreviewable
48
{
49
    /**
50
     * Override this on your custom elements to specify a CSS icon class
51
     *
52
     * @var string
53
     */
54
    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...
55
56
    /**
57
     * Describe the purpose of this element
58
     *
59
     * @config
60
     * @var string
61
     */
62
    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...
63
64
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
65
        'Title' => 'Varchar(255)',
66
        'ShowTitle' => 'Boolean',
67
        'Sort' => 'Int',
68
        'ExtraClass' => 'Varchar(255)',
69
        'Style' => 'Varchar(255)'
70
    ];
71
72
    private static $has_one = [
0 ignored issues
show
introduced by
The private property $has_one is not used, and could be removed.
Loading history...
73
        'Parent' => ElementalArea::class
74
    ];
75
76
    private static $extensions = [
0 ignored issues
show
introduced by
The private property $extensions is not used, and could be removed.
Loading history...
77
        Versioned::class
78
    ];
79
80
    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...
81
82
    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...
83
84
    /**
85
     * @var string
86
     */
87
    private static $controller_class = ElementController::class;
88
89
    /**
90
     * @var string
91
     */
92
    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...
93
94
    /**
95
     * @var ElementController
96
     */
97
    protected $controller;
98
99
    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...
100
101
    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...
102
103
    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...
104
105
    private static $summary_fields = [
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
106
        'EditorPreview' => 'Summary'
107
    ];
108
109
    /**
110
     * @config
111
     * @var array
112
     */
113
    private static $styles = [];
0 ignored issues
show
introduced by
The private property $styles is not used, and could be removed.
Loading history...
114
115
    private static $searchable_fields = [
0 ignored issues
show
introduced by
The private property $searchable_fields is not used, and could be removed.
Loading history...
116
        'ID' => [
117
            'field' => NumericField::class,
118
        ],
119
        'Title',
120
        'LastEdited'
121
    ];
122
123
    /**
124
     * Enable for backwards compatibility
125
     *
126
     * @var boolean
127
     */
128
    private static $disable_pretty_anchor_name = false;
129
130
    /**
131
     * Store used anchor names, this is to avoid title clashes
132
     * when calling 'getAnchor'
133
     *
134
     * @var array
135
     */
136
    protected static $_used_anchors = [];
137
138
    /**
139
     * For caching 'getAnchor'
140
     *
141
     * @var string
142
     */
143
    protected $_anchor = null;
144
145
    /**
146
     * Basic permissions, defaults to page perms where possible.
147
     *
148
     * @param Member $member
149
     *
150
     * @return boolean
151
     */
152
    public function canView($member = null)
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
        if ($this->hasMethod('getPage')) {
173
            if ($page = $this->getPage()) {
174
                return $page->canEdit($member);
175
            }
176
        }
177
178
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
179
    }
180
181
    /**
182
     * Basic permissions, defaults to page perms where possible.
183
     *
184
     * Uses archive not delete so that current stage is respected i.e if a
185
     * element is not published, then it can be deleted by someone who doesn't
186
     * have publishing permissions.
187
     *
188
     * @param Member $member
189
     *
190
     * @return boolean
191
     */
192
    public function canDelete($member = null)
193
    {
194
        if ($this->hasMethod('getPage')) {
195
            if ($page = $this->getPage()) {
196
                return $page->canArchive($member);
197
            }
198
        }
199
200
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
201
    }
202
203
    /**
204
     * Basic permissions, defaults to page perms where possible.
205
     *
206
     * @param Member $member
207
     * @param array $context
208
     *
209
     * @return boolean
210
     */
211
    public function canCreate($member = null, $context = array())
212
    {
213
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
214
    }
215
216
    public function onBeforeWrite()
217
    {
218
        parent::onBeforeWrite();
219
220
        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...
221
            if ($elementalArea = ElementalArea::get()->byID($areaID)) {
222
                $elementalArea->write();
223
            }
224
        }
225
226
        if (!$this->Sort) {
227
            $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...
228
229
            $this->Sort = static::get()->max('Sort') + 1;
0 ignored issues
show
Bug Best Practice introduced by
The property Sort does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
230
        }
231
    }
232
233
    public function getCMSFields()
234
    {
235
        $this->beforeUpdateCMSFields(function (FieldList $fields) {
236
            // Remove relationship fields
237
            $fields->removeByName('ParentID');
238
            $fields->removeByName('Sort');
239
240
            $fields->addFieldToTab(
241
                'Root.Settings',
242
                TextField::create('ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
0 ignored issues
show
Bug introduced by
'ExtraClass' of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

242
                TextField::create(/** @scrutinizer ignore-type */ 'ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
Loading history...
243
                    ->setAttribute(
244
                        'placeholder',
245
                        _t(__CLASS__ . '.ExtraCssClassesPlaceholder', 'my_class another_class')
246
                    )
247
            );
248
249
            // Add a combined field for "Title" and "Displayed" checkbox in a Bootstrap input group
250
            $fields->removeByName('ShowTitle');
251
            $fields->replaceField(
252
                'Title',
253
                TextCheckboxGroupField::create(
254
                    TextField::create('Title', _t(__CLASS__ . '.TitleLabel', 'Title (displayed if checked)')),
255
                    CheckboxField::create('ShowTitle', _t(__CLASS__ . '.ShowTitleLabel', 'Displayed'))
256
                )
257
                    ->setName('TitleAndDisplayed')
258
            );
259
260
            // Rename the "Main" tab
261
            $fields->fieldByName('Root.Main')
262
                ->setTitle(_t(__CLASS__ . '.MainTabLabel', 'Content'));
263
264
            $fields->addFieldsToTab('Root.Main', [
265
                HiddenField::create('AbsoluteLink', false, Director::absoluteURL($this->PreviewLink())),
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

265
                HiddenField::create('AbsoluteLink', /** @scrutinizer ignore-type */ false, Director::absoluteURL($this->PreviewLink())),
Loading history...
266
                HiddenField::create('LiveLink', false, Director::absoluteURL($this->Link())),
267
                HiddenField::create('StageLink', false, Director::absoluteURL($this->PreviewLink())),
268
            ]);
269
270
            $styles = $this->config()->get('styles');
271
272
            if ($styles && count($styles) > 0) {
273
                $styleDropdown = DropdownField::create('Style', _t(__CLASS__.'.STYLE', 'Style variation'), $styles);
274
275
                $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

275
                $fields->insertBefore($styleDropdown, /** @scrutinizer ignore-type */ 'ExtraClass');
Loading history...
276
277
                $styleDropdown->setEmptyString(_t(__CLASS__.'.CUSTOM_STYLES', 'Select a style..'));
278
            } else {
279
                $fields->removeByName('Style');
280
            }
281
282
            $history = $this->getHistoryFields();
283
284
            if ($history) {
285
                $fields->addFieldsToTab('Root.History', $history);
286
            }
287
        });
288
289
        return parent::getCMSFields();
290
    }
291
292
    /**
293
     * Returns the history fields for this element.
294
     *
295
     * @param  bool $checkLatestVersion Whether to check if this is the latest version. Prevents recursion, but can be
296
     *                                  overridden to get the history GridField if required.
297
     * @return FieldList
298
     */
299
    public function getHistoryFields($checkLatestVersion = true)
300
    {
301
        if ($checkLatestVersion && !$this->isLatestVersion()) {
0 ignored issues
show
Bug introduced by
The method isLatestVersion() 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

301
        if ($checkLatestVersion && !$this->/** @scrutinizer ignore-call */ isLatestVersion()) {
Loading history...
302
            // if viewing the history of the of page then don't show the history
303
            // fields as then we have recursion.
304
            return null;
305
        }
306
307
        Requirements::javascript('dnadesign/silverstripe-elemental:client/dist/js/bundle.js');
308
309
        $config = GridFieldConfig_RecordViewer::create();
310
        $config->removeComponentsByType(GridFieldPageCount::class);
311
        $config->removeComponentsByType(GridFieldToolbarHeader::class);
312
        // Replace the sortable ID column with a static header component
313
        $config->removeComponentsByType(GridFieldSortableHeader::class);
314
        $config->addComponent(new GridFieldTitleHeader);
315
316
        $config
317
            ->getComponentByType(GridFieldDetailForm::class)
318
            ->setItemRequestClass(HistoricalVersionedGridFieldItemRequest::class);
319
320
        $config->getComponentByType(GridFieldDataColumns::class)
321
            ->setDisplayFields([
322
                'Version' => '#',
323
                'RecordStatus' => _t(__CLASS__ . '.Record', 'Record'),
324
                'getAuthor.Name' => _t(__CLASS__ . '.Author', 'Author')
325
            ])
326
            ->setFieldFormatting([
327
                'RecordStatus' => '$VersionedStateNice <span class=\"element-history__date--small\">on $LastEditedNice</span>',
328
            ]);
329
330
        $config->removeComponentsByType(GridFieldViewButton::class);
331
        $config->addComponent(new ElementalGridFieldHistoryButton());
332
333
        $history = Versioned::get_all_versions(__CLASS__, $this->ID)
334
            ->sort('Version', 'DESC');
335
336
        return FieldList::create(
337
            GridField::create('History', '', $history, $config)
0 ignored issues
show
Bug introduced by
$history of type SilverStripe\ORM\DataList is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

337
            GridField::create('History', '', /** @scrutinizer ignore-type */ $history, $config)
Loading history...
Bug introduced by
'History' of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

337
            GridField::create(/** @scrutinizer ignore-type */ 'History', '', $history, $config)
Loading history...
338
                ->addExtraClass('elemental-block__history')
339
        );
340
    }
341
342
    /**
343
     * Get the type of the current block, for use in GridField summaries, block
344
     * type dropdowns etc. Examples are "Content", "File", "Media", etc.
345
     *
346
     * @return string
347
     */
348
    public function getType()
349
    {
350
        return _t(__CLASS__ . '.BlockType', 'Block');
351
    }
352
353
    /**
354
     * @param ElementController $controller
355
     *
356
     * @return $this
357
     */
358
    public function setController($controller)
359
    {
360
        $this->controller = $controller;
361
362
        return $this;
363
    }
364
365
    /**
366
     * @throws Exception If the specified controller class doesn't exist
367
     *
368
     * @return ElementController
369
     */
370
    public function getController()
371
    {
372
        if ($this->controller) {
373
            return $this->controller;
374
        }
375
376
        $controllerClass = self::config()->controller_class;
377
378
        if (!class_exists($controllerClass)) {
379
            throw new Exception('Could not find controller class ' . $controllerClass . ' as defined in ' . static::class);
380
        }
381
382
        $this->controller = Injector::inst()->create($controllerClass, $this);
383
        $this->controller->doInit();
384
385
        return $this->controller;
386
    }
387
388
    /**
389
     * @return Controller
390
     */
391
    public function Top()
392
    {
393
        return (Controller::has_curr()) ? Controller::curr() : null;
394
    }
395
396
    /**
397
     * Default way to render element in templates. Note that all blocks should
398
     * be rendered through their {@link ElementController} class as this
399
     * contains the holder styles.
400
     *
401
     * @return string|null HTML
402
     */
403
    public function forTemplate($holder = true)
0 ignored issues
show
Unused Code introduced by
The parameter $holder is not used and could be removed. ( Ignorable by Annotation )

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

403
    public function forTemplate(/** @scrutinizer ignore-unused */ $holder = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
404
    {
405
        $templates = $this->getRenderTemplates();
406
407
        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...
408
            return $this->renderWith($templates);
409
        }
410
    }
411
412
    /**
413
     * @param string $suffix
414
     *
415
     * @return array
416
     */
417
    public function getRenderTemplates($suffix = '')
418
    {
419
        $classes = ClassInfo::ancestry($this->ClassName);
420
        $classes[static::class] = static::class;
421
        $classes = array_reverse($classes);
422
        $templates = array();
423
424
        foreach ($classes as $key => $value) {
425
            if ($value == BaseElement::class) {
426
                continue;
427
            }
428
429
            if ($value == DataObject::class) {
430
                break;
431
            }
432
433
            $templates[] = $value . $suffix;
434
        }
435
436
        return $templates;
437
    }
438
439
    /**
440
     * Strip all namespaces from class namespace.
441
     *
442
     * @param string $classname e.g. "\Fully\Namespaced\Class"
443
     *
444
     * @return string following the param example, "Class"
445
     */
446
    protected function stripNamespacing($classname)
447
    {
448
        $classParts = explode('\\', $classname);
449
        return array_pop($classParts);
450
    }
451
452
    /**
453
     * @return string
454
     */
455
    public function getSimpleClassName()
456
    {
457
        return strtolower($this->sanitiseClassName($this->ClassName, '__'));
458
    }
459
460
    /**
461
     * @return SiteTree
0 ignored issues
show
Bug introduced by
The type DNADesign\Elemental\Models\SiteTree was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
462
     */
463
    public function getPage()
464
    {
465
        $area = $this->Parent();
0 ignored issues
show
Bug introduced by
The method Parent() 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

465
        /** @scrutinizer ignore-call */ 
466
        $area = $this->Parent();
Loading history...
466
467
        if ($area instanceof ElementalArea && $area->exists()) {
468
            return $area->getOwnerPage();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $area->getOwnerPage() returns the type false which is incompatible with the documented return type DNADesign\Elemental\Models\SiteTree.
Loading history...
469
        }
470
471
        return null;
472
    }
473
474
    /**
475
     * Get a unique anchor name
476
     *
477
     * @return string
478
     */
479
    public function getAnchor()
480
    {
481
        if ($this->_anchor !== null) {
482
            return $this->_anchor;
483
        }
484
485
        $anchorTitle = '';
486
487
        if (!$this->config()->disable_pretty_anchor_name) {
488
            if ($this->hasMethod('getAnchorTitle')) {
489
                $anchorTitle = $this->getAnchorTitle();
490
            } elseif ($this->config()->enable_title_in_template) {
491
                $anchorTitle = $this->getField('Title');
492
            }
493
        }
494
495
        if (!$anchorTitle) {
496
            $anchorTitle = 'e'.$this->ID;
497
        }
498
499
        $filter = URLSegmentFilter::create();
500
        $titleAsURL = $filter->filter($anchorTitle);
501
502
        // Ensure that this anchor name isn't already in use
503
        // ie. If two elemental blocks have the same title, it'll append '-2', '-3'
504
        $result = $titleAsURL;
505
        $count = 1;
506
        while (isset(self::$_used_anchors[$result]) && self::$_used_anchors[$result] !== $this->ID) {
507
            ++$count;
508
            $result = $titleAsURL.'-'.$count;
509
        }
510
        self::$_used_anchors[$result] = $this->ID;
511
        return $this->_anchor = $result;
512
    }
513
514
    /**
515
     * @param string $action
516
     *
517
     * @return string
518
     */
519
    public function AbsoluteLink($action = null)
520
    {
521
        if ($page = $this->getPage()) {
522
            $link = $page->AbsoluteLink($action) . '#' . $this->getAnchor();
523
524
            return $link;
525
        }
526
    }
527
528
    /**
529
     * @param string $action
530
     *
531
     * @return string
532
     */
533
    public function Link($action = null)
534
    {
535
        if ($page = $this->getPage()) {
536
            $link = $page->Link($action) . '#' . $this->getAnchor();
537
538
            $this->extend('updateLink', $link);
539
540
            return $link;
541
        }
542
    }
543
544
    /**
545
     * @param string $action
546
     *
547
     * @return string
548
     */
549
    public function PreviewLink($action = null)
550
    {
551
        $action = $action . '?ElementalPreview=' . mt_rand();
0 ignored issues
show
Bug introduced by
The call to mt_rand() has too few arguments starting with min. ( Ignorable by Annotation )

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

551
        $action = $action . '?ElementalPreview=' . /** @scrutinizer ignore-call */ mt_rand();

This check compares calls to functions or methods with their respective definitions. If the call has less 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...
552
        $link = $this->Link($action);
553
        $this->extend('updatePreviewLink', $link);
554
555
        return $link;
556
    }
557
558
    /**
559
     * @return boolean
560
     */
561
    public function isCMSPreview()
562
    {
563
        if (Controller::has_curr()) {
564
            $controller = Controller::curr();
565
566
            if ($controller->getRequest()->requestVar('CMSPreview')) {
567
                return true;
568
            }
569
        }
570
571
        return false;
572
    }
573
574
    /**
575
     * @return string|null
576
     */
577
    public function CMSEditLink()
578
    {
579
        $relationName = $this->getAreaRelationName();
580
        $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

580
        /** @scrutinizer ignore-call */ 
581
        $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...
581
582
        if (!$page) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $page of type null|false is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
583
            return null;
584
        }
585
586
        $link = Controller::join_links(
587
            singleton(CMSPageEditController::class)->Link('EditForm'),
588
            $page->ID,
589
            'field/' . $relationName . '/item/',
590
            $this->ID
591
        );
592
593
        $link = Controller::join_links(
594
            $link,
595
            'edit'
596
        );
597
598
        $this->extend('updateCMSEditLink', $link);
599
600
        return $link;
601
    }
602
603
    /**
604
     * Retrieve a elemental area relation for creating cms links
605
     *
606
     * @return string The name of a valid elemental area relation
607
     */
608
    public function getAreaRelationName()
609
    {
610
        $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

610
        /** @scrutinizer ignore-call */ 
611
        $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...
611
612
        if ($page) {
613
            $has_one = $page->config()->get('has_one');
614
            $area = $this->Parent();
615
616
            foreach ($has_one as $relationName => $relationClass) {
617
                if ($relationClass === $area->ClassName) {
618
                    return $relationName;
619
                }
620
            }
621
        }
622
623
        return 'ElementalArea';
624
    }
625
626
    /**
627
     * Sanitise a model class' name for inclusion in a link.
628
     *
629
     * @return string
630
     */
631
    public function sanitiseClassName($class, $delimiter = '-')
632
    {
633
        return str_replace('\\', $delimiter, $class);
634
    }
635
636
    public function unsanitiseClassName($class, $delimiter = '-')
637
    {
638
        return str_replace($delimiter, '\\', $class);
639
    }
640
641
    /**
642
     * @return string|null
643
     */
644
    public function getEditLink()
645
    {
646
        return $this->CMSEditLink();
647
    }
648
649
    /**
650
     * @return HTMLText
0 ignored issues
show
Bug introduced by
The type DNADesign\Elemental\Models\HTMLText was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
651
     */
652
    public function PageCMSEditLink()
653
    {
654
        if ($page = $this->getPage()) {
655
            return DBField::create_field('HTMLText', sprintf(
0 ignored issues
show
Bug Best Practice introduced by
The expression return SilverStripe\ORM\...tLink(), $page->Title)) returns the type SilverStripe\ORM\FieldType\DBField which is incompatible with the documented return type DNADesign\Elemental\Models\HTMLText.
Loading history...
656
                '<a href="%s">%s</a>',
657
                $page->CMSEditLink(),
658
                $page->Title
659
            ));
660
        }
661
    }
662
663
    /**
664
     * @return string
665
     */
666
    public function getMimeType()
667
    {
668
        return 'text/html';
669
    }
670
671
    /**
672
     * This can be overridden on child elements to create a summary for display
673
     * in GridFields.
674
     *
675
     * @return string
676
     */
677
    public function getSummary()
678
    {
679
        return '';
680
    }
681
682
683
    /**
684
     * Generate markup for element type icons suitable for use in GridFields.
685
     *
686
     * @return HTMLVarchar
0 ignored issues
show
Bug introduced by
The type DNADesign\Elemental\Models\HTMLVarchar was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
687
     */
688
    public function getIcon()
689
    {
690
        $iconClass = $this->config()->get('icon');
691
692
        if ($iconClass) {
693
            return DBField::create_field('HTMLVarchar', '<i class="' . $iconClass . '"></i>');
0 ignored issues
show
Bug Best Practice introduced by
The expression return SilverStripe\ORM\... $iconClass . '"></i>') returns the type SilverStripe\ORM\FieldType\DBField which is incompatible with the documented return type DNADesign\Elemental\Models\HTMLVarchar.
Loading history...
694
        }
695
    }
696
697
    /**
698
     * Get a description for this content element, if available
699
     *
700
     * @return string
701
     */
702
    public function getDescription()
703
    {
704
        $description = $this->config()->uninherited('description');
705
        if ($description) {
706
            return _t(__CLASS__ . '.Description', $description);
707
        }
708
        return '';
709
    }
710
711
    /**
712
     * Generate markup for element type, with description suitable for use in
713
     * GridFields.
714
     *
715
     * @return DBField
716
     */
717
    public function getTypeNice()
718
    {
719
        $description = $this->getDescription();
720
        $desc = ($description) ? ' <span class="element__note"> &mdash; ' . $description . '</span>' : '';
721
722
        return DBField::create_field(
723
            'HTMLVarchar',
724
            $this->getType() . $desc
725
        );
726
    }
727
728
    /**
729
     * @return HTMLText
730
     */
731
    public function getEditorPreview()
732
    {
733
        $templates = $this->getRenderTemplates('_EditorPreview');
734
        $templates[] = BaseElement::class . '_EditorPreview';
735
736
        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 DNADesign\Elemental\Models\HTMLText.
Loading history...
737
    }
738
739
    /**
740
     * @return Member
741
     */
742
    public function getAuthor()
743
    {
744
        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...
745
            return Member::get()->byId($this->AuthorID);
746
        }
747
    }
748
749
    /**
750
     * Get a user defined style variant for this element, if available
751
     *
752
     * @return string
753
     */
754
    public function getStyleVariant()
755
    {
756
        $style = $this->Style;
0 ignored issues
show
Bug Best Practice introduced by
The property Style does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __get, consider adding a @property annotation.
Loading history...
757
        $styles = $this->config()->get('styles');
758
759
        if (isset($styles[$style])) {
760
            $style = strtolower($style);
761
        } else {
762
            $style = '';
763
        }
764
765
        $this->extend('updateStyleVariant', $style);
766
767
        return $style;
768
    }
769
770
    /**
771
     *
772
     */
773
    public function getPageTitle()
774
    {
775
        $page = $this->getPage();
776
777
        if ($page) {
778
            return $page->Title;
779
        }
780
781
        return null;
782
    }
783
784
    /**
785
     * Get a "nice" label for use in the block history GridField
786
     *
787
     * @return string
788
     */
789
    public function getVersionedStateNice()
790
    {
791
        if ($this->WasPublished) {
0 ignored issues
show
Bug Best Practice introduced by
The property WasPublished does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __get, consider adding a @property annotation.
Loading history...
792
            return _t(__CLASS__ . '.Published', 'Published');
793
        }
794
795
        return _t(__CLASS__ . '.Modified', 'Modified');
796
    }
797
798
    /**
799
     * Return a formatted date for use in the block history GridField
800
     *
801
     * @return string
802
     */
803
    public function getLastEditedNice()
804
    {
805
        return $this->dbObject('LastEdited')->Nice();
806
    }
807
}
808