Completed
Push — develop ( 2bd525...55adb8 )
by John
02:46
created

RendererProviderHTML::editView()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 43
rs 8.8571
cc 3
eloc 22
nc 4
nop 1
1
<?php
2
3
namespace Alpha\View\Renderer\Html;
4
5
use Alpha\View\Renderer\RendererProviderInterface;
6
use Alpha\View\Widget\Button;
7
use Alpha\View\Widget\TextBox;
8
use Alpha\View\Widget\SmallTextBox;
9
use Alpha\View\Widget\DateBox;
10
use Alpha\View\Widget\RecordSelector;
11
use Alpha\View\View;
12
use Alpha\View\ViewState;
13
use Alpha\Controller\Front\FrontController;
14
use Alpha\Controller\Controller;
15
use Alpha\Util\Logging\Logger;
16
use Alpha\Util\Security\SecurityUtils;
17
use Alpha\Util\Config\ConfigProvider;
18
use Alpha\Util\InputFilter;
19
use Alpha\Util\Service\ServiceFactory;
20
use Alpha\Util\Http\Request;
21
use Alpha\Model\Type\DEnum;
22
use Alpha\Model\Type\SmallText;
23
use Alpha\Model\Type\Text;
24
use Alpha\Model\ActiveRecord;
25
use Alpha\Exception\IllegalArguementException;
26
use Alpha\Exception\AlphaException;
27
use ReflectionClass;
28
29
/**
30
 * HTML renderer.  Will invoke widgets from the Alpha\View\Widgets package
31
 * automatically for the correct data type.  Templates from ./templates/html
32
 * will be loaded by default, but these can be overridden on a per-record level in
33
 * the application when required (consider the default ones to be scaffolding).
34
 *
35
 * @since 1.2
36
 *
37
 * @author John Collins <[email protected]>
38
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
39
 * @copyright Copyright (c) 2017, John Collins (founder of Alpha Framework).
40
 * All rights reserved.
41
 *
42
 * <pre>
43
 * Redistribution and use in source and binary forms, with or
44
 * without modification, are permitted provided that the
45
 * following conditions are met:
46
 *
47
 * * Redistributions of source code must retain the above
48
 *   copyright notice, this list of conditions and the
49
 *   following disclaimer.
50
 * * Redistributions in binary form must reproduce the above
51
 *   copyright notice, this list of conditions and the
52
 *   following disclaimer in the documentation and/or other
53
 *   materials provided with the distribution.
54
 * * Neither the name of the Alpha Framework nor the names
55
 *   of its contributors may be used to endorse or promote
56
 *   products derived from this software without specific
57
 *   prior written permission.
58
 *
59
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
60
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
61
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
62
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
63
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
64
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
65
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
66
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
67
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
69
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
70
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
71
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72
 * </pre>
73
 */
