GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Block::onAfterWrite()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
namespace SheaDawson\Blocks\Model;
4
5
use SheaDawson\Blocks\BlockManager;
6
use SilverStripe\ORM\DataObject;
7
use SilverStripe\Security\Security;
8
use SilverStripe\Versioned\Versioned;
9
use SilverStripe\ORM\FieldType\DBBoolean;
10
use SilverStripe\ORM\FieldType\DBHTMLText;
11
use SilverStripe\ORM\ValidationException;
12
use SilverStripe\ORM\DB;
13
use SilverStripe\Core\ClassInfo;
14
use SilverStripe\Core\Injector\Injector;
15
use SilverStripe\CMS\Model\SiteTree;
16
use SilverStripe\View\Requirements;
17
use SilverStripe\View\SSViewer;
18
use SilverStripe\Control\Controller;
19
use SilverStripe\Security\PermissionProvider;
20
use SilverStripe\Security\Permission;
21
use SilverStripe\Security\Group;
22
use SilverStripe\Security\Member;
23
use SilverStripe\Forms\DropdownField;
24
use SilverStripe\Forms\OptionsetField;
25
use SilverStripe\Forms\ListboxField;
26
use SilverStripe\Forms\Tab;
27
28
/**
29
 * Block
30
 * Subclass this basic Block with your more interesting ones.
31
 *
32
 * @author Shea Dawson <[email protected]>
33
 */
34
class Block extends DataObject implements PermissionProvider
35
{
36
37
	private static $table_name = 'Block';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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...
38
39
    /**
40
     * @var array
41
     */
42
    private static $db = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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...
43
        'Title' => 'Varchar(255)',
44
        'CanViewType' => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone')",
45
        'ExtraCSSClasses' => 'Varchar'
46
    ];
47
48
    /**
49
     * @var array
50
     */
51
    private static $many_many = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $many_many 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
        "ViewerGroups" => Group::class,
53
    ];
54
55
    /**
56
     * @var array
57
     */
58
    private static $belongs_many_many = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $belongs_many_many 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
        "Pages" => SiteTree::class,
60
        "BlockSets" => BlockSet::class,
61
    ];
62
63
    private static $summary_fields = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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...
64
        'singular_name',
65
        'Title',
66
        'isPublishedField',
67
        'UsageListAsString',
68
    ];
69
70
    private static $searchable_fields = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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...
71
        'Title',
72
        'ClassName',
73
    ];
74
75
    public function fieldLabels($includerelations = true)
76
    {
77
        $labels =  parent::fieldLabels($includerelations);
78
79
        $labels = array_merge($labels, [
80
            'singular_name' => _t('Block.BlockType', 'Block Type'),
81
            'Title' => _t('Block.Title', 'Title'),
82
            'isPublishedField' => _t('Block.IsPublishedField', 'Published'),
83
            'UsageListAsString' => _t('Block.UsageListAsString', 'Used on'),
84
            'ExtraCSSClasses' => _t('Block.ExtraCSSClasses', 'Extra CSS Classes'),
85
            'ClassName' => _t('Block.BlockType', 'Block Type'),
86
        ]);
87
88
        return $labels;
89
    }
90
91
    public function getDefaultSearchContext()
92
    {
93
        $context = parent::getDefaultSearchContext();
94
95
        $results = $this->blockManager->getBlockClasses();
96
        if (sizeof($results) > 1) {
97
            $classfield = new DropdownField('ClassName', _t('Block.BlockType', 'Block Type'));
98
            $classfield->setSource($results);
99
            $classfield->setEmptyString(_t('Block.Any', '(any)'));
100
            $context->addField($classfield);
101
        }
102
103
        return $context;
104
    }
105
106
    /**
107
     * @var array
108
     */
109
    private static $default_sort = ['Title' => 'ASC'];
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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...
110
111
    /**
112
     * @var array
113
     */
