Passed
Pull Request — 4 (#10222)
by Steve
07:01
created

TabSet::__construct()   C

Complexity

Conditions 12
Paths 13

Size

Total Lines 40
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 21
nc 13
nop 3
dl 0
loc 40
rs 6.9666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SilverStripe\Forms;
4
5
use SilverStripe\Core\Convert;
6
use SilverStripe\ORM\FieldType\DBHTMLText;
7
use SilverStripe\View\Requirements;
8
use InvalidArgumentException;
9
10
/**
11
 * Defines a set of tabs in a form.
12
 * The tabs are build with our standard tabstrip javascript library.
13
 * By default, the HTML is generated using FieldHolder.
14
 *
15
 * <b>Usage</b>
16
 *
17
 * <code>
18
 * new TabSet(
19
 *  $name = "TheTabSetName",
20
 *  new Tab(
21
 *      $title='Tab one',
22
 *      new HeaderField("A header"),
23
 *      new LiteralField("Lipsum","Lorem ipsum dolor sit amet enim.")
24
 *  ),
25
 *  new Tab(
26
 *      $title='Tab two',
27
 *      new HeaderField("A second header"),
28
 *      new LiteralField("Lipsum","Ipsum dolor sit amet enim.")
29
 *  )
30
 * )
31
 * </code>
32
 *
33
 * Caution: The form field does not include any JavaScript or CSS when used outside of the CMS context,
34
 * since the required frontend dependencies are included through CMS bundling.
35
 */
36
class TabSet extends CompositeField
37
{
38
39
    /**
40
     * Use custom react component
41
     *
42
     * @var string
43
     */
44
    protected $schemaComponent = 'Tabs';
45
46
    /**
47
     * @var TabSet
48
     */
49
    protected $tabSet;
50
51
    /**
52
     * @var string
53
     */
54
    protected $id;
55
56
    /**
57
     * @param string $name Identifier
58
     * @param string|Tab|TabSet $titleOrTab Natural language title of the tabset, or first tab.
59
     * If its left out, the class uses {@link FormField::name_to_label()} to produce a title
60
     * from the {@link $name} parameter.
61
     * @param Tab|TabSet ...$tabs All further parameters are inserted as children into the TabSet
62
     */
63
    public function __construct($name, $titleOrTab = null, $tabs = null)
64
    {
65
        if (!is_string($name)) {
66
            throw new InvalidArgumentException('Invalid string parameter for $name');
67
        }
68
69
        // Get following arguments
70
        $tabs = func_get_args();
71
        array_shift($tabs);
72
73
        // Detect title from second argument, if it is a string
74
        if ($titleOrTab && is_string($titleOrTab)) {
75
            $title = $titleOrTab;
76
            array_shift($tabs);
77
        } else {
78
            $title = static::name_to_label($name);
79
        }
80
81
        // Normalise children list
82
        if (count($tabs ?: []) === 1 && (is_array($tabs[0]) || $tabs[0] instanceof FieldList)) {
83
            $tabs = $tabs[0];
84
        }
85
86
        // Ensure tabs are assigned to this tabset
87
        if ($tabs) {
88
            foreach ($tabs as $tab) {
89
                if ($tab instanceof Tab || $tab instanceof TabSet) {
90
                    $tab->setTabSet($this);
91
                } else {
92
                    throw new InvalidArgumentException("TabSet can only contain instances of other Tab or Tabsets");
93
                }
94
            }
95
        }
96
97
        parent::__construct($tabs);
98
99
        // Assign name and title (not assigned by parent constructor)
100
        $this->setName($name);
101
        $this->setTitle($title);
102
        $this->setID(Convert::raw2htmlid($name));
103
    }
104
105
    public function ID()
106
    {
107
        if ($this->tabSet) {
108
            return $this->tabSet->ID() . '_' . $this->id . '_set';
109
        }
110
        return $this->id;
111
    }
112
113
    /**
114
     * Set custom HTML ID to use for this tabset
115
     *
116
     * @param string $id
117
     * @return $this
118
     */
119
    public function setID($id)
120
    {
121
        $this->id = $id;
122
        return $this;
123
    }
124
125
    /**
126
     * Returns a tab-strip and the associated tabs.
127
     * The HTML is a standardised format, containing a &lt;ul;
128
     *
129
     * @param array $properties
130
     * @return DBHTMLText|string
131
     */
132
    public function FieldHolder($properties = [])
133
    {
134
        $obj = $properties ? $this->customise($properties) : $this;
135
136
        return $obj->renderWith($this->getTemplates());
137
    }
138
139
    /**
140
     * Return a set of all this classes tabs
141
     *
142
     * @return FieldList
143
     */
144
    public function Tabs()
145
    {
146
        return $this->children;
147
    }
148
149
    /**
150
     * @param FieldList $children Assign list of tabs
151
     */
152
    public function setTabs($children)
153
    {
154
        $this->children = $children;
155
    }
156
157
    /**
158
     * Assign to a TabSet instance
159
     *
160
     * @param TabSet $val
161
     * @return $this
162
     */
163
    public function setTabSet($val)
164
    {
165
        $this->tabSet = $val;
166
        return $this;
167
    }
168
169
    /**
170
     * Get parent tabset
171
     *
172
     * @return TabSet
173
     */
174
    public function getTabSet()
175
    {
176
        return $this->tabSet;
177
    }
178
179
    public function getAttributes()
180
    {
181
        $attributes = array_merge(
182
            $this->attributes,
183
            [
184
                'id' => $this->ID(),
185
                'class' => $this->extraClass()
186
            ]
187
        );
188
189
        $this->extend('updateAttributes', $attributes);
190
191
        return $attributes;
192
    }
193
194
    /**
195
     * Add a new child field to the end of the set.
196
     *
197
     * @param FormField $field
198
     */
199
    public function push(FormField $field)
200
    {
201
        if ($field instanceof Tab || $field instanceof TabSet) {
202
            $field->setTabSet($this);
203
        }
204
        parent::push($field);
205
    }
206
207
    /**
208
     * Add a new child field to the beginning of the set.
209
     *
210
     * @param FormField $field
211
     */
212
    public function unshift(FormField $field)
213
    {
214
        if ($field instanceof Tab || $field instanceof TabSet) {
215
            $field->setTabSet($this);
216
        }
217
        parent::unshift($field);
218
    }
219
220
    /**
221
     * Inserts a field before a particular field in a FieldList.
222
     *
223
     * @param string $insertBefore Name of the field to insert before
224
     * @param FormField $field The form field to insert
225
     * @param bool $appendIfMissing
226
     * @return FormField|null
227
     */
228
    public function insertBefore($insertBefore, $field, $appendIfMissing = true)
229
    {
230
        if ($field instanceof Tab || $field instanceof TabSet) {
231
            $field->setTabSet($this);
232
        }
233
        return parent::insertBefore($insertBefore, $field, $appendIfMissing);
234
    }
235
236
    /**
237
     * Inserts a field after a particular field in a FieldList.
238
     *
239
     * @param string $insertAfter Name of the field to insert after
240
     * @param FormField $field The form field to insert
241
     * @param bool $appendIfMissing
242
     * @return FormField|null
243
     */
244
    public function insertAfter($insertAfter, $field, $appendIfMissing = true)
245
    {
246
        if ($field instanceof Tab || $field instanceof TabSet) {
247
            $field->setTabSet($this);
248
        }
249
        return parent::insertAfter($insertAfter, $field, $appendIfMissing);
250
    }
251
252
    /**
253
     * Sets an additional default for $schemaData.
254
     * The existing keys are immutable. HideNav is added in this overriding method to ensure it is not ignored by
255
     * {@link setSchemaData()}
256
     * It allows hiding of the navigation in the Tabs.js React component.
257
     *
258
     * @return array
259
     */
260
    public function getSchemaStateDefaults()
261
    {
262
        $defaults = parent::getSchemaStateDefaults();
263
        $defaults['hideNav'] = false;
264
        return $defaults;
265
    }
266
}
267