74
class RendererProviderHTML implements RendererProviderInterface
75
{
76
    /**
77
     * Trace logger.
78
     *
79
     * @var \Alpha\Util\Logging\Logger;
80
     *
81
     * @since 1.2
82
     */
83
    private static $logger = null;
84
85
    /**
86
     * The business object that we are renderering.
87
     *
88
     * @var \Alpha\Model\ActiveRecord
89
     *
90
     * @since 1.2
91
     */
92
    private $record;
93
94
    /**
95
     * The constructor.
96
     *
97
     * @since 1.2
98
     */
99
    public function __construct()
100
    {
101
        self::$logger = new Logger('RendererProviderHTML');
102
        self::$logger->debug('>>__construct()');
103
104
        self::$logger->debug('<<__construct');
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function setRecord($Record)
111
    {
112
        $this->record = $Record;
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function createView($fields = array())
119
    {
120
        self::$logger->debug('>>createView(fields=['.var_export($fields, true).'])');
121
122
        // the form ID
123
        $fields['formID'] = stripslashes(get_class($this->record).'_'.$this->record->getID());
124
125
        // buffer form fields to $formFields
126
        $fields['formFields'] = $this->renderAllFields('create');
127
128
        // buffer HTML output for Create and Cancel buttons
129
        $button = new Button('submit', 'Create', 'createBut');
130
        $fields['createButton'] = $button->render();
131
132
        if (isset($fields['cancelButtonURL'])) {
133
            $button = new Button("document.location.replace('".$fields['cancelButtonURL']."')", 'Cancel', 'cancelBut');
134
        } else {
135
            $button = new Button("document.location.replace('".FrontController::generateSecureURL('act=Alpha\\Controller\\ListActiveRecordsController')."')", 'Cancel', 'cancelBut');
136
        }
137
        $fields['cancelButton'] = $button->render();
138
139
        // buffer security fields to $formSecurityFields variable
140
        $fields['formSecurityFields'] = self::renderSecurityFields();
141
142
        self::$logger->debug('<<createView [HTML]');
143
144
        return View::loadTemplate($this->record, 'create', $fields);
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    public function editView($fields = array())
151
    {
152
        self::$logger->debug('>>editView(fields=['.var_export($fields, true).'])');
153
154
        $config = ConfigProvider::getInstance();
155
156
        // the form ID
157
        $fields['formID'] = stripslashes(get_class($this->record).'_'.$this->record->getID());
158
159
        // buffer form fields to $formFields
160
        $fields['formFields'] = $this->renderAllFields('edit');
161
162
        // buffer HTML output for Create and Cancel buttons
163
        $button = new Button('submit', 'Save', 'saveBut');
164
        $fields['saveButton'] = $button->render();
165
166
        $formFieldId = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('ActiveRecordID')) : 'ActiveRecordID');
167
            
168
        $js = View::loadTemplateFragment('html', 'bootstrapconfirmokay.phtml', array('prompt' => 'Are you sure you wish to delete this item?', 'formFieldId' => $formFieldId, 'formFieldValue' => $this->record->getID(), 'formId' => 'deleteForm'));
169
170
        $button = new Button($js, 'Delete', 'deleteBut');
171
        $fields['deleteButton'] = $button->render();
172
173
        $viewState = ViewState::getInstance();
174
        $start = $viewState->get('selectedStart');
175
176
        if (isset($fields['cancelButtonURL'])) {
177
            $button = new Button("document.location = '".$fields['cancelButtonURL']."'", 'Back to List', 'cancelBut');
178
        } else {
179
            $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.get_class($this->record).'&start='.$start.'&limit='.$config->get('app.list.page.amount'))."'", 'Back to List', 'cancelBut');
180
        }
181
        $fields['cancelButton'] = $button->render();
182
183
        // buffer security fields to $formSecurityFields variable
184
        $fields['formSecurityFields'] = self::renderSecurityFields();
185
186
        // ID will need to be posted for optimistic lock checking
187
        $fields['version_num'] = $this->record->getVersionNumber();
188
189
        self::$logger->debug('<<editView [HTML]');
190
191
        return View::loadTemplate($this->record, 'edit', $fields);
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function listView($fields = array())
198
    {
199
        self::$logger->debug('>>listView(fields=['.var_export($fields, true).'])');
200
201
        $config = ConfigProvider::getInstance();
202
        $sessionProvider = $config->get('session.provider.name');
203
        $session = ServiceFactory::getInstance($sessionProvider, 'Alpha\Util\Http\Session\SessionProviderInterface');
204
205
        // work out how many columns will be in the table
206
        $reflection = new ReflectionClass(get_class($this->record));
207
        $properties = array_keys($reflection->getDefaultProperties());
208
        $fields['colCount'] = 1+count(array_diff($properties, $this->record->getDefaultAttributes(), $this->record->getTransientAttributes()));
209
210
        // get the class attributes
211
        $properties = $reflection->getProperties();
212
213
        $html = '';
214
215
        $html .= '<tr>';
216
        foreach ($properties as $propObj) {
217
            $propName = $propObj->name;
218
219
            // skip over password fields
220
            $property = $this->record->getPropObject($propName);
221
            if (!($property instanceof SmallText && $property->checkIsPassword())) {
222
                if (!in_array($propName, $this->record->getDefaultAttributes()) && !in_array($propName, $this->record->getTransientAttributes())) {
223
                    $html .= '  <th>'.$this->record->getDataLabel($propName).'</th>';
224
                }
225
                if ($propName == 'ID') {
226
                    $html .= '  <th>'.$this->record->getDataLabel($propName).'</th>';
227
                }
228
            } else {
229
                $fields['colCount'] = $fields['colCount']-1;
230
            }
231
        }
232
        $html .= '</tr><tr>';
233
234
        $fields['formHeadings'] = $html;
235
236
        $html = '';
237
238
        // and now the values
239
        foreach ($properties as $propObj) {
240
            $propName = $propObj->name;
241
242
            $property = $this->record->getPropObject($propName);
243
            if (!($property instanceof SmallText && $property->checkIsPassword())) {
244
                if (!in_array($propName, $this->record->getDefaultAttributes()) && !in_array($propName, $this->record->getTransientAttributes())) {
245
                    if ($property instanceof Text) {
246
                        $text = htmlentities($this->record->get($propName), ENT_COMPAT, 'utf-8');
247
                        if (mb_strlen($text) > 70) {
248
                            $html .= '  <td>&nbsp;'.mb_substr($text, 0, 70).'...</td>';
249
                        } else {
250
                            $html .= '  <td>&nbsp;'.$text.'</td>';
251
                        }
252
                    } elseif ($property instanceof DEnum) {
253
                        $html .= '  <td>&nbsp;'.$property->getDisplayValue().'</td>';
254
                    } else {
255
                        $html .= '  <td>&nbsp;'.$property->getValue().'</td>';
256
                    }
257
                }
258
                if ($propName == 'ID') {
259
                    $html .= '  <td>&nbsp;'.$this->record->getID().'</td>';
260
                }
261
            }
262
        }
263
        $html .= '</tr>';
264
265
        $fields['formFields'] = $html;
266
267
        $request = new Request(array('method' => 'GET'));
268
269
        // View button
270
        if (mb_strpos($request->getURI(), '/tk/') !== false) {
271
            if (isset($fields['viewButtonURL'])) {
272
                $button = new Button("document.location = '".$fields['viewButtonURL']."';", 'View', 'view'.$this->record->getID().'But');
273
            } else {
274
                $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.get_class($this->record).'&ActiveRecordID='.$this->record->getID())."';", 'View', 'view'.$this->record->getID().'But');
275
            }
276
            $fields['viewButton'] = $button->render();
277
        } else {
278
            if ($this->record->hasAttribute('URL')) {
279
                $button = new Button("document.location = '".$this->record->get('URL')."';", 'View', 'view'.$this->record->getID().'But');
280
            } else {
281
                $button = new Button("document.location = '".$config->get('app.url').'/record/'.urlencode(get_class($this->record)).'/'.$this->record->getID()."';", 'View', 'view'.$this->record->getID().'But');
282
            }
283
284
            $fields['viewButton'] = $button->render();
285
        }
286
287
        $html = '';
288
        // render edit and delete buttons for admins only
289
        if ($session->get('currentUser') && $session->get('currentUser')->inGroup('Admin')) {
290
            $html .= '&nbsp;&nbsp;';
291
            if (isset($fields['editButtonURL'])) {
292
                $button = new Button("document.location = '".$fields['editButtonURL']."'", 'Edit', 'edit'.$this->record->getID().'But');
293
            } else {
294
                $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.get_class($this->record).'&ActiveRecordID='.$this->record->getID().'&view=edit')."'", 'Edit', 'edit'.$this->record->getID().'But');
295
            }
296
297
            $html .= $button->render();
298
            $html .= '&nbsp;&nbsp;';
299
300
            $formFieldId = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('ActiveRecordID')) : 'ActiveRecordID');
301
            
