Passed
Pull Request — master (#123)
by Will
01:35
created

BaseElement::getHistoryFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 20
rs 9.4285
cc 1
eloc 14
nc 1
nop 0
1
<?php
2
3
namespace DNADesign\Elemental\Models;
4
5
use Exception;
6
use DNADesign\Elemental\Controllers\ElementController;
7
use SilverStripe\CMS\Controllers\CMSPageEditController;
8
use SilverStripe\Control\Controller;
9
use SilverStripe\Control\Director;
10
use SilverStripe\Core\ClassInfo;
11
use SilverStripe\Core\Config\Config;
12
use SilverStripe\Core\Injector\Injector;
13
use SilverStripe\Core\Manifest\ModuleResourceLoader;
14
use SilverStripe\Forms\CheckboxField;
15
use SilverStripe\Forms\DropdownField;
16
use SilverStripe\Forms\FieldGroup;
17
use SilverStripe\Forms\FieldList;
18
use SilverStripe\Forms\HiddenField;
19
use SilverStripe\Forms\NumericField;
20
use SilverStripe\Forms\ReadonlyField;
21
use SilverStripe\Forms\TextField;
22
use SilverStripe\Forms\GridField\GridField;
23
use SilverStripe\Forms\GridField\GridFieldConfig_RecordViewer;
24
use SilverStripe\Forms\GridField\GridFieldDataColumns;
25
use SilverStripe\Forms\GridField\GridFieldVersionedState;
26
use SilverStripe\ORM\ArrayList;
27
use SilverStripe\ORM\CMSPreviewable;
28
use SilverStripe\ORM\DataObject;
29
use SilverStripe\ORM\DB;
30
use SilverStripe\ORM\FieldType\DBField;
31
use SilverStripe\ORM\Search\SearchContext;
32
use SilverStripe\Security\Permission;
33
use SilverStripe\Security\Member;
34
use SilverStripe\SiteConfig\SiteConfig;
35
use SilverStripe\Versioned\Versioned;
36
use SilverStripe\View\Parsers\URLSegmentFilter;
37
use SilverStripe\View\SSViewer;
38
39
class BaseElement extends DataObject implements CMSPreviewable
40
{
41
    /**
42
     * Override this on your custom elements to specify a cms icon
43
     * @var string
44
     */
45
    private static $icon = 'dnadesign/silverstripe-elemental:images/base.svg';
0 ignored issues
show
Unused Code introduced by
The property $icon is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
46
47
    private static $db = [
0 ignored issues
show
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
48
        'Title' => 'Varchar(255)',
49
        'ShowTitle' => 'Boolean',
50
        'Sort' => 'Int',
51
        'ExtraClass' => 'Varchar(255)'
52
    ];
53
54
    private static $has_one = [
0 ignored issues
show
Unused Code introduced by
The property $has_one is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
55
        'Parent' => ElementalArea::class
56
    ];
57
58
    private static $extensions = [
0 ignored issues
show
Unused Code introduced by
The property $extensions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
59
        Versioned::class
60
    ];
61
62
    private static $table_name = 'Element';
0 ignored issues
show
Unused Code introduced by
The property $table_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
63
64
    /**
65
     * @var string
66
     */
67
    private static $controller_class = ElementController::class;
0 ignored issues
show
Unused Code introduced by
The property $controller_class is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
68
69
    /**
70
     * @var string
71
     */
72
    private static $controller_template = 'ElementHolder';
0 ignored issues
show
Unused Code introduced by
The property $controller_template is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
73
74
    /**
75
     * @var ElementController
76
     */
77
    protected $controller;
78
79
    private static $default_sort = 'Sort';
0 ignored issues
show
Unused Code introduced by
The property $default_sort is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
80
81
    private static $singular_name = 'block';
0 ignored issues
show
Unused Code introduced by
The property $singular_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
82
83
    private static $plural_name = 'blocks';
0 ignored issues
show
Unused Code introduced by
The property $plural_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
84
85
    private static $summary_fields = [
0 ignored issues
show
Unused Code introduced by
The property $summary_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
86
        'EditorPreview' => 'Summary'
87
    ];
88
89
    private static $searchable_fields = [
0 ignored issues
show
Unused Code introduced by
The property $searchable_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
90
        'ID' => [
91
            'field' => NumericField::class,
92
        ],
93
        'Title',
94
        'LastEdited'
95
    ];
96
97
    /**
98
     * Enable for backwards compatibility
99
     *
100
     * @var boolean
101
     */
102
    private static $disable_pretty_anchor_name = false;
0 ignored issues
show
Unused Code introduced by
The property $disable_pretty_anchor_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
103
104
    /**
105
     * Store used anchor names, this is to avoid title clashes
106
     * when calling 'getAnchor'
107
     *
108
     * @var array
109
     */
110
    protected static $_used_anchors = [];
111
112
    /**
113
     * For caching 'getAnchor'
114
     *
115
     * @var string
116
     */
117
    protected $_anchor = null;
118
119
    /**
120
     * @return array
121
     */
122
    public function getAllowedElementClasses()
123
    {
124
        $classes = [];
125
126
        foreach (ClassInfo::subclassesFor(DataObject::class) as $className) {
127
            if (Injector::inst()->get($className)->hasExtension(ElementPageExtension::class)) {
0 ignored issues
show
Bug introduced by
The type DNADesign\Elemental\Models\ElementPageExtension 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...
128
                $classes[] = $className;
129
            }
130
        }
131
132
        $allowed = [];
133
134
        foreach ($classes as $className) {
135
            $elements = Config::inst()->get($className, 'allowed_elements');
136
137
            if ($elements) {
138
                $allowed = array_merge($allowed, $elements);
139
            }
140
        }
141
142
        $allowed = array_unique($allowed);
143
144
        $elements = [];
145
146
        foreach ($allowed as $className) {
147
            $elements[$className] = _t($className, Config::inst()->get($className, 'title'));
148
        }
149
150
        $this->invokeWithExtensions('updateAllowedElementClasses', $elements);
151
152
        return $elements;
153
    }
154
155
    /**
156
     * Basic permissions, defaults to page perms where possible.
157
     *
158
     * @param Member $member
159
     *
160
     * @return boolean
161
     */
162 View Code Duplication
    public function canView($member = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
    {
164
        if ($this->hasMethod('getPage')) {
165
            if ($page = $this->getPage()) {
166
                return $page->canView($member);
167
            }
168
        }
169
170
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
171
    }
172
173
    /**
174
     * Basic permissions, defaults to page perms where possible.
175
     *
176
     * @param Member $member
177
     *
178
     * @return boolean
179
     */
180 View Code Duplication
    public function canEdit($member = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
181
    {
182
        if ($this->hasMethod('getPage')) {
183
            if ($page = $this->getPage()) {
184
                return $page->canEdit($member);
185
            }
186
        }
187
188
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
189
    }
190
191
    /**
192
     * Basic permissions, defaults to page perms where possible.
193
     *
194
     * Uses archive not delete so that current stage is respected i.e if a
195
     * element is not published, then it can be deleted by someone who doesn't
196
     * have publishing permissions.
197
     *
198
     * @param Member $member
199
     *
200
     * @return boolean
201
     */
202 View Code Duplication
    public function canDelete($member = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
224
    }
225
226
    /**
227
     *
228
     */
229
    public function onBeforeWrite()
230
    {
231
        parent::onBeforeWrite();
232
233
        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...
234
            if ($elementalArea = ElementalArea::get()->byID($areaID)) {
235
                $elementalArea->write();
236
            }
237
        }
238
239
        if (!$this->Sort) {
240
            $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...
241
242
            $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...
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'))
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

255
                TextField::create(/** @scrutinizer ignore-type */ 'ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
Loading history...
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
                FieldGroup::create(
267
                    TextField::create('Title', ''),
0 ignored issues
show
Bug introduced by
It seems like SilverStripe\Forms\TextField::create('Title', '') can also be of type object; however, parameter $args of SilverStripe\View\ViewableData::create() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

267
                    /** @scrutinizer ignore-type */ TextField::create('Title', ''),
Loading history...
268
                    CheckboxField::create('ShowTitle', _t(__CLASS__ . '.ShowTitleLabel', 'Displayed'))
269
                )
270
                    ->setTemplate(__CLASS__ . '\\FieldGroup')
271
                    ->setTitle(_t(__CLASS__ . '.TitleLabel', 'Title (not displayed unless specified)'))
272
            );
273
274
            // Rename the "Main" tab
275
            $fields->fieldByName('Root.Main')
276
                ->setTitle(_t(__CLASS__ . '.MainTabLabel', 'Content'));
277
278
            // Remove divider lines on all block forms
279
            $fields->fieldByName('Root')->addExtraClass('form--no-dividers');
280
281
            $fields->addFieldsToTab('Root.Main', [
282
                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

282
                HiddenField::create('AbsoluteLink', /** @scrutinizer ignore-type */ false, Director::absoluteURL($this->PreviewLink())),
Loading history...
283
                HiddenField::create('LiveLink', false, Director::absoluteURL($this->Link())),
284
                HiddenField::create('StageLink', false, Director::absoluteURL($this->PreviewLink())),
285
            ]);
286
287
288
289
            $fields->addFieldsToTab('Root.History', $this->getHistoryFields());
0 ignored issues
show
Bug introduced by
$this->getHistoryFields() of type SilverStripe\Forms\FieldList is incompatible with the type array expected by parameter $fields of SilverStripe\Forms\FieldList::addFieldsToTab(). ( Ignorable by Annotation )

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

289
            $fields->addFieldsToTab('Root.History', /** @scrutinizer ignore-type */ $this->getHistoryFields());
Loading history...
290
        });
291
292
        return parent::getCMSFields();
293
    }
294
295
    /**
296
     * Returns the history fields for this element.
297
     *
298
     * @return FieldList
299
     */
300
    public function getHistoryFields()
301
    {
302
        $config = GridFieldConfig_RecordViewer::create();
303
        $config->removeComponentsByType('SilverStripe\Forms\GridField\GridFieldPageCount');
304
305
        $config->getComponentByType(GridFieldDataColumns::class)->setDisplayFields([
306
            'Version' => '#',
307
            'LastEdited' => _t(__CLASS__ . '.LastEdited', 'Last Edited'),
308
            'getAuthor.Name' => _t(__CLASS__ . '.Author', 'Author')
309
        ]);
310
311
        $history = Versioned::get_all_versions(__CLASS__, $this->ID);
312
        $history = $history->sort('Version', 'DESC');
313
314
        return new FieldList(
315
            GridField::create(
316
                'History',
0 ignored issues
show
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

316
                /** @scrutinizer ignore-type */ 'History',
Loading history...
317
                '',
318
                $history,
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

318
                /** @scrutinizer ignore-type */ $history,
Loading history...
319
                $config
0 ignored issues
show
Bug introduced by
It seems like $config can also be of type object; however, parameter $args of SilverStripe\View\ViewableData::create() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

319
                /** @scrutinizer ignore-type */ $config
Loading history...
320
            )
321
        );
322
    }
323
324
    /**
325
     * Get the type of the current block, for use in GridField summaries, block type dropdowns etc. Examples
326
     * are "Content", "File", "Media", etc.
327
     *
328
     * @return string
329
     */
330
    public function getType()
331
    {
332
        return _t(__CLASS__ . '.BlockType', 'Block');
333
    }
334
335
    /**
336
     * @param ElementController
337
     *
338
     * @return $this
339
     */
340
    public function setController($controller)
341
    {
342
        $this->controller = $controller;
343
344
        return $this;
345
    }
346
347
    /**
348
     * @throws Exception
349
     *
350
     * @return ElementController
351
     */
352
    public function getController()
353
    {
354
        if ($this->controller) {
355
            return $this->controller;
356
        }
357
358
        $controllerClass = self::config()->controller_class;
359
360
        if (!class_exists($controllerClass)) {
361
            throw new Exception('Could not find controller class ' . $controllerClass . ' as defined in ' . static::class);
362
        }
363
364
        $this->controller = Injector::inst()->create($controllerClass, $this);
365
        $this->controller->doInit();
366
        return $this->controller;
367
    }
368
369
    /**
370
     * @return Controller
371
     */
372
    public function Top()
373
    {
374
        return (Controller::has_curr()) ? Controller::curr() : null;
375
    }
376
377
    /**
378
     * Default way to render element in templates. Note that all blocks should
379
     * be rendered through their {@link ElementController} class as this
380
     * contains the holder styles.
381
     *
382
     * @return string HTML
383
     */
384
    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

384
    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...
385
    {
386
        $templates = $this->getRenderTemplates();
387
388
        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...
389
            return $this->renderWith($templates);
390
        }
391
    }
392
393
    /**
394
     * @param string $suffix
395
     *
396
     * @return array
397
     */
398
    public function getRenderTemplates($suffix = '')
399
    {
400
        $classes = ClassInfo::ancestry($this->ClassName);
401
        $classes[static::class] = static::class;
402
        $classes = array_reverse($classes);
403
        $templates = array();
404
405
        foreach ($classes as $key => $value) {
406
            if ($value == BaseElement::class) {
407
                continue;
408
            }
409
410
            if ($value == DataObject::class) {
411
                break;
412
            }
413
414
            $templates[] = $value . $suffix;
415
        }
416
417
        return $templates;
418
    }
419
420
    /**
421
     * Strip all namespaces from class namespace
422
     * @param string $classname e.g. "\Fully\Namespaced\Class"
423
     *
424
     * @return string following the param example, "Class"
425
     */
426
    protected function stripNamespacing($classname)
427
    {
428
        $classParts = explode('\\', $classname);
429
        return array_pop($classParts);
430
    }
431
432
    /**
433
     * @return string
434
     */
435
    public function getSimpleClassName()
436
    {
437
        return strtolower($this->sanitiseClassName($this->ClassName, '__'));
438
    }
439
440
    /**
441
     * @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...
442
     */
443
    public function getPage()
444
    {
445
        $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

445
        /** @scrutinizer ignore-call */ 
446
        $area = $this->Parent();
Loading history...
446
447
        if ($area instanceof ElementalArea) {
448
            return $area->getOwnerPage();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $area->getOwnerPage() could also return false which is incompatible with the documented return type DNADesign\Elemental\Models\SiteTree. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
449
        }
450
451
        return null;
452
    }
453
454
    /**
455
     * Get a unique anchor name
456
     *
457
     * @return string
458
     */
459
    public function getAnchor()
460
    {
461
        if ($this->_anchor !== null) {
462
            return $this->_anchor;
463
        }
464
465
        $anchorTitle = '';
466
467
        if (!$this->config()->disable_pretty_anchor_name) {
468
            if ($this->hasMethod('getAnchorTitle')) {
469
                $anchorTitle = $this->getAnchorTitle();
470
            } elseif ($this->config()->enable_title_in_template) {
471
                $anchorTitle = $this->getField('Title');
472
            }
473
        }
474
475
        if (!$anchorTitle) {
476
            $anchorTitle = 'e'.$this->ID;
477
        }
478
479
        $filter = URLSegmentFilter::create();
480
        $titleAsURL = $filter->filter($anchorTitle);
481
482
        // Ensure that this anchor name isn't already in use
483
        // ie. If two elemental blocks have the same title, it'll append '-2', '-3'
484
        $result = $titleAsURL;
485
        $count = 1;
486
        while (isset(self::$_used_anchors[$result]) && self::$_used_anchors[$result] !== $this->ID) {
487
            ++$count;
488
            $result = $titleAsURL.'-'.$count;
489
        }
490
        self::$_used_anchors[$result] = $this->ID;
491
        return $this->_anchor = $result;
492
    }
493
494
    /**
495
     * @param string $action
496
     *
497
     * @return string
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
508
    /**
509
     * @param string $action
510
     *
511
     * @return string
512
     */
513
    public function Link($action = null)
514
    {
515
        if ($page = $this->getPage()) {
516
            $link = $page->Link($action) . '#' . $this->getAnchor();
517
518
            $this->extend('updateLink', $link);
519
520
            return $link;
521
        }
522
    }
523
524
    /**
525
     * @param string $action
526
     *
527
     * @return string
528
     */
529
    public function PreviewLink($action = null)
530
    {
531
        $action = $action . '?ElementalPreview=' . mt_rand();
532
        $link = $this->Link($action);
533
        $this->extend('updatePreviewLink', $link);
534
535
        return $link;
536
    }
537
538
    /**
539
     * @return boolean
540
     */
541
    public function isCMSPreview()
542
    {
543
        if (Controller::has_curr()) {
544
            $c = Controller::curr();
545
546
            if ($c->getRequest()->requestVar('CMSPreview')) {
547
                return true;
548
            }
549
        }
550
551
        return false;
552
    }
553
554
    /**
555
     * @return string
556
     */
557
    public function CMSEditLink()
558
    {
559
        $relationName = $this->getAreaRelationName();
560
561
        $link = Controller::join_links(
562
            singleton(CMSPageEditController::class)->Link('EditForm'),
563
            $this->getPage(true)->ID,
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

563
            $this->/** @scrutinizer ignore-call */ 
564
                   getPage(true)->ID,

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...
564
            'field/' . $relationName . '/item/',
565
            $this->ID
566
        );
567
568
        if ($inList) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $inList seems to be never defined.
Loading history...
569
            return $link;
570
        }
571
572
        return Controller::join_links(
573
            $link,
574
            'edit'
575
        );
576
    }
