Passed
Push — master ( bad1ac...1cdfe7 )
by Robbie
15:25 queued 05:45
created

TabSet::getSchemaStateDefaults()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
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
        } else {
110
            return $this->id;
111
        }
112
    }
113
114
    /**
115
     * Set custom HTML ID to use for this tabset
116
     *
117
     * @param string $id
118
     * @return $this
119
     */
120
    public function setID($id)
121
    {
122
        $this->id = $id;
123
        return $this;
124
    }
125
126
    /**
127
     * Returns a tab-strip and the associated tabs.
128
     * The HTML is a standardised format, containing a &lt;ul;
129
     *
130
     * @param array $properties
131
     * @return DBHTMLText|string
132
     */
133
    public function FieldHolder($properties = array())
134
    {
135
        $obj = $properties ? $this->customise($properties) : $this;
136
137
        return $obj->renderWith($this->getTemplates());
138
    }
139
140
    /**
141
     * Return a set of all this classes tabs
142
     *
143
     * @return FieldList
144
     */
145
    public function Tabs()
146
    {
147
        return $this->children;
148
    }
149
150
    /**
151
     * @param FieldList $children Assign list of tabs
152
     */
153
    public function setTabs($children)
154
    {
155
        $this->children = $children;
156
    }
157
158
    /**
159
     * Assign to a TabSet instance
160
     *
161
     * @param TabSet $val
162
     * @return $this
163
     */
164
    public function setTabSet($val)
165
    {
166
        $this->tabSet = $val;
167
        return $this;
168
    }
169
170
    /**
171
     * Get parent tabset
172
     *
173
     * @return TabSet
174
     */
175
    public function getTabSet()
176
    {
177
        return $this->tabSet;
178
    }
179
180
    public function getAttributes()
181
    {
182
        return array_merge(
183
            $this->attributes,
184
            array(
185
                'id' => $this->ID(),
186
                'class' => $this->extraClass()
187
            )
188
        );
189
    }
190
191
    /**
192
     * Add a new child field to the end of the set.
193
     *
194
     * @param FormField $field
195
     */
196
    public function push(FormField $field)
197
    {
198
        if ($field instanceof Tab || $field instanceof TabSet) {
199
            $field->setTabSet($this);
200
        }
201
        parent::push($field);
202
    }
203
204
    /**
205
     * Add a new child field to the beginning of the set.
206
     *
207
     * @param FormField $field
208
     */
209
    public function unshift(FormField $field)
210
    {
211
        if ($field instanceof Tab || $field instanceof TabSet) {
212
            $field->setTabSet($this);
213
        }
214
        parent::unshift($field);
215
    }
216
217
    /**
218
     * Inserts a field before a particular field in a FieldList.
219
     *
220
     * @param string $insertBefore Name of the field to insert before
221
     * @param FormField $field The form field to insert
222
     * @return FormField|null
223
     */
224
    public function insertBefore($insertBefore, $field, $appendIfMissing = true)
225
    {
226
        if ($field instanceof Tab || $field instanceof TabSet) {
227
            $field->setTabSet($this);
228
        }
229
        return parent::insertBefore($insertBefore, $field, $appendIfMissing);
230
    }
231
232
    /**
233
     * Inserts a field after a particular field in a FieldList.
234
     *
235
     * @param string $insertAfter Name of the field to insert after
236
     * @param FormField $field The form field to insert
237
     * @return FormField|null
238
     */
239
    public function insertAfter($insertAfter, $field, $appendIfMissing = true)
240
    {
241
        if ($field instanceof Tab || $field instanceof TabSet) {
242
            $field->setTabSet($this);
243
        }
244
        return parent::insertAfter($insertAfter, $field, $appendIfMissing);
245
    }
246
247
    /**
248
     * Sets an additional default for $schemaData.
249
     * The existing keys are immutable. HideNav is added in this overriding method to ensure it is not ignored by
250
     * {@link setSchemaData()}
251
     * It allows hiding of the navigation in the Tabs.js React component.
252
     *
253
     * @return array
254
     */
255
    public function getSchemaStateDefaults()
256
    {
257
        $defaults = parent::getSchemaStateDefaults();
258
        $defaults['hideNav'] = false;
259
        return $defaults;
260
    }
261
}
262