114
    private static $dependencies = [
0 ignored issues
show
Unused Code introduced by
The property $dependencies 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...
115
        'blockManager' => '%$blockManager',
116
    ];
117
118
    /**
119
     * @var BlockManager
120
     */
121
    public $blockManager;
122
123
    /**
124
     * @var BlockController
125
     */
126
    protected $controller;
127
128
    /**
129
     * @return mixed
130
     */
131
    public function getTypeForGridfield()
132
    {
133
        return $this->singular_name();
134
    }
135
136
    public function getCMSFields()
137
    {
138
        $self = $this;
139
        $this->beforeUpdateCMSFields(function($fields) use($self) {
140
            /** @var FieldList $fields */
141
            Requirements::add_i18n_javascript(BLOCKS_DIR . '/javascript/lang');
142
143
            // this line is a temporary patch until I can work out why this dependency isn't being
144
            // loaded in some cases...
145
            if (!$self->blockManager) {
146
                $self->blockManager = singleton("SheaDawson\\Blocks\\BlockManager");
147
            }
148
149
            // ClassNmae - block type/class field
150
            $classes = $self->blockManager->getBlockClasses();
151
            $fields->addFieldToTab('Root.Main', DropdownField::create('ClassName', _t('Block.BlockType', 'Block Type'), $classes)->addExtraClass('block-type'), 'Title');
152
153
            // BlockArea - display areas field if on page edit controller
154
            if (Controller::curr()->class == 'CMSPageEditController') {
155
                $currentPage = Controller::curr()->currentPage();
156
                $areas = $self->blockManager->getAreasForPageType($currentPage->ClassName);
157
                $fields->addFieldToTab(
158
                    'Root.Main',
159
                    $blockAreaField = DropdownField::create('ManyMany[BlockArea]', _t('Block.BlockArea', 'Block Area'), $areas),
160
                    'ClassName'
161
                );
162
163
164
165
                if (count($areas) > 1) {
166
                    $blockAreaField->setEmptyString('(Select one)');
167
                }
168
169
                if (BlockManager::config()->get('block_area_preview')) {
170
                    $blockAreaField->setRightTitle($currentPage->areasPreviewButton());
171
                }
172
            }
173
174
            $fields->removeFieldFromTab('Root', 'BlockSets');
175
            $fields->removeFieldFromTab('Root', 'Pages');
176
177
            // legacy fields, will be removed in later release
178
            $fields->removeByName('Weight');
179
            $fields->removeByName('Area');
180
            $fields->removeByName('Published');
181
182
            if ($self->blockManager->getUseExtraCSSClasses()) {
183
                $fields->addFieldToTab('Root.Main', $fields->dataFieldByName('ExtraCSSClasses'), 'Title');
184
            } else {
185
                $fields->removeByName('ExtraCSSClasses');
186
            }
187
188
            // Viewer groups
189
            $fields->removeFieldFromTab('Root', 'ViewerGroups');
190
            $groupsMap = Group::get()->map('ID', 'Breadcrumbs')->toArray();
191
            asort($groupsMap);
192
            $viewersOptionsField = new OptionsetField(
193
                'CanViewType',
194
                _t('SiteTree.ACCESSHEADER', 'Who can view this page?')
195
            );
196
            $viewerGroupsField = ListboxField::create('ViewerGroups', _t('SiteTree.VIEWERGROUPS', 'Viewer Groups'))
197
                ->setSource($groupsMap)
198
                ->setAttribute(
199
                    'data-placeholder',
200
                    _t('SiteTree.GroupPlaceholder', 'Click to select group')
201
                );
202
            $viewersOptionsSource = [];
203
            $viewersOptionsSource['Anyone'] = _t('SiteTree.ACCESSANYONE', 'Anyone');
204
            $viewersOptionsSource['LoggedInUsers'] = _t('SiteTree.ACCESSLOGGEDIN', 'Logged-in users');
205
            $viewersOptionsSource['OnlyTheseUsers'] = _t('SiteTree.ACCESSONLYTHESE', 'Only these people (choose from list)');
206
            $viewersOptionsField->setSource($viewersOptionsSource)->setValue('Anyone');
207
208
            $fields->addFieldToTab('Root', new Tab('ViewerGroups', _t('Block.ViewerGroups', 'Viewer Groups')));
209
            $fields->addFieldsToTab('Root.ViewerGroups', [
210
                $viewersOptionsField,
211
                $viewerGroupsField,
212
            ]);
213
214
            // Disabled for now, until we can list ALL pages this block is applied to (inc via sets)
215
            // As otherwise it could be misleading
216
            // Show a GridField (list only) with pages which this block is used on
217
            // $fields->removeFieldFromTab('Root.Pages', 'Pages');
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
218
            // $fields->addFieldsToTab('Root.Pages',
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
219
            //         new GridField(
220
            //                 'Pages',
221
            //                 'Used on pages',
222
            //                 $self->Pages(),
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
223
            //                 $gconf = GridFieldConfig_Base::create()));
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
224
            // enhance gridfield with edit links to pages if GFEditSiteTreeItemButtons is available
225
            // a GFRecordEditor (default) combined with BetterButtons already gives the possibility to
226
            // edit versioned records (Pages), but STbutton loads them in their own interface instead
227
            // of GFdetailform
228
            // if(class_exists('GridFieldEditSiteTreeItemButton')) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
229
            //     $gconf->addComponent(new GridFieldEditSiteTreeItemButton());
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
230
            // }
231
        });
232
        return parent::getCMSFields();
233
    }
