Widget::getController()   A
last analyzed

Complexity

Conditions 6
Paths 10

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 23
rs 9.2222
c 0
b 0
f 0
cc 6
nc 10
nop 0
1
<?php
2
3
namespace SilverStripe\Widgets\Model;
4
5
use Exception;
6
use SilverStripe\Control\HTTPRequest;
7
use SilverStripe\Core\ClassInfo;
8
use SilverStripe\Core\Injector\Injector;
9
use SilverStripe\Forms\CheckboxField;
10
use SilverStripe\Forms\FieldList;
11
use SilverStripe\Forms\HiddenField;
12
use SilverStripe\Forms\TextField;
13
use SilverStripe\ORM\DataObject;
14
use SilverStripe\ORM\FieldType\DBHTMLText;
15
use SilverStripe\Versioned\Versioned;
16
17
/**
18
 * Widgets let CMS authors drag and drop small pieces of functionality into
19
 * defined areas of their websites.
20
 *
21
 * You can use forms in widgets by implementing a {@link WidgetController}.
22
 *
23
 * See {@link WidgetController} for more information.
24
 *
25
 * @package widgets
26
 */
27
class Widget extends DataObject
28
{
29
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
30
        "Title" => "Varchar(255)",
31
        "Sort" => "Int",
32
        "Enabled" => "Boolean",
33
    ];
34
35
    private static $defaults = [
0 ignored issues
show
introduced by
The private property $defaults is not used, and could be removed.
Loading history...
36
        'Enabled' => true,
37
    ];
38
39
    private static $casting = [
0 ignored issues
show
introduced by
The private property $casting is not used, and could be removed.
Loading history...
40
        'CMSTitle' => 'Text',
41
        'Description' => 'Text',
42
    ];
43
44
    private static $only_available_in = [];
0 ignored issues
show
introduced by
The private property $only_available_in is not used, and could be removed.
Loading history...
45
46
    private static $has_one = [
0 ignored issues
show
introduced by
The private property $has_one is not used, and could be removed.
Loading history...
47
        "Parent" => WidgetArea::class,
48
    ];
49
50
    private static $default_sort = "\"Sort\"";
0 ignored issues
show
introduced by
The private property $default_sort is not used, and could be removed.
Loading history...
51
52
    /**
53
     * @var string
54
     */
55
    private static $cmsTitle = "Name of this widget";
0 ignored issues
show
introduced by
The private property $cmsTitle is not used, and could be removed.
Loading history...
56
57
    /**
58
     * @var string
59
     */
60
    private static $description = "Description of what this widget does.";
0 ignored issues
show
introduced by
The private property $description is not used, and could be removed.
Loading history...
61
62
    private static $summary_fields = [
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
63
        'CMSTitle' => 'Title'
64
    ];
65
66
    private static $table_name = 'Widget';
0 ignored issues
show
introduced by
The private property $table_name is not used, and could be removed.
Loading history...
67
68
    private static $extensions = [
0 ignored issues
show
introduced by
The private property $extensions is not used, and could be removed.
Loading history...
69
        Versioned::class,
70
    ];
71
72
    /**
73
     * @var WidgetController
74
     */
75
    protected $controller;
76
77
    public function populateDefaults()
78
    {
79
        parent::populateDefaults();
80
        $this->setField('Title', $this->getTitle());
81
    }
82
83
    /**
84
     * Note: Overloaded in {@link WidgetController}.
85
     *
86
     * @return string HTML
87
     */
88
    public function WidgetHolder()
89
    {
90
        return $this->renderWith("WidgetHolder");
91
    }
92
93
    /**
94
     * Default way to render widget in templates.
95
     * @return string HTML
96
     */
97
    public function forTemplate($holder = true)
98
    {
99
        if ($holder) {
100
            return $this->WidgetHolder();
101
        }
102
103
        return $this->Content();
104
    }
105
106
    /**
107
     * Renders the widget content in a custom template with the same name as the
108
     * current class. This should be the main point of output customization.
109
     *
110
     * Invoked from within WidgetHolder.ss, which contains the "framing" around
111
     * the custom content, like a title.
112
     *
113
     * Note: Overloaded in {@link WidgetController}.
114
     *
115
     * @return string HTML
116
     */
117
    public function Content()
118
    {
119
        return $this->renderWith(array_reverse(ClassInfo::ancestry(__CLASS__)));
120
    }
121
122
    /**
123
     * @return string
124
     */
125
    public function getCMSTitle()
126
    {
127
        return _t(__CLASS__ . '.CMSTITLE', $this->config()->get('cmsTitle'));
128
    }
