Passed
Pull Request — master (#122)
by Robbie
01:58
created

BaseElement::getCMSFields()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 49
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 49
rs 9.2258
c 0
b 0
f 0
cc 3
eloc 28
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\DataObjectPreview\Controllers\DataObjectPreviewController;
0 ignored issues
show
Bug introduced by
The type SilverStripe\DataObjectP...ObjectPreviewController 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...
15
use SilverStripe\Forms\CheckboxField;
16
use SilverStripe\Forms\DropdownField;
17
use SilverStripe\Forms\FieldGroup;
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\ORM\ArrayList;
24
use SilverStripe\ORM\CMSPreviewable;
25
use SilverStripe\ORM\DataObject;
26
use SilverStripe\ORM\DB;
27
use SilverStripe\ORM\FieldType\DBField;
28
use SilverStripe\ORM\Search\SearchContext;
29
use SilverStripe\Security\Permission;
30
use SilverStripe\SiteConfig\SiteConfig;
31
use SilverStripe\Versioned\Versioned;
32
use SilverStripe\View\Parsers\URLSegmentFilter;
33
use SilverStripe\View\SSViewer;
34
use VersionViewerDataObject;
0 ignored issues
show
Bug introduced by
The type VersionViewerDataObject 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...
35
36
class BaseElement extends DataObject implements CMSPreviewable
37
{
38
    /**
39
     * Override this on your custom elements to specify a cms icon
40
     * @var string
41
     */
42
    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...
43
44
    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...
45
        'Title' => 'Varchar(255)',
46
        'ShowTitle' => 'Boolean',
47
        'Sort' => 'Int',
48
        'ExtraClass' => 'Varchar(255)'
49
    ];
50
51
    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...
52
        'Parent' => ElementalArea::class
53
    ];
54
55
    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...
56
        Versioned::class
57
    ];
58
59
    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...
60
61
    /**
62
     * @var string
63
     */
64
    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...
65
66
    /**
67
     * @var string
68
     */
69
    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...
70
71
    /**
72
     * @var ElementController
73
     */
74
    protected $controller;
75
76
    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...
77
78
    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...
79
80
    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...
81
82
    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...
83
        'EditorPreview' => 'Summary'
84
    ];
85
86
    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...
87
        'ID' => [
88
            'field' => NumericField::class,
89
        ],
90
        'Title',
91
        'LastEdited'
92
    ];
93
94
    /**
95
     * Enable for backwards compatibility
96
     *
97
     * @var boolean
98
     */
99
    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...
100
101
    /**
102
     * Store used anchor names, this is to avoid title clashes
103
     * when calling 'getAnchor'
104
     *
105
     * @var array
106
     */
107
    protected static $_used_anchors = [];
108
109
    /**
110
     * For caching 'getAnchor'
111
     *
112
     * @var string
113
     */
114
    protected $_anchor = null;
115
116
    /**
117
     * @return array
118
     */
119
    public function getAllowedElementClasses()
120
    {
121
        $classes = [];
122
123
        foreach (ClassInfo::subclassesFor(DataObject::class) as $className) {
124
            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...
125
                $classes[] = $className;
126
            }
127
        }
128
129
        $allowed = [];
130
131
        foreach ($classes as $className) {
132
            $elements = Config::inst()->get($className, 'allowed_elements');
133
134
            if ($elements) {
135
                $allowed = array_merge($allowed, $elements);
136
            }
137
        }
138
139
        $allowed = array_unique($allowed);
140
141
        $elements = [];
142
143
        foreach ($allowed as $className) {
144
            $elements[$className] = _t($className, Config::inst()->get($className, 'title'));
145
        }
146
147
        $this->invokeWithExtensions('updateAllowedElementClasses', $elements);
148
149
        return $elements;
150
    }
151
152
    /**
153
     * Basic permissions, defaults to page perms where possible.
154
     *
155
     * @param Member $member
0 ignored issues
show
Bug introduced by
The type DNADesign\Elemental\Models\Member 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...
156
     *
157
     * @return boolean
158
     */