577
578
    /**
579
     * Retrieve a elemental area relation for creating cms links
580
     *
581
     * @return string - the name of a valid elemental area relation
582
     */
583
    public function getAreaRelationName()
584
    {
585
        $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

585
        /** @scrutinizer ignore-call */ 
586
        $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...
586
        $has_one = $page->config()->get('has_one');
587
        $area = $this->Parent();
588
589
        foreach ($has_one as $relationName => $relationClass) {
590
            if ($relationClass === $area->ClassName) {
591
                return $relationName;
592
            }
593
        }
594
595
        return 'ElementalArea';
596
    }
597
598
    /**
599
     * Sanitise a model class' name for inclusion in a link.
600
     *
601
     * @return string
602
     */
603
    protected function sanitiseClassName($class, $delimiter = '-')
604
    {
605
        return str_replace('\\', $delimiter, $class);
606
    }
607
608
    /**
609
     * @return string
610
     */
611
    public function getEditLink()
612
    {
613
        return $this->CMSEditLink();
614
    }
615
616
    /**
617
     * @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...
618
     */
619
    public function PageCMSEditLink()
620
    {
621
        if ($page = $this->getPage()) {
622
            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...
623
                '<a href="%s">%s</a>',
624
                $page->CMSEditLink(),
625
                $page->Title
626
            ));