129
130
    /**
131
     * @return string
132
     */
133
    public function getDescription()
134
    {
135
        return _t(__CLASS__ . '.DESCRIPTION', $this->config()->get('description'));
136
    }
137
138
    /**
139
     * @return string - HTML
140
     */
141
    public function DescriptionSegment()
142
    {
143
        return $this->renderWith('WidgetDescription');
144
    }
145
146
    /**
147
     * @see WidgetController::editablesegment()
148
     *
149
     * @return string - HTML
150
     */
151
    public function EditableSegment()
152
    {
153
        return $this->renderWith('WidgetEditor');
154
    }
155
156
    /**
157
     * @return FieldList
158
     */
159
    public function getCMSFields()
160
    {
161
        $fields = new FieldList(
162
            new TextField('Title', $this->fieldLabel('Title'), null, 255),
163
            new CheckboxField('Enabled', $this->fieldLabel('Enabled'))
164
        );
165
        $this->extend('updateCMSFields', $fields);
166
167
        return $fields;
168
    }
169
170
    /**
171
     * @return FieldList
172
     */
173
    public function CMSEditor()
174
    {
175
        $fields = $this->getCMSFields();
176
        $outputFields = new FieldList();
177
178
        $this->FormID = $this->ID ?: uniqid();
0 ignored issues
show
Bug Best Practice introduced by
The property FormID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
179
        $outputFields->push(
180
            HiddenField::create(
181
                'Widget[' . $this->FormID . '][FormID]',
182
                'FormID',
183
                $this->FormID
184
            )->addExtraClass('formid')
185
        );
186
187
        foreach ($fields as $field) {
188
            $name = $field->getName();
189
            $value = $this->getField($name);
190
            if ($value) {
191
                $field->setValue($value);
192
            }
193
            $namefiltered = preg_replace("/([A-Za-z0-9\-_]+)/", "Widget[" . $this->FormID . "][\\1]", $name);
194
195
            $field->setName($namefiltered);
196
            $outputFields->push($field);
197
        }
198
199
        return $outputFields;
200
    }
201
202
    /**
203
     * A fully qualified class name is returned with underscores instead of backslashes so it is HTML safe. Dashes
204
     * can't be used as they're handled in the Javascript for other purposes.
205
     *
206
     * @return string
207
     */
208
    public function ClassName()
209
    {
210
        return str_replace('\\', '_', get_class($this));
211
    }
212
213
    /**
214
     * @return string
215
     */
216
    public function Name()
217
    {
218
        return "Widget[" . $this->ID . "]";
219
    }
220
221
    /**
222
     * @throws Exception If the widget controller's class name couldn't be found
223
     *
224
     * @return WidgetController
225
     */
226
    public function getController()
227
    {
228
        if ($this->controller) {
229
            return $this->controller;
230
        }
231
232
        foreach (array_reverse(ClassInfo::ancestry(get_class($this))) as $widgetClass) {
233
            $controllerClass = "{$widgetClass}Controller";
234
            if (class_exists($controllerClass)) {
235
                break;
236
            }
237
        }
238
239
        if (!class_exists($controllerClass)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $controllerClass seems to be defined by a foreach iteration on line 232. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
240
            throw new Exception('Could not find controller class for ' . static::class);
241
        }
242
243
        $this->controller = Injector::inst()->create($controllerClass, $this);
244
        if (Injector::inst()->has(HTTPRequest::class)) {
245
            $this->controller->setRequest(Injector::inst()->get(HTTPRequest::class));
246
        }
247
248
        return $this->controller;
249
    }
250
251
    /**
252
     * @param array $data
253
     */
254
    public function populateFromPostData($data)
255
    {
256
        $fields = $this->getCMSFields();
257
        foreach ($data as $name => $value) {
258
            if ($name != "Type") {
259
                if ($field = $fields->dataFieldByName($name)) {
260
                    $field->setValue($value);
261
                    $field->saveInto($this);
262
                } else {
263
                    $this->setField($name, $value);
264
                }
265
            }
266
        }
267
268
        //Look for checkbox fields not present in the data
269
        foreach ($fields as $field) {
270
            if ($field instanceof CheckboxField && !array_key_exists($field->getName(), $data)) {
271
                $field->setValue(false);
272
                $field->saveInto($this);
273
            }
274
        }
275
276
        $this->write();
277
278
        // The field must be written to ensure a unique ID.
279
        $this->Name = get_class($this) . $this->ID;
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
280
        $this->write();
281
    }
282
}
283