BuildFormBootstrap.php 13.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 1/25/16
 * Time: 10:00 PM
 */

namespace qfq;

use qfq;
12
use qfq\UserFormException;
13
use TYPO3\CMS\Form\Domain\Model\Element\ButtonElement;
14
15

require_once(__DIR__ . '/../qfq/Constants.php');
16
require_once(__DIR__ . '/../qfq/helper/OnArray.php');
17
require_once(__DIR__ . '/../qfq/AbstractBuildForm.php');
18
require_once(__DIR__ . '/../qfq/exceptions/UserFormException.php');
19

Carsten  Rose's avatar
Carsten Rose committed
20
21
22
23
/**
 * Class BuildFormBootstrap
 * @package qfq
 */
24
25
class BuildFormBootstrap extends AbstractBuildForm {

26
27
28
29
30
31
32
33
34
35
    private $isFirstPill;

    /**
     * @param array $formSpec
     * @param array $feSpecAction
     * @param array $feSpecNative
     */
    public function __construct(array $formSpec, array $feSpecAction, array $feSpecNative) {
        parent::__construct($formSpec, $feSpecAction, $feSpecNative);
        $this->isFirstPill = true;
36
37

        // Set some defaults
38
39
40
//        if (!isset($this->formSpec['class'])) {
//            $this->formSpec['class'] = 'container';
//        }
Carsten  Rose's avatar
Carsten Rose committed
41

42
//        $this->formSpec['class'] = 'none';
43
44
    }

Carsten  Rose's avatar
Carsten Rose committed
45
46
47
    /**
     *
     */
48
    public function fillWrap() {
49
50
51
52
53


//        $this->wrap[WRAP_SETUP_OUTER][WRAP_SETUP_START] = '<div class="tab-content">';
//        $this->wrap[WRAP_SETUP_OUTER][WRAP_SETUP_END] = '</div>';

54
55
        $this->wrap[WRAP_SETUP_TITLE][WRAP_SETUP_START] = '<div class="row hidden-xs"><div class="col-md-12"><h1>';
        $this->wrap[WRAP_SETUP_TITLE][WRAP_SETUP_END] = '</h1></div></div>';
56

57
        // Element: Label + Input + Note
58
59
        $this->wrap[WRAP_SETUP_ELEMENT][WRAP_SETUP_START] = '<div class="form-group">';
        $this->wrap[WRAP_SETUP_ELEMENT][WRAP_SETUP_END] = '</div>';
60

61
62
63
64
65
66
67
68
69
        $this->wrap[WRAP_SETUP_LABEL][WRAP_SETUP_START] = '<div class="col-md-2">';
        $this->wrap[WRAP_SETUP_LABEL][WRAP_SETUP_END] = '</div>';
        $this->wrap[WRAP_SETUP_INPUT][WRAP_SETUP_START] = '<div class="col-md-6">';
        $this->wrap[WRAP_SETUP_INPUT][WRAP_SETUP_END] = '</div>';
        $this->wrap[WRAP_SETUP_NOTE][WRAP_SETUP_START] = '<div class="col-md-4">';
        $this->wrap[WRAP_SETUP_NOTE][WRAP_SETUP_END] = '</div>';

        $this->wrap[WRAP_SETUP_SUBRECORD][WRAP_SETUP_START] = '<div class="col-md-12">';
        $this->wrap[WRAP_SETUP_SUBRECORD][WRAP_SETUP_END] = '</div>';
70
71
72
73

        $this->wrap[WRAP_SETUP_IN_FIELDSET][WRAP_SETUP_START] = '<p>';
        $this->wrap[WRAP_SETUP_IN_FIELDSET][WRAP_SETUP_END] = '</p>';

74
75
//        $this->feDivClass['radio'] = 'radio';
//        $this->feDivClass['checkbox'] = 'checkbox';
76
77
    }

Carsten  Rose's avatar
Carsten Rose committed
78
79
80
    /**
     * @return string
     */
81
82
83
84
    public function getProcessFilter() {
        return FORM_ELEMENTS_NATIVE_SUBRECORD;
    }

Carsten  Rose's avatar
Carsten Rose committed
85
86
87
    /**
     * @return string
     */
88
89
90
91
92
93
94
95
    public function doSubrecords() {
        return '';
    }