234
235
    /**
236
     * Renders this block with appropriate templates
237
     * looks for templates that match BlockClassName_AreaName
238
     * falls back to BlockClassName.
239
     *
240
     * @return string
241
     **/
242
    public function forTemplate()
243
    {
244
        if ($this->BlockArea) {
0 ignored issues
show
Documentation introduced by
The property BlockArea does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
245
            $template = [$this->class.'_'.$this->BlockArea];
0 ignored issues
show
Documentation introduced by
The property class does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property BlockArea does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
246
247
            if (SSViewer::hasTemplate($template)) {
248
                return $this->renderWith($template);
249
            }
250
        }
251
252
        return $this->renderWith($this->ClassName, $this->getController());
253
    }
254
255
    /**
256
     * @return string
257
     */
258
    public function BlockHTML()
259
    {
260
        return $this->forTemplate();
261
    }
262
263
    /*
264
     * Checks if deletion was an actual deletion, not just unpublish
265
     * If so, remove relations
266
     */
267
    public function onAfterDelete()
268
    {
269
        parent::onAfterDelete();
270
        if (Versioned::get_stage() == 'Stage') {
271
            $this->Pages()->removeAll();
0 ignored issues
show
Documentation Bug introduced by
The method Pages does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
272
            $this->BlockSets()->removeAll();
0 ignored issues
show
Documentation Bug introduced by
The method BlockSets does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
273
        }
274
    }
275
276
    /**
277
     * Remove relations onAfterDuplicate.
278
     */
279
    public function onAfterDuplicate()
280
    {
281
        // remove relations to pages & blocksets duplicated from the original item
282
        $this->Pages()->removeAll();
0 ignored issues
show
Documentation Bug introduced by
The method Pages does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
283
        $this->BlockSets()->removeAll();
0 ignored issues
show
Documentation Bug introduced by
The method BlockSets does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
284
    }
285
286
    /*
287
     * Base permissions
288
     */
289
    public function canView($member = null)
290
    {
291
        if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
292
            $member = Security::getCurrentUser()->ID;
293
        }
294
295
        // admin override
296
        if ($member && Permission::checkMember($member, ['ADMIN', 'SITETREE_VIEW_ALL'])) {
297
            return true;
298
        }
299
300
        // Standard mechanism for accepting permission changes from extensions
301
        $extended = $this->extendedCan('canView', $member);
