Completed
Pull Request — master (#137)
by
unknown
02:02
created

Widget::getController()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 8.439
c 0
b 0
f 0
cc 6
eloc 14
nc 9
nop 0
1
<?php
2
3
/**
4
 * Widgets let CMS authors drag and drop small pieces of functionality into
5
 * defined areas of their websites.
6
 *
7
 * You can use forms in widgets by implementing a {@link WidgetController}.
8
 *
9
 * See {@link Widget_Controller} for more information.
10
 *
11
 * @package widgets
12
 */
13
class Widget extends DataObject
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
14
{
15
    /**
16
     * @var array
17
     */
18
    private static $db = array(
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...
19
        "Title" => "Varchar(255)",
20
        "Sort" => "Int",
21
        "Enabled" => "Boolean",
22
    );
23
24
    /**
25
     * @var array
26
     */
27
    private static $defaults = array(
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 $defaults 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...
28
        'Enabled' => true,
29
    );
30
31
    /**
32
     * @var array
33
     */
34
    private static $casting = array(
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 $casting 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...
35
        'CMSTitle' => 'Text',
36
        'Description' => 'Text',
37
    );
38
39
    private static $only_available_in = array();
0 ignored issues
show
Unused Code introduced by
The property $only_available_in 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...
40
41
    /**
42
     * @var array
43
     */
44
    private static $has_one = array(
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 $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...
45
        "Parent" => "WidgetArea",
46
    );
47
48
    /**
49
     * @var string
50
     */
51
    private static $default_sort = "\"Sort\"";
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...
52
53
    /**
54
     * @var string
55
     */
56
    private static $title = "Widget Title";
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...
57
58
    /**
59
     * @var string
60
     */
61
    private static $cmsTitle = "Name of this widget";
0 ignored issues
show
Unused Code introduced by
The property $cmsTitle 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...
62
63
    /**
64
     * @var string
65
     */
66
    private static $description = "Description of what this widget does.";
0 ignored issues
show
Unused Code introduced by
The property $description 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 array
70
     */
71
    private static $summary_fields = array(
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...
72
        'CMSTitle' => 'Title'
73
    );
74
75
    /**
76
     * @var WidgetController
77
     */
78
    protected $controller;
79
80
    public function populateDefaults()
81
    {
82
        parent::populateDefaults();
83
        $this->setField('Title', $this->getTitle());
84
    }
85
86
    /**
87
     * Note: Overloaded in {@link WidgetController}.
88
     *
89
     * @return string HTML
90
     */
91
    public function WidgetHolder()
92
    {
93
        return $this->renderWith("WidgetHolder");
94
    }
95
96
    /**
97
     * Default way to render widget in templates.
98
     * @return string HTML
99
     */
100
    public function forTemplate($holder = true)
101
    {
102
        if ($holder) {
103
            return $this->WidgetHolder();
104
        }
105
106
        return $this->Content();
107
    }
108
109
    /**
110
     * Renders the widget content in a custom template with the same name as the
111
     * current class. This should be the main point of output customization.
112
     *
113
     * Invoked from within WidgetHolder.ss, which contains the "framing" around
114
     * the custom content, like a title.
115
     *
116
     * Note: Overloaded in {@link WidgetController}.
117
     *
118
     * @return string HTML
119
     */
120
    public function Content()
121
    {
122
        return $this->renderWith(array_reverse(ClassInfo::ancestry($this->class)));
123
    }
124
125
    /**
126
     * @return string
127
     * @deprecated
128
     */
129
    public function Title()
130
    {
131
        return $this->getTitle();
132
    }
133
134
    /**
135
     * Get the frontend title for this widget
136
     *
137
     * @return string
138
     */
139
    public function getTitle()
140
    {
141
        return $this->getField('Title')
142
            ?: _t($this->class . '.TITLE', $this->config()->title);
143
    }
144
145
    /**
146
     * @return string
147
     * @deprecated
148
     */
149
    public function CMSTitle()
150
    {
151
        return $this->getCMSTitle();
152
    }
153
154
    /**
155
     * @return string
156
     */
157
    public function getCMSTitle()
158
    {
159
        return _t($this->class . '.CMSTITLE', $this->config()->cmsTitle);
160
    }
161
162
    /**
163
     * @return string
164
     * @deprecated
165
     */
166
    public function Description()
167
    {
168
        return $this->getDescription();
169
    }
170
171
    /**
172
     * @return string
173
     */
174
    public function getDescription()
175
    {
176
        return _t($this->class . '.DESCRIPTION', $this->config()->description);
177
    }
178
179
    /**
180
     * @return string - HTML
181
     */
182
    public function DescriptionSegment()
183
    {
184
        return $this->renderWith('WidgetDescription');
185
    }
186
187
    /**
188
     * @see WidgetController::editablesegment()
189
     *
190
     * @return string - HTML
191
     */
192
    public function EditableSegment()
193
    {
194
        return $this->renderWith('WidgetEditor');
195
    }
196
197
    /**
198
     * @return FieldList
199
     */
200
    public function getCMSFields()
201
    {
202
        $fields = new FieldList(
203
            new TextField('Title', $this->fieldLabel('Title'), null, 255),
204
            new CheckboxField('Enabled', $this->fieldLabel('Enabled'))
205
        );
206
        $this->extend('updateCMSFields', $fields);
207
208
        return $fields;
209
    }
210
211
    /**
212
     * @return FieldList
213
     */
214
    public function CMSEditor()
215
    {
216
        $fields = $this->getCMSFields();
217
        $outputFields = new FieldList();
218
219
        $this->FormID = $this->ID ?: uniqid();
0 ignored issues
show
Documentation introduced by
The property FormID does not exist on object<Widget>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
220
        $outputFields->push(HiddenField::create('Widget[' . $this->FormID . '][FormID]', 'FormID',
0 ignored issues
show
Documentation introduced by
The property FormID does not exist on object<Widget>. 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...
221
            $this->FormID)->addExtraClass('formid'));
0 ignored issues
show
Documentation introduced by
The property FormID does not exist on object<Widget>. 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...
222
223
        foreach ($fields as $field) {
224
            $name = $field->getName();
225
            $value = $this->getField($name);
226
            if ($value) {
227
                $field->setValue($value);
228
            }
229
            $namefiltered = preg_replace("/([A-Za-z0-9\-_]+)/", "Widget[" . $this->FormID . "][\\1]", $name);
0 ignored issues
show
Documentation introduced by
The property FormID does not exist on object<Widget>. 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...
230
231
            $field->setName($namefiltered);
232
            $outputFields->push($field);
233
        }
234
235
        return $outputFields;
236
    }
237
238
    /**
239
     * @return string
240
     */
241
    public function ClassName()
242
    {
243
        return $this->class;
244
    }
245
246
    /**
247
     * @return string
248
     */
249
    public function Name()
250
    {
251
        return "Widget[" . $this->ID . "]";
252
    }
253
254
    /**
255
     * @throws Exception
256
     *
257
     * @return WidgetController
258
     */
259
    public function getController()
260
    {
261
        if ($this->controller) {
262
            return $this->controller;
263
        }
264
265
        foreach (array_reverse(ClassInfo::ancestry($this->class)) as $widgetClass) {
266
            $controllerClass = "{$widgetClass}_Controller";
267
268
            if (class_exists($controllerClass)) {
269
                break;
270
            }
271
272
            $controllerClass = "{$widgetClass}Controller";
273
274
            if (class_exists($controllerClass)) {
275
                break;
276
            }
277
        }
278
279
        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...
280
            throw new Exception("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...
281
        }
282
283
        $this->controller = Injector::inst()->create($controllerClass, $this);
284
285
        return $this->controller;
286
    }
287
288
    /**
289
     * @param array $data
290
     */
291
    public function populateFromPostData($data)
292
    {
293
        $fields = $this->getCMSFields();
294
        foreach ($data as $name => $value) {
295
            if ($name != "Type") {
296
                if ($field = $fields->dataFieldByName($name)) {
297
                    $field->setValue($value);
298
                    $field->saveInto($this);
299
                } else {
300
                    $this->setField($name, $value);
301
                }
302
            }
303
        }
304
305
        //Look for checkbox fields not present in the data
306
        foreach ($fields as $field) {
307
            if ($field instanceof CheckboxField && !array_key_exists($field->getName(), $data)) {
308
                $field->setValue(false);
309
                $field->saveInto($this);
310
            }
311
        }
312
313
        $this->write();
314
315
        // The field must be written to ensure a unique ID.
316
        $this->Name = $this->class . $this->ID;
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<Widget>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
317
        $this->write();
318
    }
319
    
320
    public function canView($member = null)
321
    {
322
        return true;
323
    }
324
}
325