302
            $js = View::loadTemplateFragment('html', 'bootstrapconfirmokay.phtml', array('prompt' => 'Are you sure you wish to delete this item?', 'formFieldId' => $formFieldId, 'formFieldValue' => $this->record->getID(), 'formId' => 'deleteForm'));
303
304
            $button = new Button($js, 'Delete', 'delete'.$this->record->getID().'But');
305
            $html .= $button->render();
306
        }
307
        $fields['adminButtons'] = $html;
308
309
        // buffer security fields to $formSecurityFields variable
310
        $fields['formSecurityFields'] = self::renderSecurityFields();
311
312
        self::$logger->debug('<<listView [HTML]');
313
314
        return View::loadTemplate($this->record, 'list', $fields);
315
    }
316
317
    /**
318
     * {@inheritdoc}
319
     */
320
    public function detailedView($fields = array())
321
    {
322
        self::$logger->debug('>>detailedView(fields=['.var_export($fields, true).'])');
323
324
        $config = ConfigProvider::getInstance();
325
326
        $sessionProvider = $config->get('session.provider.name');
327
        $session = ServiceFactory::getInstance($sessionProvider, 'Alpha\Util\Http\Session\SessionProviderInterface');
328
329
        // we may want to display the ID regardless of class
330
        $fields['IDLabel'] = $this->record->getDataLabel('ID');
331
        $fields['ID'] = $this->record->getID();
332
333
        // buffer form fields to $formFields
334
        $fields['formFields'] = $this->renderAllFields('view');
335
336
        // Back button
337
        $button = new Button('history.back()', 'Back', 'backBut');
338
        $fields['backButton'] = $button->render();
339
340
        $html = '';
341
        // render edit and delete buttons for admins only
342
        if ($session->get('currentUser') !== false && $session->get('currentUser')->inGroup('Admin')) {
343
            if (isset($fields['editButtonURL'])) {
344
                $button = new Button("document.location = '".$fields['editButtonURL']."'", 'Edit', 'editBut');
345
            } else {
346
                $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.get_class($this->record).'&ActiveRecordID='.$this->record->getID().'&view=edit')."'", 'Edit', 'editBut');
347
            }
348
            $html .= $button->render();
349
350
            $formFieldId = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('ActiveRecordID')) : 'ActiveRecordID');
351
            
352
            $js = View::loadTemplateFragment('html', 'bootstrapconfirmokay.phtml', array('prompt' => 'Are you sure you wish to delete this item?', 'formFieldId' => $formFieldId, 'formFieldValue' => $this->record->getID(), 'formId' => 'deleteForm'));
353
354
            $button = new Button($js, 'Delete', 'deleteBut');
355
            $html .= $button->render();
356
        }
357
        $fields['adminButtons'] = $html;
358
359
        self::$logger->debug('<<detailedView [HTML]');
360
361
        return View::loadTemplate($this->record, 'detail', $fields);
362
    }
363
364
    /**
365
     * {@inheritdoc}
366
     */
367
    public function adminView($fields = array())
368
    {
369
        self::$logger->debug('>>adminView(fields=['.var_export($fields, true).'])');
370
371
        $config = ConfigProvider::getInstance();
372
373
        // the class name of the record
374
        $fields['fullClassName'] = stripslashes(get_class($this->record));
375
376
        // the table name in the DB for the record
377
        $fields['tableName'] = $this->record->getTableName();
378
379
        // record count for the Record in the DB
380
        $fields['count'] = ($this->record->checkTableExists() ? $this->record->getCount() : '<span class="warning">unavailable</span>');
381
382
        // table exists in the DB?
383
        $fields['tableExists'] = ($this->record->checkTableExists() ? '<span class="success">Yes</span>' : '<span class="warning">No</span>');
384
385
        if ($this->record->getMaintainHistory()) {
386
            $fields['tableExists'] = ($this->record->checkTableExists(true) ? '<span class="success">Yes</span>' : '<span class="warning">No history table</span>');
387
        }
388
389
        // table schema needs to be updated in the DB?
390
        $fields['tableNeedsUpdate'] = ($this->record->checkTableNeedsUpdate() ? '<span class="warning">Yes</span>' : '<span class="success">No</span>');
391
392
        // create button
393
        if ($this->record->checkTableExists()) {
394
            if (isset($fields['createButtonURL'])) {
395
                $button = new Button("document.location = '".$fields['createButtonURL']."'", 'Create New', 'create'.stripslashes(get_class($this->record)).'But');
396
            } else {
397
                $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\\Controller\\ActiveRecordController&ActiveRecordType='.get_class($this->record))."'", 'Create New', 'create'.stripslashes(get_class($this->record)).'But');
398
            }
399
            $fields['createButton'] = $button->render();
400
        } else {
401
            $fields['createButton'] = '';
402
        }
403
404
        // list all button
405
        if ($this->record->checkTableExists()) {
406
            $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\\Controller\\ActiveRecordController&ActiveRecordType='.get_class($this->record).'&start=0&limit='.$config->get('app.list.page.amount'))."'", 'List All', 'list'.stripslashes(get_class($this->record)).'But');
407
            $fields['listButton'] = $button->render();
408
        } else {
409
            $fields['listButton'] = '';
410
        }
411
412
        // the create table button (if required)
413
        $html = '';
414
415
        if (!$this->record->checkTableExists()) {
416
            $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('createTableBut')) : 'createTableBut');
417
            $button = new Button('submit', 'Create Table', $fieldname);
418
            $html .= $button->render();
419
            // hidden field so that we know which class to create the table for
420
            $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('createTableClass')) : 'createTableClass');
421
            $html .= '<input type="hidden" name="'.$fieldname.'" value="'.get_class($this->record).'"/>';
422
        }
423
424
        if ($html == '' && $this->record->getMaintainHistory() && !$this->record->checkTableExists(true)) {
425
            $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('createHistoryTableBut')) : 'createHistoryTableBut');
