Passed
Pull Request — master (#113)
by Will
02:06
created

BaseElement::getRenderTemplates()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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

284
            TextField::create(/** @scrutinizer ignore-type */ 'ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
Loading history...
285
                ->setAttribute('placeholder', _t(__CLASS__ . '.ExtraCssClassesPlaceholder', 'my_class another_class'))
286
        );
287
288
        if ($this->IsInDB()) {
289
            if ($this->hasExtension('VersionViewerDataObject')) {
290
                $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

290
                $fields = $this->/** @scrutinizer ignore-call */ addVersionViewer($fields, $this);
Loading history...
291
            }
292
        }
293
294
        $fields->push($liveLinkField = new HiddenField('AbsoluteLink', false, Director::absoluteURL($this->PreviewLink())));
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type null|string expected by parameter $title of SilverStripe\Forms\HiddenField::__construct(). ( Ignorable by Annotation )

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

294
        $fields->push($liveLinkField = new HiddenField('AbsoluteLink', /** @scrutinizer ignore-type */ false, Director::absoluteURL($this->PreviewLink())));
Loading history...
295
        $fields->push($liveLinkField = new HiddenField('LiveLink', false, Director::absoluteURL($this->Link())));
296
        $fields->push($stageLinkField = new HiddenField('StageLink', false, Director::absoluteURL($this->PreviewLink())));
297
298
        $this->extend('updateCMSFields', $fields);
299
300
        return $fields;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $fields also could return the type SilverStripe\Forms\FieldList which is incompatible with the documented return type DNADesign\Elemental\Models\FieldList.
Loading history...
301
    }
302
303
    /**
304
     * Used in ElementalAdmin
305
     */
306
    public function getDefaultSearchContext()
307
    {
308
        $fields = $this->scaffoldSearchFields();
309
        $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

309
        $elements = BaseElement::/** @scrutinizer ignore-call */ all_allowed_elements();
Loading history...
310
311
        if (!$elements) {
312
            $elements = ClassInfo::subclassesFor(self::class);
313
        }
314
        foreach ($elements as $key => $value) {
315
            if ($key == self::class) {
316
                unset($elements[$key]);
317
                continue;
318
            }
319
            $elements[$key] = DataObjectPreviewController::stripNamespacing($value);
320
        }
321
322
        $fields->push(
323
            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

323
            DropdownField::create(/** @scrutinizer ignore-type */ 'ClassName', _t(__CLASS__.'.ELEMENTTYPE', 'Element Type'), $elements)
Loading history...
324
                ->setEmptyString(_t(__CLASS__.'.ALL', 'All types'))
325
        );
326
327
        $filters = $this->owner->defaultSearchFilters();
0 ignored issues
show
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...
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

327
        $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...
328
329
        return new SearchContext(
330
            self::class,
331
            $fields,
332
            $filters
333
        );
334
    }
335
336
    /**
337
     * @return string
338
     */
339
    public function i18n_singular_name()
340
    {
341
        return _t(__CLASS__, $this->config()->title);
342
    }
343
344
    /**
345
     * @return string
346
     */
347
    public function getType()
348
    {
349
        return $this->i18n_singular_name();
350
    }
351
352
    /**
353
     * @return string
354
     */
355
    public function getTitle()
356
    {
357
        if ($title = $this->getField('Title')) {
358
            return $title;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $title also could return the type object which is incompatible with the documented return type string.
Loading history...
359
        } else {
360
            if (!$this->isInDb()) {
361
                return;
362
            }
363
364
            return $this->config()->title;
365
        }
366
    }
367
368
    /**
369
     * @param ElementController
370
     *
371
     * @return $this
372
     */
373
    public function setController($controller)
374
    {
375
        $this->controller = $controller;
376
377
        return $this;
378
    }
379
380
    /**
381
     * @throws Exception
382
     *
383
     * @return ElementController
384
     */
385
    public function getController()