    /**
     * @return string
     */
    public function head() {
96
        $html = '';
97

98
        $html .= '<div ' . Support::doAttribute('class', $this->formSpec['class'], TRUE) . '>'; // main <div class=...> around everything, Whole FORM; class="container" or class="container-fluid"
99

100
101
102
        $title = Support::wrapTag('<div class="hidden-xs col-sm-6 col-md-8">', Support::wrapTag('<h3>', $this->formSpec['title']));
        $button = Support::wrapTag('<div class="col-xs-12 col-sm-6 col-md-4">', $this->buildButtons());
        $html .= Support::wrapTag('<div class="row">', $title . $button);
103
104


105
106
        $pill = $this->buildPillNavigation(OnArray::filter($this->feSpecNative, 'type', 'pill'));
        $html .= Support::wrapTag('<div class="row">', $pill);
107

108
109
        $html .= $this->getFormTag();

110
        $html .= '<div class="tab-content">';
111
112
113
114

        return $html;
    }

115
    /**
116
     * Simulate Submit Button: http://www.javascript-coder.com/javascript-form/javascript-form-submit.phtml
117
118
119
120
121
     *
     * @return string
     */
    private function buildButtons() {
        $buttonNew = '';
122
123
124
125
        $buttonDelete = '';
        $buttonClose = '';
        $buttonSave = '';
        $buttonEditForm = '';
Carsten  Rose's avatar
Carsten Rose committed
126
127
128
129
130
        $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP);


        // Button: FormEdit
        if ($this->showDebugInfo) {
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
            $toolTip = "Edit form" . PHP_EOL . PHP_EOL . OnArray::toString($this->store->getStore(STORE_SIP), ' = ', PHP_EOL, "'");
            $url = $this->createFormEditUrl();

            $buttonEditForm = $this->buildButtonAnchor('form-edit-button', $url, $toolTip, 'glyphicon-wrench');
        }

        // Button: Save
        if (Support::findInSet(FORM_BUTTON_SAVE, $this->formSpec['showButton'])) {
            $toolTip = 'Save';

            if ($this->showDebugInfo) {
                $toolTip .= PHP_EOL . "table = '" . $this->formSpec['tableName'] . "'" . PHP_EOL . "r = '" . $recordId . "'";
            }

            $buttonSave = $this->buildButtonCode('save-button', $toolTip, 'glyphicon-ok');
        }

        // Button: Close
        if (Support::findInSet(FORM_BUTTON_CLOSE, $this->formSpec['showButton'])) {
            $toolTip = 'Close';

            if ($this->showDebugInfo) {
                $toolTip .= PHP_EOL . "table = '" . $this->formSpec['tableName'] . "'" . PHP_EOL . "r = '" . $recordId . "'";
            }

            $buttonClose = $this->buildButtonCode('close-button', 'Close', 'glyphicon-remove');
Carsten  Rose's avatar
Carsten Rose committed
157
        }
158

Carsten  Rose's avatar
Carsten Rose committed
159
        // Button: Delete
160
        if (Support::findInSet(FORM_BUTTON_DELETE, $this->formSpec['showButton'])) {
161
162
            $toolTip = 'Delete';

Carsten  Rose's avatar
Carsten Rose committed
163
            if ($this->showDebugInfo && $recordId > 0) {
164
                $toolTip .= PHP_EOL . "table = '" . $this->formSpec['tableName'] . "'" . PHP_EOL . "r = '" . $recordId . "'";
Carsten  Rose's avatar
Carsten Rose committed
165
            }
166
            $disabled = ($recordId > 0) ? '' : 'disabled';
Carsten  Rose's avatar
Carsten Rose committed
167

168
            $buttonDelete = $this->buildButtonCode('delete-button', $toolTip, 'glyphicon-trash', $disabled);
169
170
        }

Carsten  Rose's avatar
Carsten Rose committed
171
        // Button: New
172
        if (Support::findInSet(FORM_BUTTON_NEW, $this->formSpec['showButton'])) {
173
174
            $toolTip = 'New';
            $url = $this->deriveNewRecordUrlFromExistingSip($toolTip);
Carsten  Rose's avatar
Carsten Rose committed
175

176
            $buttonNew = $this->buildButtonAnchor('form-new-button', $url, $toolTip, 'glyphicon-plus');
177
178
        }

179
180
181
182
183
184
185
        $html = Support::wrapTag('<div class="btn-group" role="group">', $buttonEditForm);
        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonSave . $buttonClose);
        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonDelete);
        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonNew);

        $html = Support::wrapTag('<div class="btn-toolbar" role="toolbar">', $html);