426
            $button = new Button('submit', 'Create History Table', $fieldname);
427
            $html .= $button->render();
428
            // hidden field so that we know which class to create the table for
429
            $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('createTableClass')) : 'createTableClass');
430
            $html .= '<input type="hidden" name="'.$fieldname.'" value="'.get_class($this->record).'"/>';
431
        }
432
        $fields['createTableButton'] = $html;
433
434
        // recreate and update table buttons (if required)
435
        $html = '';
436
        if ($this->record->checkTableNeedsUpdate() && $this->record->checkTableExists()) {
437
            $formFieldId = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('admin_'.stripslashes(get_class($this->record)).'_button_pressed')) : 'admin_'.stripslashes(get_class($this->record)).'_button_pressed');
438
            
439
            $js = View::loadTemplateFragment('html', 'bootstrapconfirmokay.phtml', array('prompt' => 'Are you sure you wish to recreate this class table (all data will be lost)?', 'formFieldId' => $formFieldId, 'formFieldValue' => 'recreateTableBut', 'formId' => 'admin_'.stripslashes(get_class($this->record))));
440
441
            $button = new Button($js, 'Recreate Table', 'recreateTableBut');
442
            $html .= $button->render();
443
            // hidden field so that we know which class to recreate the table for
444
            $html .= '<input type="hidden" name="recreateTableClass" value="'.get_class($this->record).'"/>';
445
            $html .= '&nbsp;&nbsp;';
446
447
            $formFieldId = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('admin_'.stripslashes(get_class($this->record)).'_button_pressed')) : 'admin_'.stripslashes(get_class($this->record)).'_button_pressed');
448
            
449
            $js = View::loadTemplateFragment('html', 'bootstrapconfirmokay.phtml', array('prompt' => 'Are you sure you wish to attempt to modify this class table by adding new attributes?', 'formFieldId' => $formFieldId, 'formFieldValue' => 'recreateTableBut', 'formId' => 'admin_'.stripslashes(get_class($this->record))));
450
451
            $button = new Button($js, 'Update Table', 'updateTableBut');
452
            $html .= $button->render();
453
            // hidden field so that we know which class to update the table for
454
            $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('updateTableClass')) : 'updateTableClass');
455
            $html .= '<input type="hidden" name="'.$fieldname.'" value="'.get_class($this->record).'"/>';
456
            // hidden field to tell us which button was pressed
457
            $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('admin_'.stripslashes(get_class($this->record)).'_button_pressed')) : 'admin_'.stripslashes(get_class($this->record)).'_button_pressed');
458
            $html .= '<input type="hidden" id="'.$fieldname.'" name="'.$fieldname.'" value=""/>';
459
        }
460
        $fields['recreateOrUpdateButtons'] = $html;
461
462
        // buffer security fields to $formSecurityFields variable
463
        $fields['formSecurityFields'] = self::renderSecurityFields();
464
465
        self::$logger->debug('<<adminView [HTML]');
466
467
        return View::loadTemplate($this->record, 'admin', $fields);
468
    }
469
470
    /**
471
     * {@inheritdoc}
472
     */
473
    public static function displayPageHead($controller)
474
    {
475
        if (self::$logger == null) {
476
            self::$logger = new Logger('RendererProviderHTML');
477
        }
478
479
        self::$logger->debug('>>displayPageHead(controller=['.var_export($controller, true).'])');
480
481
        $config = ConfigProvider::getInstance();
482
        $sessionProvider = $config->get('session.provider.name');
483
        $session = ServiceFactory::getInstance($sessionProvider, 'Alpha\Util\Http\Session\SessionProviderInterface');
484
485
        if (!class_exists(get_class($controller))) {
486
            throw new IllegalArguementException('The controller provided ['.get_class($controller).'] is not defined anywhere!');
487
        }
488
489
        $allowCSSOverrides = true;
490
491
        $request = new Request(array('method' => 'GET'));
492
493
        if ($session->get('currentUser') != null && ActiveRecord::isInstalled() && $session->get('currentUser')->inGroup('Admin') && mb_strpos($request->getURI(), '/tk/') !== false) {
494
            $allowCSSOverrides = false;
495
        }
496
497
        $duringCallbackOutput = '';
498
        if (method_exists($controller, 'during_displayPageHead_callback')) {
499
            $duringCallbackOutput = $controller->{'during_displayPageHead_callback'}();
500
        }
501
502
        $onloadEvent = '';
503
        if ($controller->getRecord() != null && $controller->getRecord()->hasAttribute('bodyOnload')) {
504
            $onloadEvent = $controller->getRecord()->get('bodyOnload');
505
        }
506
507
        $cmsCallbackOutput = '';
508
        if (method_exists($controller, 'insert_CMSDisplayStandardHeader_callback')) {
509
            $cmsCallbackOutput = $controller->{'insert_CMSDisplayStandardHeader_callback'}();
510
        }
511
512
        $html = View::loadTemplateFragment('html', 'head.phtml', array('title' => $controller->getTitle(), 'description' => $controller->getDescription(), 'allowCSSOverrides' => $allowCSSOverrides, 'duringCallbackOutput' => $duringCallbackOutput, 'cmsCallbackOutput' => $cmsCallbackOutput, 'onloadEvent' => $onloadEvent));
513
514
        self::$logger->debug('<<displayPageHead [HTML]');
515
516
        return $html;
517
    }
518
519
    /**
520
     * {@inheritdoc}
521
     */
522
    public static function displayPageFoot($controller)
523
    {
524
        if (self::$logger == null) {
525
            self::$logger = new Logger('RendererProviderHTML');
526
        }
527
528
        self::$logger->debug('>>displayPageFoot(controller=['.get_class($controller).'])');
529
530
        $html = View::loadTemplateFragment('html', 'footer.phtml', array());
531
532
        self::$logger->debug('<<displayPageFoot ['.$html.']');
533
534
        return $html;
535
    }