302
        if ($extended !== null) {
303
            return $extended;
304
        }
305
306
        // check for empty spec
307
        if (!$this->CanViewType || $this->CanViewType == 'Anyone') {
0 ignored issues
show
Documentation introduced by
The property CanViewType does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
308
            return true;
309
        }
310
311
        // check for any logged-in users
312
        if ($this->CanViewType == 'LoggedInUsers' && $member) {
0 ignored issues
show
Documentation introduced by
The property CanViewType does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
313
            return true;
314
        }
315
316
        // check for specific groups
317
        if ($member && is_numeric($member)) {
318
            $member = Member::get()->byID($member);
319
        }
320
        if ($this->CanViewType == 'OnlyTheseUsers' && $member && $member->inGroups($this->ViewerGroups())) {
0 ignored issues
show
Documentation introduced by
The property CanViewType does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation Bug introduced by
The method ViewerGroups does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
321
            return true;
322
        }
323
324
        return false;
325
    }
326
327
    public function canEdit($member = null)
328
    {
329
        return Permission::check('ADMIN', 'any', $member) || Permission::check('BLOCK_EDIT', 'any', $member);
330
    }
331
332
    public function canDelete($member = null)
333
    {
334
        return Permission::check('ADMIN', 'any', $member) || Permission::check('BLOCK_DELETE', 'any', $member);
335
    }
336
337
    public function canCreate($member = null, $context = [])
338
    {
339
        return Permission::check('ADMIN', 'any', $member) || Permission::check('BLOCK_CREATE', 'any', $member);
340
    }
341
342
    public function canPublish($member = null)
343
    {
344
        return Permission::check('ADMIN', 'any', $member) || Permission::check('BLOCK_PUBLISH', 'any', $member);
345
    }
346
347
    public function providePermissions()
348
    {
349
        return [
350
            'BLOCK_EDIT' => [
351
                'name' => _t('Block.EditBlock', 'Edit a Block'),
352
                'category' => _t('Block.PermissionCategory', 'Blocks'),
353
            ],
354
            'BLOCK_DELETE' => [
355
                'name' => _t('Block.DeleteBlock', 'Delete a Block'),
356
                'category' => _t('Block.PermissionCategory', 'Blocks'),
357
            ],
358
            'BLOCK_CREATE' => [
359
                'name' => _t('Block.CreateBlock', 'Create a Block'),
360
                'category' => _t('Block.PermissionCategory', 'Blocks'),
361
            ],
362
            'BLOCK_PUBLISH' => [
363
                'name' => _t('Block.PublishBlock', 'Publish a Block'),
364
                'category' => _t('Block.PermissionCategory', 'Blocks'),
365
            ],
366
        ];
367
    }
368
369
    public function onAfterWrite()
370
    {
371
        parent::onAfterWrite();
372
        if ($this->hasExtension('FilesystemPublisher')) {
373
            $this->republish($this);
0 ignored issues
show
Documentation Bug introduced by
The method republish does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
374
        }
375
    }
376
377
    /**
378
     * Get a list of URL's to republish when this block changes
379
     * if using StaticPublisher module.
380
     */
381
    public function pagesAffectedByChanges()
382
    {
383
        $pages = $this->Pages();
0 ignored issues
show
Documentation Bug introduced by
The method Pages does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
384
        $urls = [];
385
        foreach ($pages as $page) {
386
            $urls[] = $page->Link();
387
        }
388
389
        return $urls;
390
    }
391
392
    /*
393
     * Get a list of Page and Blockset titles this block is used on
394
     */
395
    public function UsageListAsString()