186
187
188
        return $html;
    }

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    /**
     * @param $id
     * @param $url
     * @param $title
     * @param $icon
     * @param string $disabled
     * @return string
     */
    private function buildButtonAnchor($id, $url, $title, $icon, $disabled = '') {
        return "<a href='$url' id='$id' class='btn btn-default navbar-btn $disabled' " . Support::doAttribute('title', $title) . "><span class='glyphicon $icon'></span></a>";
    }

    /**
     * @param $id
     * @param $title
     * @param $icon
     * @param string $disabled
     * @return string
     */
    private function buildButtonCode($id, $title, $icon, $disabled = '') {
        return "<button id='$id' type='button' class='btn btn-default navbar-btn $disabled' " . Support::doAttribute('title', $title) . "><span class='glyphicon $icon'></span></button>";
    }

Carsten  Rose's avatar
Carsten Rose committed
212
    /**
213
     * @param $pillArray
Carsten  Rose's avatar
Carsten Rose committed
214
     * @return string
215
     * @throws UserFormException
Carsten  Rose's avatar
Carsten Rose committed
216
     */
217
218
219
    private function buildPillNavigation($pillArray) {
        $pillButton = '';
        $pillDropdown = '';
220
        $htmlDropdown = '';
221
222
223
224
225
226
227
228
229
230
231
232
233

        if ($pillArray == null)
            return '';

        $maxVisiblePill = (isset($this->formSpec['maxVisiblePill']) && $this->formSpec['maxVisiblePill'] !== '') ? $this->formSpec['maxVisiblePill'] : 1000;

        // Iterate over all 'pill'
        $ii = 0;
        $active = 'class="active"';
        foreach ($pillArray as $formElement) {
            $ii++;

            if ($formElement['name'] === '' || $formElement['label'] === '') {
234
                $this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($formElement), STORE_SYSTEM);
235
                $this->store->setVar(SYSTEM_FORM_ELEMENT_COLUMN, 'name, label', STORE_SYSTEM);
236
                throw new UserFormException("Field 'name' and/or 'label' are empty", ERROR_NAME_LABEL_EMPTY);
237
238
            }

239
            // Anker for pill navigation
240
            $a = '<a href="#' . $this->createAnker($formElement['id']) . '" data-toggle="tab">' . $formElement['label'] . '</a>';
241

242
243
244
245
246
247
248
            if ($ii <= $maxVisiblePill) {
                $pillButton .= '<li role="presentation" ' . $active . '>' . $a . '</li>';
            } else {
                $pillDropdown .= '<li>' . $a . '</li>';
            }
            $active = '';
        }
249

250
251
        // Pill Dropdown necessary?
        if ($ii > $maxVisiblePill) {
252
253
            $htmlDropdown = Support::wrapTag('<ul class="dropdown-menu">', $pillDropdown, true);
            $htmlDropdown = '<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button">more <span class="caret"></span></a>' . $htmlDropdown;
254
            $htmlDropdown = Support::wrapTag('<li role="presentation" class="dropdown">', $htmlDropdown, false);
255
        }
256

257
        $htmlDropdown = Support::wrapTag('<ul id="' . $this->getTabId() . '" class="nav nav-pills" role="tablist">', $pillButton . $htmlDropdown);
258
        $htmlDropdown = Support::wrapTag('<div class="col-md-12">', $htmlDropdown);
259

260
        return $htmlDropdown;
261
262
263
264
265
266
267
268
269
270
271
272
    }

    /**
     * Create an identifier for the pill navigation menu
     *
     * @param $id
     * @return string
     */
    private function createAnker($id) {
        return $this->formSpec['name'] . '_' . $id;
    }

Carsten  Rose's avatar
Carsten Rose committed
273
274
275
276
277
278
279
    /**
     * @return string
     */
    private function getTabId() {
        return 'qfqTabs';
    }

280
281
282
283
284
    /**
     * Builds the complete HTML '<form ...>'-tag
     *
     * @return string
     */
285
    public function getFormTag() {
286
287
288
289
290
291
292
293

        $attribute = $this->getFormTagAtrributes();

        $attribute['class'] = 'form-horizontal';

        return '<form ' . OnArray::toString($attribute, '=', ' ', "'") . '>';
    }

294
295
296
297
298
    /**
     * @return string
     */
    public function tail() {
        $html = '';
299
//        $html .= $this->buildNewSip();
Carsten  Rose's avatar
Carsten Rose committed
300
        $deleteUrl = '';
301

302
303
        $formId = $this->getFormId();

304
        $html .= '</div> <!--class="tab-content" -->';  //  <div class="tab-content">
305
//        $html .= '<input type="submit" value="Submit">';
306

Carsten  Rose's avatar
Carsten Rose committed
307
308
309
        $formId = $this->getFormId();
        $tabId = $this->getTabId();

Carsten  Rose's avatar
Carsten Rose committed
310
311
312
        if (0 < ($recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP))) {
            $deleteUrl = $this->createDeleteUrl($this->formSpec['tableName'], $recordId);
        }