536
537
    /**
538
     * {@inheritdoc}
539
     */
540
    public static function displayUpdateMessage($message)
541
    {
542
        if (self::$logger == null) {
543
            self::$logger = new Logger('RendererProviderHTML');
544
        }
545
        self::$logger->debug('>>displayUpdateMessage(message=['.$message.'])');
546
547
        $html = '<div class="alert alert-success alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>'.$message.'</div>';
548
549
        self::$logger->debug('<<displayUpdateMessage ['.$html.']');
550
551
        return $html;
552
    }
553
554
    /**
555
     * {@inheritdoc}
556
     */
557
    public static function displayErrorMessage($message)
558
    {
559
        if (self::$logger == null) {
560
            self::$logger = new Logger('RendererProviderHTML');
561
        }
562
        self::$logger->debug('>>displayErrorMessage(message=['.$message.'])');
563
564
        $html = '<div class="alert alert-danger">'.$message.'</div>';
565
566
        self::$logger->debug('<<displayErrorMessage ['.$html.']');
567
568
        return $html;
569
    }
570
571
    /**
572
     * {@inheritdoc}
573
     */
574
    public static function renderErrorPage($code, $message)
575
    {
576
        $config = ConfigProvider::getInstance();
577
578
        $html = View::loadTemplateFragment('html', 'head.phtml', array('title' => $code.' - '.$message, 'description' => $message, 'allowCSSOverrides' => false));
579
        $html .= '</head>';
580
        $html .= '<body>';
581
        $html .= '<div class="container">';
582
        $html .= self::displayErrorMessage('<strong>'.$code.':</strong> '.$message);
583
        $html .= '<div align="center"><a href="'.$config->get('app.url').'">Home Page</a></div>';
584
        $html .= '</div></body></html>';
585
586
        return $html;
587
    }
588
589
    /**
590
     * {@inheritdoc}
591
     */
592
    public static function renderDeleteForm($URI)
593
    {
594
        if (self::$logger == null) {
595
            self::$logger = new Logger('RendererProviderHTML');
596
        }
597
        self::$logger->debug('>>renderDeleteForm()');
598
599
        $config = ConfigProvider::getInstance();
600
601
        $html = '<form action="'.$URI.'" method="POST" id="deleteForm" accept-charset="UTF-8">';
602
        $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('ActiveRecordID')) : 'ActiveRecordID');
603
        $html .= '<input type="hidden" name="'.$fieldname.'" id="'.$fieldname.'" value=""/>';
604
        $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('_METHOD')) : '_METHOD');
605
        $html .= '<input type="hidden" name="'.$fieldname.'" id="'.$fieldname.'" value="DELETE"/>';
606
        $html .= self::renderSecurityFields();
607
        $html .= '</form>';
608
609
        self::$logger->debug('<<renderDeleteForm ['.$html.']');
610
611
        return $html;
612
    }
613
614
    /**
615
     * {@inheritdoc}
616
     */
617
    public static function renderSecurityFields()
618
    {
619
        if (self::$logger == null) {
620
            self::$logger = new Logger('RendererProviderHTML');
621
        }
622
623
        self::$logger->debug('>>renderSecurityFields()');
624
625
        $config = ConfigProvider::getInstance();
626
627
        $html = '';
628
629
        $fields = Controller::generateSecurityFields();
630
631
        if ($config->get('security.encrypt.http.fieldnames')) {
632
            $fieldname = base64_encode(SecurityUtils::encrypt('var1'));
633
        } else {
634
            $fieldname = 'var1';
635
        }
636
637
        $html .= '<input type="hidden" name="'.$fieldname.'" value="'.$fields[0].'"/>';
638
639
        if ($config->get('security.encrypt.http.fieldnames')) {
640
            $fieldname = base64_encode(SecurityUtils::encrypt('var2'));
641
        } else {
642
            $fieldname = 'var2';
643
        }
644
645
        $html .= '<input type="hidden" name="'.$fieldname.'" value="'.$fields[1].'"/>';
646
647
        self::$logger->debug('<<renderSecurityFields ['.$html.']');
648
649
        return $html;
650
    }
651
652
    /**
653
     * {@inheritdoc}
654
     */
655
    public function renderIntegerField($name, $label, $mode, $value = '')