386
    {
387
        if ($this->controller) {
388
            return $this->controller;
389
        }
390
391
        $controllerClass = self::config()->controller_class;
392
393
        if (!class_exists($controllerClass)) {
394
            throw new Exception('Could not find controller class ' . $controllerClass . ' as defined in ' . static::class);
395
        }
396
397
        $this->controller = Injector::inst()->create($controllerClass, $this);
398
        $this->controller->doInit();
399
        return $this->controller;
400
    }
401
402
    /**
403
     * @return Controller
404
     */
405
    public function Top()
406
    {
407
        return (Controller::has_curr()) ? Controller::curr() : null;
408
    }
409
410
    /**
411
     * Default way to render element in templates. Note that all blocks should
412
     * be rendered through their {@link ElementController} class as this
413
     * contains the holder styles.
414
     *
415
     * @return string HTML
416
     */
417
    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

417
    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...
418
    {
419
        $templates = $this->getRenderTemplates();
420
421
        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...
422
            return $this->renderWith($templates);
423
        }
424
    }
425
426
    /**
427
     * @param string $suffix
428
     *
429
     * @return array
430
     */
431
    public function getRenderTemplates($suffix = '')
432
    {
433
        $classes = ClassInfo::ancestry($this->ClassName);
434
        $classes[static::class] = static::class;
435
        $classes = array_reverse($classes);
436
        $templates = array();
437
438
        foreach ($classes as $key => $value) {
439
            if ($value == BaseElement::class) {
440
                continue;
441
            }
442
443
            if ($value == DataObject::class) {
444
                break;
445
            }
446
447
            $templates[] = $value . $suffix;
448
        }
449
450
        return $templates;
451
    }
452
453
    /**
454
     * @return string
455
     */
456
    public function getSimpleClassName()
457
    {
458
        return strtolower($this->sanitiseClassName($this->ClassName, '__'));
459
    }
460
461
    /**
462
     * @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...
463
     */
464
    public function getPage()
465
    {
466
        $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

466
        $area = $this->/** @scrutinizer ignore-call */ Parent();
Loading history...
467
468
        if ($area instanceof ElementalArea) {
469
            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...
470
        }
471
472
        return null;
473
    }
474
475
    /**
476
     * Get a unique anchor name
477
     *
478
     * @return string
479
     */
480
    public function getAnchor()
481
    {
482
        if ($this->_anchor !== null) {
483
            return $this->_anchor;
484
        }
485
486
        $anchorTitle = '';
487
488
        if (!$this->config()->disable_pretty_anchor_name) {
489
            if ($this->hasMethod('getAnchorTitle')) {
490
                $anchorTitle = $this->getAnchorTitle();
491
            } elseif ($this->config()->enable_title_in_template) {
492
                $anchorTitle = $this->getField('Title');
493
            }
494
        }
495
496
        if (!$anchorTitle) {
497
            $anchorTitle = 'e'.$this->ID;
498
        }
499
500
        $filter = URLSegmentFilter::create();
501
        $titleAsURL = $filter->filter($anchorTitle);
502
503
        // Ensure that this anchor name isn't already in use
504
        // ie. If two elemental blocks have the same title, it'll append '-2', '-3'
505
        $result = $titleAsURL;
506
        $count = 1;
507
        while (isset(self::$_used_anchors[$result]) && self::$_used_anchors[$result] !== $this->ID) {
508
            ++$count;
509
            $result = $titleAsURL.'-'.$count;
510
        }
511
        self::$_used_anchors[$result] = $this->ID;
512
        return $this->_anchor = $result;
513
    }
514
515
    /**
516
     * @param string $action
517
     *
518
     * @return string
519
     */
520
    public function AbsoluteLink($action = null)
521
    {
522
        if ($page = $this->getPage()) {
523
            $link = $page->AbsoluteLink($action) . '#' . $this->getAnchor();
524
525
            return $link;
526
        }
527
    }
528
529
    /**
530
     * @param string $action
531
     *
532
     * @return string
533
     */
534
    public function Link($action = null)
535
    {
536
        if ($page = $this->getPage()) {
537
            $link = $page->Link($action) . '#' . $this->getAnchor();
538
539
            $this->extend('updateLink', $link);
540
541
            return $link;
542
        }
543
    }