313

314
        $html .= '</form>';  //  <form class="form-horizontal" ...
315
316
317
318
319
320
        $html .= <<<EOF
        <script type="text/javascript">
            $(function () {
                'use strict';
                QfqNS.Log.level = 0;

Carsten  Rose's avatar
Carsten Rose committed
321

Carsten  Rose's avatar
Carsten Rose committed
322
323
324
325
                var qfqPage = new QfqNS.QfqPage({
                    tabsId: '$tabId',
                    formId: '$formId',
                    submitTo: 'typo3conf/ext/qfq/qfq/api/save.php',
Carsten  Rose's avatar
Carsten Rose committed
326
327
328
                    deleteUrl: '$deleteUrl',
                    refreshUrl: "typo3conf/ext/qfq/qfq/api/load.php"

Carsten  Rose's avatar
Carsten Rose committed
329
330
331
                });

                var qfqRecordList = new QfqNS.QfqRecordList('typo3conf/ext/qfq/qfq/api/delete.php');
Carsten  Rose's avatar
Carsten Rose committed
332
            })
333
334
         </script>
EOF;
335
        $html .= '</div>';  //  <div class="container-fluid"> === main <div class=...> around everything
336

337
338
339
340
341
342
343
344
345
        return $html;
    }

    /**
     * @param array $formElement
     * @param $htmlFormElementId
     * @param $value
     * @return mixed
     */
Carsten  Rose's avatar
Carsten Rose committed
346
    public function buildPill(array $formElement, $htmlFormElementId, $value, &$json) {
347
        $html = '';
348
349
350
351
        // save parent processed FE's
        $tmpStore = $this->feSpecNative;

        // child FE's
352
        $sql = SQL_FORM_ELEMENT_SPECIFIC_CONTAINER;
353
        $this->feSpecNative = $this->db->sql($sql, ROW_REGULAR, ['yes', $this->formSpec["id"], 'native,container', $formElement['id']]);
354
        HelperFormElement::explodeParameterInArrayElements($this->feSpecNative);
Carsten  Rose's avatar
Carsten Rose committed
355
        $html = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), FORM_ELEMENTS_NATIVE_SUBRECORD, 0, $json);
356
357
358
359

        // restore parent processed FE's
        $this->feSpecNative = $tmpStore;

360
361
362
        return $html;
    }

363
364
365
366
367
    /**
     * @param $formElement
     * @param $elementHtml
     * @return string
     */
368
369
370
371
372
373
374
375
376
377
378
379
    public function buildRowNative($formElement, $elementHtml) {
        $html = '';

        $html .= $this->wrapItem(WRAP_SETUP_LABEL, $formElement['label']);
        $html .= $this->wrapItem(WRAP_SETUP_INPUT, $elementHtml);
        $html .= $this->wrapItem(WRAP_SETUP_NOTE, $formElement['note'], true);

        $html = $this->wrapItem(WRAP_SETUP_ELEMENT, $html);

        return $html;
    }

380
381
382
383
384
    /**
     * @param $formElement
     * @param $elementHtml
     * @return string
     */
385
386
387
388
389
390
391
    public function buildRowPill($formElement, $elementHtml) {
        $html = '';

        $html .= $this->wrapItem(WRAP_SETUP_INPUT, $elementHtml);

        $active = $this->isFirstPill ? ' active' : '';

392
        $html = Support::wrapTag('<div role="tabpanel" class="tab-pane' . $active . '" id="' . $this->createAnker($formElement['id']) . '">', $html);
393
394
395
396
397
398

        $this->isFirstPill = false;

        return $html;
    }

399
400
401
402
    /**
     * @param $formElement
     * @param $elementHtml
     */
403
404
405
    public function buildRowFieldset($formElement, $elementHtml) {
    }

406
407
408
409
410
    /**
     * @param $formElement
     * @param $elementHtml
     * @return string
     */
411
412
413
414
415
    public function buildRowSubrecord($formElement, $elementHtml) {
        $html = '';
        $html .= $this->wrapItem(WRAP_SETUP_ELEMENT, $this->wrapItem(WRAP_SETUP_SUBRECORD, $formElement['label']));
        $html .= $this->wrapItem(WRAP_SETUP_ELEMENT, $this->wrapItem(WRAP_SETUP_SUBRECORD, $elementHtml));
        $html .= $this->wrapItem(WRAP_SETUP_ELEMENT, $this->wrapItem(WRAP_SETUP_SUBRECORD, $formElement['note']));
416
417
418

        return $html;
    }
419
}