656
    {
657
        self::$logger->debug('>>renderIntegerField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
658
659
        $config = ConfigProvider::getInstance();
660
661
        if ($config->get('security.encrypt.http.fieldnames')) {
662
            $fieldname = base64_encode(SecurityUtils::encrypt($name));
663
        } else {
664
            $fieldname = $name;
665
        }
666
667
        $html = '<div class="form-group">';
668
        $html .= '  <label for="'.$fieldname.'">'.$label.'</label>';
669
670
        $request = new Request(array('method' => 'GET'));
671
672
        if ($mode == 'create') {
673
            $html .= '<input type="text" style="width:100%;" name="'.$fieldname.'" value="'.$request->getParam($name, '').'"/>';
674
        }
675
676
        if ($mode == 'edit') {
677
            $html .= '<input type="text" style="width:100%;" name="'.$fieldname.'" value="'.$value.'"/>';
678
        }
679
680
        $html .= '</div>';
681
682
        self::$logger->debug('<<renderIntegerField ['.$html.']');
683
684
        return $html;
685
    }
686
687
    /**
688
     * {@inheritdoc}
689
     */
690
    public function renderDoubleField($name, $label, $mode, $value = '')
691
    {
692
        self::$logger->debug('>>renderDoubleField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
693
694
        $config = ConfigProvider::getInstance();
695
696
        if ($config->get('security.encrypt.http.fieldnames')) {
697
            $fieldname = base64_encode(SecurityUtils::encrypt($name));
698
        } else {
699
            $fieldname = $name;
700
        }
701
702
        $html = '<div class="form-group">';
703
        $html .= '  <label for="'.$fieldname.'">'.$label.'</label>';
704
705
        $request = new Request(array('method' => 'GET'));
706
707
        if ($mode == 'create') {
708
            $html .= '<input type="text" size="13" name="'.$fieldname.'" value="'.$request->getParam($name, '').'"/>';
709
        }
710
711
        if ($mode == 'edit') {
712
            $html .= '<input type="text" size="13" name="'.$fieldname.'" value="'.$value.'"/>';
713
        }
714
715
        $html .= '</div>';
716
717
        self::$logger->debug('<<renderDoubleField ['.$html.']');
718
719
        return $html;
720
    }
721
722
    /**
723
     * {@inheritdoc}
724
     */
725
    public function renderBooleanField($name, $label, $mode, $value = '')
726
    {
727
        self::$logger->debug('>>renderBooleanField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
728
729
        $config = ConfigProvider::getInstance();
730
731
        if ($config->get('security.encrypt.http.fieldnames')) {
732
            $fieldname = base64_encode(SecurityUtils::encrypt($name));
733
        } else {
734
            $fieldname = $name;
735
        }
736
737
        $html = '<div class="checkbox">';
738
        $html .= '  <label>';
739
740
        if ($mode == 'create') {
741
            $html .= '      <input type="hidden" name="'.$fieldname.'" value="0">';
742
            $html .= '      <input type="checkbox" name="'.$fieldname.'" id="'.$fieldname.'">';
743
            $html .= '          '.$label;
744
        }
745
746
        if ($mode == 'edit') {
747
            $html .= '      <input type="hidden" name="'.$fieldname.'" value="0">';
748
            $html .= '      <input type="checkbox" name="'.$fieldname.'" id="'.$fieldname.'"'.($value == '1' ? ' checked' : '').' />';
749
            $html .= '          '.$label;
750
        }
751
752
        $html .= '  </label>';
753
        $html .= '</div>';
754
755
        self::$logger->debug('<<renderBooleanField ['.$html.']');
756
757
        return $html;
758
    }
759
760
    /**
761
     * {@inheritdoc}
762
     */
763
    public function renderEnumField($name, $label, $mode, $options, $value = '')
764
    {
765
        self::$logger->debug('>>renderEnumField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
766
767
        $config = ConfigProvider::getInstance();
768
769
        if ($config->get('security.encrypt.http.fieldnames')) {
770
            $fieldname = base64_encode(SecurityUtils::encrypt($name));
771
        } else {
772
            $fieldname = $name;
773
        }
774
775
        $html = '<div class="form-group">';
776
        $html .= '  <label for="'.$fieldname.'">'.$label.'</label>';
777
778
        if ($mode == 'create') {
779
            $html .= '  <select name="'.$fieldname.'" id="'.$fieldname.'" class="form-control"/>';
780
            foreach ($options as $val) {
781
                $html .= '      <option value="'.$val.'">'.$val.'</option>';
782
            }
783
            $html .= '  </select>';
784
        }
785
786
        if ($mode == 'edit') {
787
            $html .= '  <select name="'.$fieldname.'" id="'.$fieldname.'" class="form-control"/>';
788
            foreach ($options as $val) {
789
                if ($value == $val) {
790
                    $html .= '      <option value="'.$val.'" selected>'.$val.'</option>';
791
                } else {
792
                    $html .= '      <option value="'.$val.'">'.$val.'</option>';
793
                }
794
            }
795
            $html .= '  </select>';
796
        }
797
798
        $html .= '</div>';
799
800
        self::$logger->debug('<<renderEnumField ['.$html.']');
801
802
        return $html;
803
    }
804
805
    /**
806
     * {@inheritdoc}
807
     */
808
    public function renderDEnumField($name, $label, $mode, $options, $value = '')
809
    {
810
        self::$logger->debug('>>renderDEnumField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
811
812
        $config = ConfigProvider::getInstance();
813
814
        if ($config->get('security.encrypt.http.fieldnames')) {
815
            $fieldname = base64_encode(SecurityUtils::encrypt($name));
816
        } else {
817
            $fieldname = $name;
818
        }
819
820
        $html = '<div class="form-group">';
821
        $html .= '  <label for="'.$fieldname.'">'.$label.'</label>';
822
823
        if ($mode == 'create') {
824
            $html .= '  <select name="'.$fieldname.'" id="'.$fieldname.'" class="form-control"/>';
825
            foreach (array_keys($options) as $index) {
826
                $html .= '<option value="'.$index.'">'.$options[$index].'</option>';
827
            }
828
            $html .= '  </select>';
829
        }
830
831
        if ($mode == 'edit') {
832
            $html .= '  <select name="'.$fieldname.'" id="'.$fieldname.'" class="form-control"/>';
833
            foreach (array_keys($options) as $index) {
834
                if ($value == $index) {
835
                    $html .= '<option value="'.$index.'" selected>'.$options[$index].'</option>';
836
                } else {
837
                    $html .= '<option value="'.$index.'">'.$options[$index].'</option>';
838
                }
839
            }
840
            $html .= '  </select>';
841
        }
842
843
        $html .= '</div>';
844
845
        self::$logger->debug('<<renderDEnumField ['.$html.']');
846
847
        return $html;
848
    }
849
850
    /**
851
     * {@inheritdoc}
852
     */
853
    public function renderDefaultField($name, $label, $mode, $value = '')
854
    {
855
        self::$logger->debug('>>renderDefaultField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
856
857
        $config = ConfigProvider::getInstance();
858
859
        if ($config->get('security.encrypt.http.fieldnames')) {
860
            $fieldname = base64_encode(SecurityUtils::encrypt($name));
861
        } else {
862
            $fieldname = $name;
863
        }
864
865
        $html = '';
866
867
        $request = new Request(array('method' => 'GET'));
868
869
        if ($mode == 'create') {
870
            $html .= '<textarea cols="100" rows="3" name="'.$fieldname.'">'.$request->getParam($name, '').'</textarea>';
871
        }
872
873
        if ($mode == 'edit') {
874
            $html .= '<textarea cols="100" rows="3" name="'.$fieldname.'">'.$value.'</textarea>';
875
        }
876
877
        if ($mode == 'view') {
878
            $html .= '<p><strong>'.$label.':</strong> '.$value.'</p>';
879
        }
880
881
        self::$logger->debug('<<renderDefaultField ['.$html.']');
882
883
        return $html;
884
    }
885
886
    /**
887
     * {@inheritdoc}
888
     */
889
    public function renderTextField($name, $label, $mode, $value = '')
890
    {
891
        self::$logger->debug('>>renderTextField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
892
893
        $html = '';
894
895
        if ($mode == 'create') {
896
            // give 10 rows for content fields (other 5 by default)
897
            if ($name == 'content') {
898
                $text = new TextBox($this->record->getPropObject($name), $label, $name, 10);
0 ignored issues
show
Documentation introduced by
$this->record->getPropObject($name) is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Text>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
899
            } else {
900
                $text = new TextBox($this->record->getPropObject($name), $label, $name);
0 ignored issues
show
Documentation introduced by
$this->record->getPropObject($name) is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Text>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
901
            }
902
            $html .= $text->render();
903
        }
904
905
        if ($mode == 'edit') {
906
            // give 10 rows for content fields (other 5 by default)
907
            if ($name == 'content') {
908
                $viewState = ViewState::getInstance();
909
910
                if ($viewState->get('markdownTextBoxRows') == '') {
911
                    $text = new TextBox($this->record->getPropObject($name), $label, $name, 10);
0 ignored issues
show
Documentation introduced by
$this->record->getPropObject($name) is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Text>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
912
                } else {
913
                    $text = new TextBox($this->record->getPropObject($name), $label, $name, (integer)$viewState->get('markdownTextBoxRows'));
0 ignored issues
show
Documentation introduced by
$this->record->getPropObject($name) is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Text>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
914
                }
915
916
                $html .= $text->render();
917
            } else {
918
                $text = new TextBox($this->record->getPropObject($name), $label, $name);
0 ignored issues
show
Documentation introduced by
$this->record->getPropObject($name) is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Text>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
919
                $html .= $text->render();
920
            }
921
        }
922
923
        if ($mode == 'view') {
924
            $html .= '<p><strong>';
925
926
            $html .= $label;
927
928
            $html .= ':</strong>';
929
930
            // filter ouput to prevent malicious injection
931
            $value = InputFilter::encode($value);
932
933
            // ensures that line returns are rendered
934
            $value = str_replace("\n", '<br>', $value);
935
936
            $html .= '&nbsp;';
937
938
            $html .= $value;
939
940
            $html .= '</p>';
941
        }
942
943
        self::$logger->debug('<<renderTextField ['.$html.']');
944
945
        return $html;
946
    }
947
948
    /**
949
     * {@inheritdoc}
950
     */
951
    public function renderStringField($name, $label, $mode, $value = '')
952
    {
953
        self::$logger->debug('>>renderStringField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'])');
954
955
        $html = '';
956
957
        if ($mode == 'create' || $mode == 'edit') {
958
            $string = new SmallTextBox($this->record->getPropObject($name), $label, $name);
0 ignored issues
show
Documentation introduced by
$this->record->getPropObject($name) is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\SmallText>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
959
            $html .= $string->render();
960
        }
961
962
        if ($mode == 'view') {
963
            $html .= '<p><strong>'.$label.':</strong> '.$value.'</p>';
964
        }
965
966
        self::$logger->debug('<<renderStringField ['.$html.']');
967
968
        return $html;
969
    }
970
971
    /**
972
     * {@inheritdoc}
973
     */
974
    public function renderRelationField($name, $label, $mode, $value = '', $expanded = false, $buttons = true)
975
    {
976
        self::$logger->debug('>>renderRelationField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], expanded=['.$expanded.'], buttons=['.$buttons.'])');
977
978
        $html = '';
979
980
        $rel = $this->record->getPropObject($name);
981
982
        if ($mode == 'create' || $mode == 'edit') {
983
            if ($rel->getRelationType() == 'MANY-TO-MANY') {
984
                try {
985
                    // check to see if the rel is on this class
986
                    $rel->getSide(get_class($this->record));
987
                    $widget = new RecordSelector($rel, $label, $name, get_class($this->record));
0 ignored issues
show
Documentation introduced by
$rel is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Relation>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
988
                    $html .= $widget->render($expanded, $buttons);
989
                } catch (IllegalArguementException $iae) {
990
                    // the rel may be on a parent class
991
                    $widget = new RecordSelector($rel, $label, $name, get_parent_class($this->record));
0 ignored issues
show
Documentation introduced by
$rel is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Relation>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
992
                    $html .= $widget->render($expanded, $buttons);
993
                }
994
            } else {
995
                $rel = new RecordSelector($rel, $label, $name);
0 ignored issues
show
Documentation introduced by
$rel is of type object<Alpha\Model\Type\Type>|boolean, but the function expects a object<Alpha\Model\Type\Relation>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
996
                $html .= $rel->render($expanded, $buttons);
997
            }
998
        }
999
1000
        if ($mode == 'view') {
1001
            if ($rel->getRelationType() == 'MANY-TO-ONE') {
1002
                $html .= $this->renderDefaultField($name, $label, 'view', $rel->getRelatedClassDisplayFieldValue());
1003
            } elseif ($rel->getRelationType() == 'MANY-TO-MANY') {
1004
                try {
1005
                    // check to see if the rel is on this class
1006
                    $rel->getSide(get_class($this->record));
1007
                    $html .= $this->renderDefaultField($name, $label, 'view', $rel->getRelatedClassDisplayFieldValue(get_class($this->record)));
1008
                } catch (IllegalArguementException $iae) {
1009
                    // the rel may be on a parent class
1010
                    $html .= $this->renderDefaultField($name, $label, 'view', $rel->getRelatedClassDisplayFieldValue(get_parent_class($this->record)));
1011
                }
1012
            } else {
1013
                $rel = new RecordSelector($rel, $label, $name);
0 ignored issues
show
Documentation introduced by
$rel is of type object<Alpha\Model\Type\...\Widget\RecordSelector>, but the function expects a object<Alpha\Model\Type\Relation>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1014
                $html .= $rel->render($expanded, $buttons);
1015
            }
1016
        }
1017
1018
        self::$logger->debug('<<renderRelationField ['.$html.']');
1019
1020
        return $html;
1021
    }
1022
1023
    /**
1024
     * {@inheritdoc}
1025
     */
1026
    public function renderAllFields($mode, $filterFields = array(), $readOnlyFields = array())
1027
    {
1028
        self::$logger->debug('>>renderAllFields(mode=['.$mode.'], filterFields=['.var_export($filterFields, true).'], readOnlyFields=['.var_export($readOnlyFields, true).'])');
1029
1030
        $html = '';
1031
1032
        // get the class attributes
1033
        $properties = array_keys($this->record->getDataLabels());
1034
1035
        $orignalMode = $mode;
1036
1037
        foreach ($properties as $propName) {
1038
            if (!in_array($propName, $this->record->getDefaultAttributes()) && !in_array($propName, $filterFields)) {
1039
                // render readonly fields in the supplied array
1040
                if (in_array($propName, $readOnlyFields)) {
1041
                    $mode = 'view';
1042
                } else {
1043
                    $mode = $orignalMode;
1044
                }
1045
1046
                if (!is_object($this->record->getPropObject($propName))) {
1047
                    continue;
1048
                }
1049
1050
                $reflection = new ReflectionClass($this->record->getPropObject($propName));
1051
                $propClass = $reflection->getShortName();
1052
1053
                // exclude non-Relation transient attributes from create and edit screens
1054
                if ($propClass != 'Relation' && ($mode == 'edit' || $mode == 'create') && in_array($propName, $this->record->getTransientAttributes())) {
1055
                    continue;
1056
                }
1057
1058
                switch (mb_strtoupper($propClass)) {
1059
                    case 'INTEGER':
1060
                        if ($mode == 'view') {
1061
                            $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), 'view', $this->record->get($propName));
1062
                        } else {
1063
                            $html .= $this->renderIntegerField($propName, $this->record->getDataLabel($propName), $mode, $this->record->get($propName));
1064
                        }
1065
                    break;
1066
                    case 'DOUBLE':
1067
                        if ($mode == 'view') {
1068
                            $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), 'view', $this->record->get($propName));
1069
                        } else {
1070
                            $html .= $this->renderDoubleField($propName, $this->record->getDataLabel($propName), $mode, $this->record->get($propName));
1071
                        }
1072
                    break;
1073
                    case 'DATE':
1074
                        if ($mode == 'view') {
1075
                            $value = $this->record->get($propName);
1076
                            if ($value == '0000-00-00') {
1077
                                $value = '';
1078
                            }
1079
                            $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), 'view', $value);
1080
                        } else {
1081
                            $date = new DateBox($this->record->getPropObject($propName), $this->record->getDataLabel($propName), $propName);
1082
                            $html .= $date->render();
1083
                        }
1084
                    break;
1085
                    case 'TIMESTAMP':
1086
                        if ($mode == 'view') {
1087
                            $value = $this->record->get($propName);
1088
                            if ($value == '0000-00-00 00:00:00') {
1089
                                $value = '';
1090
                            }
1091
                            $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), 'view', $value);
1092
                        } else {
1093
                            $timestamp = new DateBox($this->record->getPropObject($propName), $this->record->getDataLabel($propName), $propName);
1094
                            $html .= $timestamp->render();
1095
                        }
1096
                    break;
1097
                    case 'SMALLTEXT':
1098
                        $html .= $this->renderStringField($propName, $this->record->getDataLabel($propName), $mode, $this->record->get($propName));
1099
                    break;
1100
                    case 'TEXT':
1101
                        $html .= $this->renderTextField($propName, $this->record->getDataLabel($propName), $mode, $this->record->get($propName));
1102
                    break;
1103
                    case 'BOOLEAN':
1104
                        if ($mode == 'view') {
1105
                            $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), 'view', $this->record->get($propName));
1106
                        } else {
1107
                            $html .= $this->renderBooleanField($propName, $this->record->getDataLabel($propName), $mode, $this->record->get($propName));
1108
                        }
