Passed
Push — master ( 78e071...9f4322 )
by Will
03:15
created

src/Extension/BaseElementExtension.php (6 issues)

1
<?php
2
3
namespace DNADesign\ElementalVirtual\Extensions;
4
5
use DNADesign\ElementalVirtual\Forms\ElementalGridFieldDeleteAction;
6
use DNADesign\ElementalVirtual\Model\ElementVirtual;
7
use SilverStripe\ORM\DataExtension;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Versioned\Versioned;
10
use SilverStripe\Forms\LiteralField;
11
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
12
use SilverStripe\Forms\GridField\GridFieldDataColumns;
13
use SilverStripe\Forms\GridField\GridFieldAddNewButton;
14
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
15
use SilverStripe\Forms\GridField\GridFieldDetailForm;
16
17
class BaseElementExtension extends DataExtension
18
{
19
    /**
20
     * @var mixed
21
     */
22
    protected $virtualOwner;
23
24
    /**
25
     * @config
26
     *
27
     * @var boolean
28
     */
29
    private static $default_global_elements = true;
30
31
    /**
32
     * @var array
33
     */
34
    private static $db = [
35
        'AvailableGlobally' => 'Boolean(1)'
36
    ];
37
38
    /**
39
     * @var array $has_many
40
     */
41
    private static $has_many = [
42
        'VirtualClones' => ElementVirtual::class
43
    ];
44
45
    public function populateDefaults()
46
    {
47
        $this->AvailableGlobally = $this->owner->config()->get('default_global_elements');
0 ignored issues
show
Bug Best Practice introduced by
The property AvailableGlobally does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
48
    }
49
50
    /**
51
     * @param ElementVirtual
52
     *
53
     * @return $this
54
     */
55
    public function setVirtualOwner(ElementVirtual $owner)
56
    {
57
        $this->virtualOwner = $owner;
58
        return $this;
59
    }
60
61
    /**
62
     * @return ElementVirtual
63
     */
64
    public function getVirtualOwner()
65
    {
66
        return $this->virtualOwner;
67
    }
68
69
    /**
70
     * Finds and returns elements that are virtual elements which link to this
71
     * element.
72
     *
73
     * @return DataList
74
     */
75
    public function getVirtualElements()
76
    {
77
        return ElementVirtual::get()->filter('LinkedElementID', $this->owner->ID);
0 ignored issues
show
Bug Best Practice introduced by
The expression return DNADesign\Element...tID', $this->owner->ID) returns the type SilverStripe\ORM\DataList which is incompatible with the documented return type DNADesign\ElementalVirtual\Extensions\DataList.
Loading history...
78
    }
79
80
    /**
81
     * @return DataList
82
     */
83
    public function getPublishedVirtualElements()
84
    {
85
        return ElementVirtual::get()->filter('LinkedElementID', $this->owner->ID)->setDataQueryParam([
0 ignored issues
show
Bug Best Practice introduced by
The expression return DNADesign\Element...oned.stage' => 'Live')) returns the type SilverStripe\ORM\DataList which is incompatible with the documented return type DNADesign\ElementalVirtual\Extensions\DataList.
Loading history...
86
            'Versioned.mode' => 'stage',
87
            'Versioned.stage' => 'Live'
88
        ]);
89
    }
90
91
    /**
92
     * @param FieldList $fields
93
     *
94
     * @return FieldList
95
     */
96
    public function updateCMSFields(FieldList $fields)
97
    {
98
        $global = $fields->dataFieldByName('AvailableGlobally');
99
100
        if ($global) {
101
            $fields->removeByName('AvailableGlobally');
102
            $fields->addFieldToTab('Root.Settings', $global);
103
        }
104
105
        if ($virtual = $fields->dataFieldByName('VirtualClones')) {
106
            if ($this->owner->VirtualClones()->Count() > 0) {
107
                $tab = $fields->findOrMakeTab('Root.VirtualClones');
108
                $tab->setTitle(_t(__CLASS__ . '.LinkedTo', 'Linked To'));
109
110
                if ($ownerPage = $this->owner->getPage()) {
111
                    $fields->addFieldToTab(
112
                        'Root.VirtualClones',
113
                        LiteralField::create(
114
                            'DisplaysOnPage',
115
                            sprintf(
116
                                "<p>"
117
                                . _t(__CLASS__ . '.OriginalContentFrom', 'The original content element appears on')
118
                                . " <a href='%s'>%s</a></p>",
119
                                ($ownerPage->hasMethod('CMSEditLink') && $ownerPage->canEdit()) ? $ownerPage->CMSEditLink() : $ownerPage->Link(),
120
                                $ownerPage->MenuTitle
121
                            )
122
                        ),
123
                        'VirtualClones'
124
                    );
125
                }
126
127
                $virtual->setConfig(new GridFieldConfig_Base());
128
                $virtual
129
                    ->setTitle(_t(__CLASS__ . '.OtherPages', 'Other pages'))
130
                    ->getConfig()
131
                        ->removeComponentsByType(GridFieldAddExistingAutocompleter::class)
132
                        ->removeComponentsByType(GridFieldAddNewButton::class)
133
                        ->removeComponentsByType(GridFieldDeleteAction::class)
134
                        ->removeComponentsByType(GridFieldDetailForm::class)
135
                        ->addComponent(new ElementalGridFieldDeleteAction());
136
137
                $virtual->getConfig()
138
                    ->getComponentByType(GridFieldDataColumns::class)
139
                    ->setDisplayFields([
140
                        'getPage.Title' => _t(__CLASS__ . '.GridFieldTitle', 'Title'),
141
                        'ParentCMSEditLink' => _t(__CLASS__ . '.GridFieldUsedOn', 'Used on'),
142
                    ]);
143
            } else {
144
                $fields->removeByName('VirtualClones');
145
            }
146
        }
147
    }
148
149
    /**
150
     * Ensure that if there are elements that are virtualised from this element
151
     * that we move the original element to replace one of the virtual elements
152
     *
153
     * But only if it's a delete not an unpublish
154
     */
155
    public function onBeforeDelete()
156
    {
157
        if (Versioned::get_reading_mode() == 'Stage.Stage') {
158
            $firstVirtual = false;
159
            $allVirtual = $this->getVirtualElements();
160
161
            if ($this->getPublishedVirtualElements()->Count() > 0) {
162
                // choose the first one
163
                $firstVirtual = $this->getPublishedVirtualElements()->First();
164
                $wasPublished = true;
165
            } elseif ($allVirtual->Count() > 0) {
166
                // choose the first one
167
                $firstVirtual = $this->getVirtualElements()->First();
168
                $wasPublished = false;
169
            }
170
            if ($firstVirtual) {
171
172
                $clone = $this->owner->duplicate(false);
173
174
                // set clones values to first virtual's values
175
                $clone->ParentID = $firstVirtual->ParentID;
176
                $clone->Sort = $firstVirtual->Sort;
177
178
                $clone->write();
179
                if ($wasPublished) {
180
                    $clone->doPublish();
181
                    $firstVirtual->doUnpublish();
182
                }
183
184
                // clone has a new ID, so need to repoint
185
                // all the other virtual elements
186
                foreach ($allVirtual as $virtual) {
187
                    if ($virtual->ID == $firstVirtual->ID) {
188
                        continue;
189
                    }
190
                    $pub = false;
191
                    if ($virtual->isPublished()) {
192
                        $pub = true;
193
                    }
194
                    $virtual->LinkedElementID = $clone->ID;
195
                    $virtual->write();
196
                    if ($pub) {
197
                        $virtual->doPublish();
198
                    }
199
                }
200
201
                $firstVirtual->delete();
202
            }
203
        }
204
    }
205
206
    /**
207
     * @param array $classes
208
     */
209
    public function updateAllowedElementClasses(&$classes)
210
    {
211
        if (isset($classes[ElementVirtual::class])) {
212
            unset($classes[ElementVirtual::class]);
213
        }
214
    }
215
216
217
    /**
218
     * get all pages where this element is used
219
     *
220
     * @return ArrayList
221
     */
222
    public function getUsage()
223
    {
224
        $usage = new ArrayList();
225
226
        if ($page = $this->getPage()) {
227
            $usage->push($page);
228
            if ($this->virtualOwner) {
229
                $page->setField('ElementType', 'Linked');
230
            } else {
231
                $page->setField('ElementType', 'Master');
232
            }
233
        }
234
235
        $linkedElements = ElementVirtual::get()->filter('LinkedElementID', $this->ID);
236
237
        foreach ($linkedElements as $element) {
238
            $area = $element->Parent();
239
240
            if ($area instanceof ElementalArea && $page = $area->getOwnerPage()) {
241
                $page->setField('ElementType', 'Linked');
242
                $usage->push($page);
243
            }
244
        }
245
246
        $usage->removeDuplicates();
247
        return $usage;
248
    }
249
250
    /**
251
     * @return DBHTMLText
252
     */
253
    public function UsageSummary()
254
    {
255
        $usage = $this->getUsage();
256
        $arr = array();
257
        foreach ($usage as $page) {
258
            $type = ($page->ElementType) ? sprintf("<em> - %s</em>", $page->ElementType) : null;
259
            $arr[] = sprintf("<a href=\"%s\" target=\"blank\">%s</a> %s", $page->CMSEditLink(), $page->Title, $type);
260
        }
261
        $html = DBHTMLText::create('UsageSummary');
262
        $html->setValue(implode('<br>', $arr));
263
264
        return $html;
265
    }
266
267
    /**
268
     * @param DBHTMLVarchar
269
     */
270
    public function updateElementIcon($icon)
271
    {
272
        $linked = $this->owner->LinkedElement();
273
274
        if ($linked) {
275
            $linkedIcon = $linked->config()->get('icon');
276
277
            $icon = DBField::create_field('HTMLVarchar', '<span class="el-icongroup"><img width="16px" src="' . Director::absoluteBaseURL() . $linkedIcon . '" alt="" /><img class="el-icon--virtual" width="16px" src="' . Director::absoluteBaseURL() . $icon . '" alt="" /></span>');
0 ignored issues
show
The type DNADesign\ElementalVirtual\Extensions\Director 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...
The assignment to $icon is dead and can be removed.
Loading history...
The type DNADesign\ElementalVirtual\Extensions\DBField 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...
278
        }
279
    }
280
}
281