627
        }
628
    }
629
630
    /**
631
     * @return string
632
     */
633
    public function getMimeType()
634
    {
635
        return 'text/html';
636
    }
637
638
    /**
639
     * This can be overridden on child elements to create a summary for display
640
     * in GridFields.
641
     *
642
     * @return string
643
     */
644
    public function getSummary()
645
    {
646
        return '';
647
    }
648
649
650
    /**
651
     * Generate markup for element type icons suitable for use in GridFields.
652
     *
653
     * @return DBField
654
     */
655
    public function getIcon()
656
    {
657
        $icon = $this->config()->get('icon');
658
659
        if ($icon) {
660
            $icon = ModuleResourceLoader::resourceURL($icon);
661
662
            return DBField::create_field('HTMLVarchar', '<img width="16px" src="' . Director::absoluteBaseURL() . $icon . '" alt="" />');
663
        }
664
    }
665
666
    /**
667
     * Generate markup for element type, with description suitable for use in
668
     * GridFields.
669
     *
670
     * @return DBField
671
     */
672
    public function getTypeNice()
673
    {
674
        $description = $this->config()->get('description');
675
676
        return DBField::create_field(
677
            'HTMLVarchar',
678
            $this->getType() . ' <span class="el-description"> &mdash; ' . $description . '</span>'
679
        );
680
    }
681
682
    /**
683
     * @return HTMLText
684
     */
685
    public function getEditorPreview()
686
    {
687
        $templates = $this->getRenderTemplates('_EditorPreview');
688
        $templates[] = BaseElement::class . '_EditorPreview';
689
690
        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...
691
    }
692
693
    /**
694
     * @return Member
695
     */
696
    public function getAuthor()
697
    {
698
        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...
699
            return Member::get()->byId($this->AuthorID);
700
        }
701
    }
702
}
703