1109
                    break;
1110
                    case 'ENUM':
1111
                        if ($mode == 'view') {
1112
                            $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), 'view', $this->record->get($propName));
1113
                        } else {
1114
                            $enum = $this->record->getPropObject($propName);
1115
                            $html .= $this->renderEnumField($propName, $this->record->getDataLabel($propName), $mode, $enum->getOptions(), $this->record->get($propName));
1116
                        }
1117
                    break;
1118
                    case 'DENUM':
1119
                        if ($mode == 'view') {
1120
                            $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), 'view', $this->record->getPropObject($propName)->getDisplayValue());
1121
                        } else {
1122
                            $denum = $this->record->getPropObject($propName);
1123
                            $html .= $this->renderDEnumField($propName, $this->record->getDataLabel($propName), $mode, $denum->getOptions(), $this->record->get($propName));
1124
                        }
1125
                    break;
1126
                    case 'RELATION':
1127
                        $html .= $this->renderRelationField($propName, $this->record->getDataLabel($propName), $mode, $this->record->get($propName));
1128
                    break;
1129
                    default:
1130
                        $html .= $this->renderDefaultField($propName, $this->record->getDataLabel($propName), $mode, $this->record->get($propName));
1131
                    break;
1132
                }
1133
            }
1134
        }
1135
1136
        self::$logger->debug('<<renderAllFields ['.$html.']');
1137
1138
        return $html;
1139
    }
1140
}
1141