159 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...
160
    {
161
        if ($this->hasMethod('getPage')) {
162
            if ($page = $this->getPage()) {
163
                return $page->canView($member);
164
            }
165
        }
166
167
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
168
    }
169
170
    /**
171
     * Basic permissions, defaults to page perms where possible.
172
     *
173
     * @param Member $member
174
     *
175
     * @return boolean
176
     */
177 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...
178
    {
179
        if ($this->hasMethod('getPage')) {
180
            if ($page = $this->getPage()) {
181
                return $page->canEdit($member);
182
            }
183
        }
184
185
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
186
    }
187
188
    /**
189
     * Basic permissions, defaults to page perms where possible.
190
     *
191
     * Uses archive not delete so that current stage is respected i.e if a
192
     * element is not published, then it can be deleted by someone who doesn't
193
     * have publishing permissions.
194
     *
195
     * @param Member $member
196
     *
197
     * @return boolean
198
     */
199 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...
200
    {
201
        if ($this->hasMethod('getPage')) {
202
            if ($page = $this->getPage()) {
203
                return $page->canArchive($member);
204
            }
205
        }
206
207
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
208
    }
209
210
    /**
211
     * Basic permissions, defaults to page perms where possible.
212
     *
213
     * @param Member $member
214
     * @param array $context
215
     *
216
     * @return boolean
217
     */
218
    public function canCreate($member = null, $context = array())
219
    {
220
        return (Permission::check('CMS_ACCESS', 'any', $member)) ? true : null;
221
    }
222
223
    /**
224
     *
225
     */
226
    public function onBeforeWrite()
227
    {
228
        parent::onBeforeWrite();
229
230
        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...
231
            if ($elementalArea = ElementalArea::get()->byID($areaID)) {
232
                $elementalArea->write();
233
            }
234
        }
235
236
        if (!$this->Sort) {
237
            $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...
238
239
            $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...
240
        }
241
    }
242
243
    public function getCMSFields()