544
545
    /**
546
     * @param string $action
547
     *
548
     * @return string
549
     */
550
    public function PreviewLink($action = 'show')
551
    {
552
        $link = Controller::join_links(
553
            Director::baseURL(),
554
            'cms-preview',
555
            $action,
556
            urlencode($this->ClassName),
557
            $this->ID
558
        );
559
560
        $this->extend('updatePreviewLink', $link);
561
562
        return $link;
563
    }
564
565
    /**
566
     * @return boolean
567
     */
568
    public function isCMSPreview()
569
    {
570
        if (Controller::has_curr()) {
571
            $c = Controller::curr();
572
573
            if ($c->getRequest()->requestVar('CMSPreview')) {
574
                return true;
575
            }
576
        }
577
578
        return false;
579
    }
580
581
    /**
582
     * @return string
583
     */
584
    public function CMSEditLink()
585
    {
586
        $relationName = $this->getAreaRelationName();
587
588
        $link = Controller::join_links(
589
            singleton(CMSPageEditController::class)->Link('EditForm'),
590
            $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

590
            /** @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...
591
            'field/' . $relationName . '/item/',
592
            $this->ID
593
        );
594
595
        if ($inList) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $inList seems to be never defined.
Loading history...
596
            return $link;
597
        }
598
599
        return Controller::join_links(
600
            $link,
601
            'edit'
602
        );
603
    }
604
605
    /**
606
     * Retrieve a elemental area relation for creating cms links
607
     *
608
     * @return string - the name of a valid elemental area relation
609
     */
610
    public function getAreaRelationName()
611
    {
612
        $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

612
        $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...
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
        return 'ElementalArea';
623
    }
624
625
    /**
626
     * Sanitise a model class' name for inclusion in a link.
627
     *
628
     * @return string
629
     */
630
    protected function sanitiseClassName($class, $delimiter = '-')
631
    {
632
        return str_replace('\\', $delimiter, $class);
633
    }
634
635
    /**
636
     * @return string
637
     */
638
    public function getEditLink()
639
    {
640
        return $this->CMSEditLink();
641
    }
642
643
    /**
644
     * @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...
645
     */
646
    public function PageCMSEditLink()
647
    {
648
        if ($page = $this->getPage()) {
649
            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...
650
                '<a href="%s">%s</a>',
651
                $page->CMSEditLink(),
652
                $page->Title
653
            ));
654
        }
655
    }
656
657
    /**
658
     * @return string
659
     */
660
    public function getMimeType()
661
    {
662
        return 'text/html';
663
    }
664
665
    /**
666
     * This can be overridden on child elements to create a summary for display
667
     * in GridFields.
668
     *
669
     * @return string
670
     */
671
    public function getSummary()
672
    {
673
        return '';
674
    }
675
676
677
    /**
678
     * Generate markup for element type icons suitable for use in GridFields.
679
     *
680
     * @return DBField
681
     */
682
    public function getIcon()
683
    {
684
        $icon = $this->config()->get('icon');
685
686
        if ($icon) {
687
            $icon = ModuleResourceLoader::resourceURL($icon);
688
689
            return DBField::create_field('HTMLVarchar', '<img width="16px" src="' . Director::absoluteBaseURL() . $icon . '" alt="" />');
690
        }
691
    }
692
693
    /**
694
     * Generate markup for element type, with description suitable for use in
695
     * GridFields.
696
     *
697
     * @return DBField
698
     */
699
    public function getTypeNice()
700
    {
701
        $description = $this->config()->get('description');
702
703
        return DBField::create_field('HTMLVarchar', $this->ElementType .' <span class="el-description"> &mdash; ' . $description . '</span>');
0 ignored issues
show
Bug Best Practice introduced by
The property ElementType does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __get, consider adding a @property annotation.
Loading history...
704
    }
705
706
    /**
707
     * @return HTMLText
708
     */
709
    public function getEditorPreview()
710
    {
711
        $templates = $this->getRenderTemplates('_EditorPreview');
712
        $templates[] = BaseElement::class . '_EditorPreview';
713
714
        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...
715
    }
716
}
717