396
    {
397
        $pages = implode(', ', $this->Pages()->column('URLSegment'));
0 ignored issues
show
Documentation Bug introduced by
The method Pages does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
398
        $sets = implode(', ', $this->BlockSets()->column('Title'));
0 ignored issues
show
Documentation Bug introduced by
The method BlockSets does not exist on object<SheaDawson\Blocks\Model\Block>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
399
        $_t_pages = _t('Block.PagesAsString', 'Pages: {pages}', '', ['pages' => $pages]);
400
        $_t_sets = _t('Block.BlockSetsAsString', 'Block Sets: {sets}', '', ['sets' => $sets]);
401
        if ($pages && $sets) {
402
            return "$_t_pages<br />$_t_sets";
403
        }
404
        if ($pages) {
405
            return $_t_pages;
406
        }
407
        if ($sets) {
408
            return $_t_sets;
409
        }
410
    }
411
412
    /**
413
     * Check if this block has been published.
414
     *
415
     * @return bool True if this page has been published.
416
     */
417
    public function isPublished()
418
    {
419
        if (!$this->exists()) {
420
            return false;
421
        }
422
423
        return (DB::query("SELECT \"ID\" FROM \"Block_Live\" WHERE \"ID\" = $this->ID")->value())
424
            ? 1
425
            : 0;
426
    }
427
428
    /**
429
     * Check if this block has been published.
430
     *
431
     * @return bool True if this page has been published.
432
     */
433
    public function isPublishedNice()
434
    {
435
        $field = DBBoolean::create('isPublished');
436
        $field->setValue($this->isPublished());
437
438
        return $field->Nice();
439
    }
440
441
    /**
442
     * @return DBHTMLText
443
     */
444
    public function isPublishedIcon()
445
    {
446
        $obj = DBHTMLText::create();
447
        if ($this->isPublished()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->isPublished() of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
448
            $obj->setValue('<img src="' . FRAMEWORK_ADMIN_DIR . '/images/alert-good.gif" />');
449
        } else {
450
            $obj->setValue('<img src="' . FRAMEWORK_ADMIN_DIR . '/images/alert-bad.gif" />');
451
        }
452
        return $obj;
453
    }
454
455
    /**
456
     * CSS Classes to apply to block element in template.
457
     *
458
     * @return string $classes
459
     */
460
    public function CSSClasses($stopAtClass = 'DataObject')
461
    {
462
        $classes = strtolower(parent::CSSClasses($stopAtClass));
463
464
        if (!empty($classes) && ($prefix = $this->blockManager->getPrefixDefaultCSSClasses())) {
465
            $classes = $prefix.str_replace(' ', " {$prefix}", $classes);
466
        }
467
468
        if ($this->blockManager->getUseExtraCSSClasses()) {
469
            $classes = $this->ExtraCSSClasses ? $classes." $this->ExtraCSSClasses" : $classes;
0 ignored issues
show
Documentation introduced by
The property ExtraCSSClasses does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
470
        }
471
472
        return $classes;
473
    }
474
475
    /**
476
     * Access current page scope from Block templates with $CurrentPage
477
     *
478
     * @return Controller
479
     */
480
    public function getCurrentPage()
481
    {
482
        return Controller::curr();
483
    }
484
485
    /**
486
     * @throws Exception
487
     *
488
     * @return BlockController
489
     */
490
    public function getController()
491
    {
492
        if ($this->controller) {
493
            return $this->controller;
494
        }
495
        foreach (array_reverse(ClassInfo::ancestry($this->class)) as $blockClass) {
0 ignored issues
show
Documentation introduced by
The property class does not exist on object<SheaDawson\Blocks\Model\Block>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
496
            $controllerClass = "{$blockClass}Controller";
497
            if (class_exists($controllerClass)) {
498
                break;
499
            }
500
        }
501
        if (!class_exists($controllerClass)) {
0 ignored issues
show
Bug introduced by
The variable $controllerClass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
502
            throw new ValidationException("Could not find controller class for $this->classname");
0 ignored issues
show
Bug introduced by
The property classname does not seem to exist. Did you mean ClassName?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
503
        }
504
505
        $this->controller = Injector::inst()->create($controllerClass, $this);
506
        $this->controller->init();
507
508
        return $this->controller;
509
    }
510
}
511