244
    {
245
        $this->beforeUpdateCMSFields(function (FieldList $fields) {
246
            // Remove relationship fields
247
            $fields->removeByName('ParentID');
248
            $fields->removeByName('Sort');
249
250
            $fields->addFieldToTab(
251
                'Root.Settings',
252
                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

252
                TextField::create(/** @scrutinizer ignore-type */ 'ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
Loading history...
253
                    ->setAttribute(
254
                        'placeholder',
255
                        _t(__CLASS__ . '.ExtraCssClassesPlaceholder', 'my_class another_class')
256
                    )
257
            );
258
259
            // Add a combined field for "Title" and "Displayed" checkbox in a Bootstrap input group
260
            $fields->removeByName('ShowTitle');
261
            $fields->replaceField(
262
                'Title',
263
                FieldGroup::create(
264
                    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

264
                    /** @scrutinizer ignore-type */ TextField::create('Title', ''),
Loading history...
265
                    CheckboxField::create('ShowTitle', _t(__CLASS__ . '.ShowTitleLabel', 'Displayed'))
266
                )
267
                    ->setTemplate(__CLASS__ . '\\FieldGroup')
268
                    ->setTitle(_t(__CLASS__ . '.TitleLabel', 'Title (not displayed unless specified)'))
269
            );
270
271
            // Rename the "Main" tab
272
            $fields->fieldByName('Root.Main')
273
                ->setTitle(_t(__CLASS__ . '.MainTabLabel', 'Content'));
274
275
            // Remove divider lines on all block forms
276
            $fields->fieldByName('Root')->addExtraClass('form--no-dividers');
277
278
            if ($this->isInDB()) {
279
                if ($this->hasExtension(VersionViewerDataObject::class)) {
280
                    $fields = $this->addVersionViewer($fields, $this);
0 ignored issues
show
Bug introduced by
The method addVersionViewer() 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

280
                    $fields = $this->/** @scrutinizer ignore-call */ addVersionViewer($fields, $this);
Loading history...
281
                }
282
            }
283
284
            $fields->addFieldsToTab('Root.Main', [
285
                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

285
                HiddenField::create('AbsoluteLink', /** @scrutinizer ignore-type */ false, Director::absoluteURL($this->PreviewLink())),
Loading history...
286
                HiddenField::create('LiveLink', false, Director::absoluteURL($this->Link())),
287
                HiddenField::create('StageLink', false, Director::absoluteURL($this->PreviewLink())),
288
            ]);
289
        });
290
291
        return parent::getCMSFields();
292
    }
293
294
    /**
295
     * Used in ElementalAdmin
296
     */
297
    public function getDefaultSearchContext()
298
    {
299
        $fields = $this->scaffoldSearchFields();
300
        $elements = BaseElement::all_allowed_elements();
0 ignored issues
show
Bug introduced by
The method all_allowed_elements() does not exist on DNADesign\Elemental\Models\BaseElement. It seems like you code against a sub-type of DNADesign\Elemental\Models\BaseElement such as DNADesign\Elemental\Models\ElementContent or DNADesign\Elemental\Tests\Src\TestElement. ( Ignorable by Annotation )

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

300
        $elements = BaseElement::/** @scrutinizer ignore-call */ all_allowed_elements();
Loading history...
301
302
        if (!$elements) {
303
            $elements = ClassInfo::subclassesFor(self::class);
304
        }
305
        foreach ($elements as $key => $value) {
306
            if ($key == self::class) {
307
                unset($elements[$key]);
308
                continue;
309
            }
310
            $elements[$key] = DataObjectPreviewController::stripNamespacing($value);
311
        }
312
313
        $fields->push(
314
            DropdownField::create('ClassName', _t(__CLASS__.'.ELEMENTTYPE', 'Element Type'), $elements)
0 ignored issues
show
Bug introduced by
'ClassName' 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

314
            DropdownField::create(/** @scrutinizer ignore-type */ 'ClassName', _t(__CLASS__.'.ELEMENTTYPE', 'Element Type'), $elements)
Loading history...
315
                ->setEmptyString(_t(__CLASS__.'.ALL', 'All types'))
316
        );
317
318
        $filters = $this->owner->defaultSearchFilters();
0 ignored issues
show
Bug introduced by
The method defaultSearchFilters() does not exist on null. ( Ignorable by Annotation )

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

318
        $filters = $this->owner->/** @scrutinizer ignore-call */ defaultSearchFilters();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

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

387
    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...
388
    {
389
        $templates = $this->getRenderTemplates();
390
391
        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...
392
            return $this->renderWith($templates);
393
        }
394
    }
395
396
    /**
397
     * @param string $suffix
398
     *
399
     * @return array
400
     */
401
    public function getRenderTemplates($suffix = '')
402
    {
403
        $classes = ClassInfo::ancestry($this->ClassName);
404
        $classes[static::class] = static::class;
405
        $classes = array_reverse($classes);
406
        $templates = array();
407
408
        foreach ($classes as $key => $value) {
409
            if ($value == BaseElement::class) {
410
                continue;
411
            }
412
413
            if ($value == DataObject::class) {
414
                break;
415
            }
416
417
            $templates[] = $value . $suffix;
418
            $templates[] = 'elements/' . DataObjectPreviewController::stripNamespacing($value) . $suffix;
419
            $templates[] = DataObjectPreviewController::stripNamespacing($value) . $suffix;
420
        }
421
422
        return $templates;
423
    }
424
425
    /**
426
     * @return string
427
     */
428
    public function getSimpleClassName()
429
    {
430
        return strtolower($this->sanitiseClassName($this->ClassName, '__'));
431
    }
432
433
    /**
434
     * @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...
435
     */
436
    public function getPage()
437
    {
438
        $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

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

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

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