Passed
Branchfeature/useWidgetsNamespaces (54f503)
by Robin
04:17
created

AppCtrlRecord::search()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 28
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 20
c 1
b 1
f 0
dl 0
loc 28
rs 9.6
cc 4
nc 3
nop 1
1
<?php
2
3
// -------------------------------------------------------------------------
4
// OVIDENTIA http://www.ovidentia.org
5
// Ovidentia is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 2, or (at your option)
8
// any later version.
9
//
10
// This program is distributed in the hope that it will be useful, but
11
// WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
// See the GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18
// USA.
19
// -------------------------------------------------------------------------
20
/**
21
 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
22
 * @copyright Copyright (c) 2022 by SI4YOU ({@link https://www.siforyou.com})
23
 */
24
namespace Capwelton\LibApp\Ctrl;
25
26
use Capwelton\Widgets\Widgets\Abstracts\WidgetItem;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widgets\Abstracts\WidgetItem was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
use Capwelton\Widgets\Widgets\Layout\WidgetFlexLayout;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widgets\Layout\WidgetFlexLayout was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use Capwelton\Widgets\Widgets\Page\WidgetPage;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widgets\Page\WidgetPage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use Capwelton\Widgets\Widgets\Table\WidgetTableModelView;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widget...le\WidgetTableModelView was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
use Capwelton\LibApp\Ui\AppToolbar;
31
use Capwelton\Widgets\Widgets\Helpers\WidgetAction;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widgets\Helpers\WidgetAction was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use Capwelton\Widgets\Widgets\Item\WidgetLink;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widgets\Item\WidgetLink was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use Capwelton\LibApp\Exceptions\AppAccessException;
34
use Capwelton\LibApp\Ui\Page\AppPage;
35
use Capwelton\LibApp\Ui\AppRecordEditor;
36
use Capwelton\LibApp\Ui\AppTableModelView;
37
use Capwelton\LibApp\Ui\AppEditor;
38
use Capwelton\LibApp\Exceptions\AppSaveException;
39
use Capwelton\LibApp\Set\AppRecord;
40
use Capwelton\LibApp\Set\AppTraceableRecord;
41
use Capwelton\LibApp\Set\AppRecordSet;
42
use Capwelton\LibOrm\ORMRecord;
0 ignored issues
show
Bug introduced by
The type Capwelton\LibOrm\ORMRecord was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
43
use Capwelton\Widgets\Widgets\Form\WidgetSelect2Option;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widgets\Form\WidgetSelect2Option was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
44
use Capwelton\Widgets\Widgets\Form\WidgetSelect2OptionsCollection;
0 ignored issues
show
Bug introduced by
The type Capwelton\Widgets\Widget...elect2OptionsCollection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
45
46
/**
47
 * @method self proxy()
48
 */
49
abstract class AppCtrlRecord extends AppController
50
{
51
    
52
    /**
53
     * This methods returns the Record classname managed by this controller.
54
     * The default method guess the record classname based on the controller name.
55
     * It can be overriden by inherited controllers.
56
     *
57
     * @return string
58
     */
59
    protected function getRecordClassName()
60
    {
61
        $class = $this->getClass();
62
        if(strpos($class, 'Controller') !== false){
63
            $App = $this->App();
64
            $componentName = strtoupper(str_replace('Controller', '', $class));
65
            $component = $App->getComponentByName($componentName);
66
            if($component){
67
                list (, $recordClassname) = explode($App->classPrefix, $component->getRecordClassName());
68
                return $recordClassname;
69
            }
70
        }
71
        if(strpos($class, '_Ctrl')){
72
            list (, $recordClassname) = explode('_Ctrl', $class);
73
            return $recordClassname;
74
        }
75
        list (, $recordClassname) = explode('AppCtrl', $class);
76
        return $recordClassname;
77
    }
78
    
79
    /**
80
     * This methods returns the Record set managed by this controller.
81
     * The default method guess the record set based on the controller name.
82
     * It can be overriden by inherited controllers.
83
     *
84
     * @return AppRecordSet
85
     */
86
    protected function getRecordSet()
87
    {
88
        $App = $this->App();
89
        
90
        
91
        $recordClassname = $this->getRecordClassName();
92
        $recordSetClassname = $recordClassname . 'Set';
93
        
94
        $recordSet = $App->$recordSetClassname();
95
        return $recordSet;
96
    }
97
    
98
    /**
99
     * @return AppRecordSet
100
     */
101
    protected function getEditRecordSet()
102
    {
103
        return $this->getRecordSet();
104
    }
105
    
106
    /**
107
     * This methods returns the Record set used to save records
108
     *
109
     * @return AppRecordSet
110
     */
111
    protected function getSaveRecordSet()
112
    {
113
        return $this->getRecordSet();
114
    }
115
    
116
    /**
117
     * This methods returns the Record set used to delete records
118
     *
119
     * @return AppRecordSet
120
     */
121
    protected function getDeleteRecordSet()
122
    {
123
        return $this->getSaveRecordSet();
124
    }
125
    
126
    /**
127
     * @param WidgetAction|WidgetLink|WidgetAction[]|WidgetLink[]|array $actions
128
     * @param WidgetItem $box
129
     * @return string
130
     */
131
    protected function createMenu($actions, $icon = true, $showLabel = false)
132
    {
133
        $canvas = bab_Widgets()->HtmlCanvas();
134
        $html = '';
135
        if($actions instanceof WidgetAction){
136
            $text = '';
137
            if($showLabel){
138
                $text = $actions->getTitle();
139
            }
140
            $html = '<li><a class="icon ' . $actions->getIcon() . '" href="' . $actions->url() . '">' . $text . '</a></li>';
141
        }
142
        elseif($actions instanceof WidgetLink){
0 ignored issues
show
introduced by
$actions is never a sub-type of Capwelton\Widgets\Widgets\Item\WidgetLink.
Loading history...
143
            $html = '<li>' . $actions->display($canvas) . '</li>';
144
        }
145
        elseif(is_array($actions)){
0 ignored issues
show
introduced by
The condition is_array($actions) is always true.
Loading history...
146
            if(isset($actions['items'])){
147
                $items = $actions['items'];
148
            }
149
            else{
150
                $items = $actions;
151
            }
152
            foreach ($items as $action){
153
                $html .= $this->createMenu($action, true, true);
154
            }
155
            if(isset($actions['icon'])){
156
                
157
                $html = '<li class="dropdown">' . '<a href="#" class="' . $actions['icon'] . ' icon dropdown-toogle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">' . ($actions['icon'] === 'actions-context-menu'/*\Func_Icons::ACTIONS_CONTEXT_MENU*/ ? '' : '<span class="caret"></span>') . '</a>' . '<ul class="dropdown-menu dropdown-menu-right ' . \Func_Icons::ICON_LEFT_SYMBOLIC . '">' . $html . '</ul>';
158
            }
159
        }
160
        
161
        return $html;
162
    }
163
    
164
    /**
165
     * @return string[]
166
     */
167
    protected function getAvailableModelViewTypes()
168
    {
169
        $App = $this->App();
170
        $Ui = $App->Ui();
171
        
172
        $types = array();
173
        
174
        $recordClassname = $this->getRecordClassName();
175
        
176
        $methods = array();
177
        $methods['table'] = array(
178
            'method' => 'TableView',
179
            'icon' => \Func_Icons::ACTIONS_VIEW_LIST_TEXT,
180
            'label' => $App->translate('Detailed list')
181
        );
182
        $methods['cards'] = array(
183
            'method' => 'CardsView',
184
            'icon' => \Func_Icons::ACTIONS_VIEW_LIST_CARDS,
185
            'label' => $App->translate('Cards')
186
        );
187
        $methods['map'] = array(
188
            'method' => 'MapView',
189
            'icon' => \Func_Icons::APPS_PREFERENCES_SITE,
190
            'label' => $App->translate('Map')
191
        );
192
        $methods['kanban'] = array(
193
            'method' => 'KanbanView',
194
            'icon' => \Func_Icons::APPS_PORTLET,
195
            'label' => $App->translate('Kanban')
196
        );
197
        $methods['statistics'] = array(
198
            'method' => 'StatisticsView',
199
            'icon' => \Func_Icons::APPS_STATISTICS,
200
            'label' => $App->translate('Statistics')
201
        );
202
        
203
        foreach ($methods as $index => $method){
204
            try{
205
                $methodName = $recordClassname . $method['method'];
206
                if($Ui->$methodName()){
207
                    $types[$index] = array(
208
                        'classname' => $methodName,
209
                        'icon' => $method['icon'],
210
                        'label' => $method['label']
211
                    );
212
                }
213
            }
214
            catch (\Exception $e){
215
                unset($types[$index]);
216
                continue;
217
            }
218
        }
219
        
220
        return $types;
221
    }
222
    
223
    /**
224
     * Returns an array of field names and descriptions that can be used in Full/CardFrames.
225
     *
226
     * @return string[]
227
     */
228
    public function getAvailableDisplayFields()
229
    {
230
        $App = $this->App();
231
        $recordSet = $this->getRecordSet();
232
        
233
        $availableFields = array();
234
        
235
        foreach ($recordSet->getFields() as $name => $field){
236
            $fieldName = $field->getName();
237
            $fieldDescription = $field->getDescription();
238
            if(substr($fieldName, 0, 1) !== '_'){
239
                $fieldDescription = $App->translate($fieldDescription);
240
            }
241
            if(empty($fieldDescription)){
242
                $fieldDescription = $fieldName;
243
            }
244
            $availableFields[$name] = array(
245
                'name' => $fieldName,
246
                'description' => $fieldDescription
247
            );
248
        }
249
        
250
        $availableFields['_spacer'] = array(
251
            'name' => '_spacer',
252
            'description' => sprintf('[%s]', $App->translate('Spacer'))
253
        );
254
        
255
        $availableFields['_fieldsGroup'] = array(
256
            'name' => '_fieldsGroup',
257
            'description' => sprintf('[%s]', $App->translate('Fields group'))
258
        );
259
        
260
        return $availableFields;
261
    }
262
    
263
    /**
264
     * Displays an editor of the record values corresponding to the fields of a custom section.
265
     *
266
     * @param int $id
267
     *            The id of the record to edit
268
     * @param int $customSectionId
269
     *            The id of the section used to create the editor
270
     * @param string $itemId
271
     *
272
     * @throws AppAccessException::
273
     * @return AppPage
274
     */
275
    public function editSection($id, $customSectionId, $itemId = null)
276
    {
277
        $W = bab_Widgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $W is dead and can be removed.
Loading history...
278
        $App = $this->App();
279
        $Ui = $App->Ui();
280
        
281
        $page = $Ui->Page();
282
        
283
        $customSectionSet = $App->CustomSectionSet();
284
        $customSection = $customSectionSet->get($customSectionSet->id->is($customSectionId));
285
        
286
        $page->setTitle($customSection->name);
287
        
288
        $recordSet = $this->getEditRecordSet();
289
        
290
        if(isset($id)){
291
            $record = $recordSet->request($id);
292
            if(! $record->isUpdatable()){
293
                throw new AppAccessException($App->translate('You do not have access to this page'));
294
            }
295
        }
296
        else{
297
            if(! $recordSet->isCreatable()){
298
                throw new AppAccessException($App->translate('You do not have access to this page'));
299
            }
300
            $record = $recordSet->newRecord();
301
        }
302
        
303
        /* @var $editor AppRecordEditor */
304
        $editor = $this->getSectionEditor($record, $recordSet, $itemId);
305
        
306
        $section = $editor->sectionContent($customSectionId);
307
        $section->setSizePolicy('widget-60em');
308
        
309
        $editor->addItem($section);
310
        
311
        $editor->isAjax = bab_isAjaxRequest();
312
        
313
        $page->addItem($editor);
314
        
315
        return $page;
316
    }
317
    
318
    protected function getSectionEditor($record, $recordSet, $itemId = null)
319
    {
320
        $App = $this->App();
321
        $Ui = $App->Ui();
322
        $W = bab_Widgets();
323
        
324
        $recordClassname = $this->getRecordClassName();
325
        $editorClassname = $recordClassname . 'SectionEditor';
326
        
327
        /* @var $editor AppRecordEditor */
328
        $editor = $Ui->$editorClassname($record);
329
        if(! isset($itemId)){
330
            $itemId = $this->getClass() . '_' . __FUNCTION__;
331
        }
332
        $editor->setId($itemId);
333
        $editor->setController($this);
334
        $editor->setHiddenValue('tg', $App->controllerTg);
335
        $editor->setSaveAction($this->proxy()
336
            ->save());
337
        $editor->setCancelAction($this->proxy()
338
            ->cancel());
339
        $editor->setName('data');
340
        $editor->addItem($W->Hidden()
341
            ->setName('id'));
342
        $editor->recordSet = $recordSet;
343
        $editor->setRecord($record);
344
        
345
        return $editor;
346
    }
347
    
348
    public function cancel()
349
    {
350
        return true;
351
    }
352
    
353
    /**
354
     * @param string $itemId
355
     * @return string
356
     */
357
    public function getModelViewDefaultId($itemId = null)
358
    {
359
        if(! isset($itemId)){
360
            $itemId = $this->getClass() . '_modelView';
361
        }
362
        
363
        return $itemId;
364
    }
365
    
366
    /**
367
     * Returns the xxxModelView associated to the RecordSet.
368
     *
369
     * @param array|null $filter
370
     * @param string $type
371
     * @param array|null $columns
372
     *            Optional list of columns. array($columnPath] => '1' | '0').
373
     * @param string|null $itemId
374
     *            Widget item id
375
     * @return AppTableModelView
376
     */
377
    protected function modelView($filter = null, $type = null, $columns = null, $itemId = null)
378
    {
379
        $App = $this->App();
380
        $Ui = $App->Ui();
381
        
382
        $recordSet = $this->getRecordSet();
383
        
384
        $recordClassname = $this->getRecordClassName();
385
        
386
        $itemId = $this->getModelViewDefaultId($itemId);
387
        
388
        if(! isset($type)){
389
            $type = $this->getFilteredViewType($itemId);
390
        }
391
        
392
        // $types = $this->getAvailableModelViewTypes();
393
        
394
        switch ($type) {
395
            case 'cards':
396
                $tableviewClassname = $recordClassname . 'CardsView';
397
                break;
398
            
399
            case 'map':
400
                $tableviewClassname = $recordClassname . 'MapView';
401
                break;
402
            
403
            case 'calendar':
404
                $tableviewClassname = $recordClassname . 'CalendarView';
405
                break;
406
            
407
            case 'statistics':
408
                $tableviewClassname = $recordClassname . 'StatisticsView';
409
                break;
410
            
411
            case 'table':
412
            default:
413
                $tableviewClassname = $recordClassname . 'TableView';
414
                break;
415
        }
416
        
417
        /* @var $tableview WidgetTableModelView */
418
        $tableview = $Ui->$tableviewClassname();
419
        
420
        $tableview->setRecordController($this);
421
        
422
        $tableview->setId($itemId);
423
        
424
        $tableview->setRecordSet($recordSet);
425
        $tableview->addDefaultColumns($recordSet);
426
        if(isset($filter)){
427
            $tableview->setFilterValues($filter);
428
        }
429
        $filter = $tableview->getFilterValues();
430
        
431
        if(isset($filter['showTotal']) && $filter['showTotal']){
432
            $tableview->displaySubTotalRow(true);
433
        }
434
        
435
        $conditions = $tableview->getFilterCriteria($filter);
436
        
437
        $conditions = $conditions->_AND_($recordSet->isReadable());
438
        
439
        $records = $recordSet->select($conditions);
440
        
441
        // print_r($records->getSelectQuery());
442
        
443
        $tableview->setDataSource($records);
444
        
445
        if(isset($columns)){
446
            $availableColumns = $tableview->getVisibleColumns();
447
            
448
            $remainingColumns = array();
449
            foreach ($availableColumns as $availableColumn){
450
                $colPath = $availableColumn->getFieldPath();
451
                if(isset($columns[$colPath]) && $columns[$colPath] == '1'){
452
                    $remainingColumns[] = $availableColumn;
453
                }
454
            }
455
            $tableview->setColumns($remainingColumns);
456
        }
457
        
458
        $tableview->allowColumnSelection();
459
        
460
        return $tableview;
461
    }
462
    
463
    /**
464
     * @return AppEditor
465
     */
466
    protected function recordEditor($itemId = null)
467
    {
468
        $App = $this->App();
469
        $Ui = $App->Ui();
470
        $recordClassname = $this->getRecordClassName();
471
        $editorClassname = $recordClassname . 'Editor';
472
        $editor = $Ui->$editorClassname();
473
        
474
        if(! isset($itemId)){
475
            $itemId = $this->getClass() . '_' . __FUNCTION__;
476
        }
477
        $editor->setId($itemId);
478
        $editor->setHiddenValue('tg', $App->controllerTg);
479
        $editor->setSaveAction($this->proxy()->save());
480
        $editor->setCancelAction($this->proxy()->cancel());
481
        $editor->setName('data');
482
        
483
        $editor->isAjax = bab_isAjaxRequest();
484
        
485
        return $editor;
486
    }
487
    
488
    /**
489
     * @param WidgetTableModelView $tableView
490
     * @return AppToolbar
491
     */
492
    protected function toolbar(WidgetTableModelView $tableView)
493
    {
494
        $W = bab_Widgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $W is dead and can be removed.
Loading history...
495
        
496
        $toolbar = new AppToolbar();
497
        
498
        return $toolbar;
499
    }
500
    
501
    /**
502
     * @param WidgetTableModelView $tableView
503
     * @return AppToolbar
504
     */
505
    protected function listToolbar($tableView)
506
    {
507
        $W = bab_Widgets();
508
        $App = $this->App();
509
        
510
        $proxy = $this->proxy();
511
        
512
        $filter = $tableView->getFilterValues();
513
        
514
        $toolbar = new AppToolbar();
515
        
516
        $viewTypes = $this->getAvailableModelViewTypes();
517
        
518
        if(count($viewTypes) > 1){
519
            $viewsBox = $W->Items();
520
            $viewsBox->setSizePolicy('pull-right');
521
            // $viewsBox->addClass('btn-group', \Func_Icons::ICON_LEFT_16);
522
            $toolbar->addItem($viewsBox);
523
            
524
            $filteredViewType = $this->getFilteredViewType($tableView->getId());
525
            
526
            foreach ($viewTypes as $viewTypeId => $viewType){
527
                $viewsBox->addItem($W->Link('', $proxy->setFilteredViewType($tableView->getId(), $viewTypeId))
0 ignored issues
show
Bug introduced by
$proxy->setFilteredViewT...->getId(), $viewTypeId) of type true is incompatible with the type Widget_Action|bab_url|string expected by parameter $url of Func_Widgets::Link(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

527
                $viewsBox->addItem($W->Link('', /** @scrutinizer ignore-type */ $proxy->setFilteredViewType($tableView->getId(), $viewTypeId))
Loading history...
528
                    ->addClass('icon', $viewType['icon'] . ($filteredViewType === $viewTypeId ? ' active' : ''))
529
                    ->
530
                // ->setSizePolicy('btn btn-xs btn-default ' . ($filteredViewType === $viewTypeId ? 'active' : ''))
531
                setTitle($viewType['label'])
532
                    ->setAjaxAction());
533
            }
534
        }
535
        
536
        if(method_exists($proxy, 'exportSelect')){
537
            $toolbar->addItem($W->Link($App->translate('Export'), $proxy->exportSelect($filter))
538
                ->addClass('icon', \Func_Icons::ACTIONS_DOCUMENT_DOWNLOAD)
539
                ->setOpenMode(WidgetLink::OPEN_DIALOG)
540
                ->setDialogClass('box gradient blue halfSizeDialog'));
0 ignored issues
show
Bug introduced by
The method setDialogClass() does not exist on Widget_Link. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

540
                ->/** @scrutinizer ignore-call */ setDialogClass('box gradient blue halfSizeDialog'));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
541
        }
542
        
543
        if(method_exists($proxy, 'printList')){
544
            $toolbar->addItem($W->Link($App->translate('Print'), $proxy->printList($filter))
0 ignored issues
show
Bug introduced by
The method printList() does not exist on Capwelton\LibApp\Ctrl\AppCtrlRecord. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

544
            $toolbar->addItem($W->Link($App->translate('Print'), $proxy->/** @scrutinizer ignore-call */ printList($filter))
Loading history...
545
                ->addClass('icon', \Func_Icons::ACTIONS_DOCUMENT_PRINT)
546
                ->setOpenMode(WidgetLink::OPEN_POPUP));
547
        }
548
        
549
        return $toolbar;
550
    }
551
    
552
    /**
553
     * @param string $itemId
554
     * @return boolean
555
     */
556
    public function toggleFilterVisibility($itemId)
557
    {
558
        $W = bab_Widgets();
559
        
560
        $filterVisibility = $this->getFilterVisibility($itemId);
561
        $filterVisibility = ! $filterVisibility;
562
        $W->setUserConfiguration($itemId . '/filterVisibility', $filterVisibility);
563
        
564
        return true;
565
    }
566
    
567
    /**
568
     * @param string $itemId
569
     * @return boolean
570
     */
571
    protected function getFilterVisibility($itemId)
572
    {
573
        $W = bab_Widgets();
574
        $filterVisibility = $W->getUserConfiguration($itemId . '/filterVisibility');
575
        if(! isset($filterVisibility)){
576
            $filterVisibility = false;
577
            $W->setUserConfiguration($itemId . '/filterVisibility', $filterVisibility);
578
        }
579
        return $filterVisibility;
580
    }
581
    
582
    /**
583
     * Returns the current filtered view type (table, cards...)
584
     *
585
     * @param string $itemId
586
     *            The model view widget id
587
     * @return string
588
     */
589
    protected function getFilteredViewType($itemId)
590
    {
591
        $W = bab_Widgets();
592
        $type = $W->getUserConfiguration($itemId . '/viewType');
593
        if(! isset($type)){
594
            $type = 'table';
595
        }
596
        return $type;
597
    }
598
    
599
    /**
600
     * Sets the current filtered view type (table, cards...)
601
     *
602
     * @param string $itemId
603
     *            The model view widget id
604
     * @param string $type
605
     *            'table, 'cards'...
606
     */
607
    public function setFilteredViewType($itemId, $type = null)
608
    {
609
        $W = bab_Widgets();
610
        $W->setUserConfiguration($itemId . '/viewType', $type);
611
        
612
        return true;
613
    }
614
    
615
    /**
616
     * @param array $filter
617
     * @param string $type
618
     * @param string $itemId
619
     */
620
    public function filteredView($filter = null, $type = null, $itemId = null)
621
    {
622
        $W = bab_Widgets();
623
        
624
        $view = $this->modelView($filter, $type, null, $itemId);
625
        $view->setAjaxAction();
626
        
627
        $filter = $view->getFilterValues();
628
        
629
        $filterPanel = $view->advancedFilterPanel($filter);
630
        
631
        if($this->getFilterVisibility($itemId)){
632
            $filterPanel->addClass('show-filter');
633
        }
634
        else{
635
            $filterPanel->addClass('hide-filter');
636
        }
637
        
638
        $toolbar = $this->toolbar($view);
639
        $listToolbar = $this->listToolbar($view);
640
        
641
        if($view->isColumnSelectionAllowed()){
642
            $App = $this->App();
643
            $columnSelectionMenu = $W->Link($App->translate('Table configuration'), $this->proxy()
644
                ->modelViewColumnSettings($type, $itemId))
645
                ->setIcon(\Func_Icons::ACTIONS_VIEW_LIST_DETAILS)
646
                ->setOpenMode(WidgetLink::OPEN_DIALOG)
647
                ->setDialogClass('box gradient blue halfSizeDialog');
648
            $listToolbar->addItem($columnSelectionMenu);
649
        }
650
        
651
        $box = $W->VBoxItems($W->FlexItems($toolbar, $listToolbar)
0 ignored issues
show
Bug introduced by
The method FlexItems() does not exist on Func_Widgets. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

651
        $box = $W->VBoxItems($W->/** @scrutinizer ignore-call */ FlexItems($toolbar, $listToolbar)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
652
            ->setJustifyContent(WidgetFlexLayout::FLEX_JUSTIFY_CONTENT_SPACE_BETWEEN), $filterPanel, $this->previewHighlightedRecords()
653
            ->addClass('highlightedRecordsPreviewBox'));
654
        $box->setReloadAction($this->proxy()
0 ignored issues
show
Bug introduced by
$this->proxy()->filtered..., null, $view->getId()) of type Widget_VBoxLayout is incompatible with the type Widget_Action expected by parameter $reloadAction of Widget_Item::setReloadAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

654
        $box->setReloadAction(/** @scrutinizer ignore-type */ $this->proxy()
Loading history...
655
            ->filteredView(null, null, $view->getId()));
656
        
657
        return $box;
658
    }
659
    
660
    public function modelViewColumnSettings($type = null, $itemId = null)
661
    {
662
        $App = $this->App();
663
        $Ui = $App->Ui();
664
        $page = $Ui->Page();
665
        $page->setTitle($App->translate('Table configuration'));
666
        $W = bab_Widgets();
667
        
668
        $currentFilter = $W->getUserConfiguration($itemId . '/filter', 'widgets', false);
669
        
670
        $view = $this->modelView(array(), $type, null, $itemId);
671
        
672
        $page->addItem($editor = $Ui->TableModelViewColumnSettingsEditor($view));
673
        
674
        $editor->addItem(
675
            $W->Hidden(null, 'currentFilter', json_encode($currentFilter))    
676
        );
677
        
678
        $editor->setName('data');
679
        $editor->isAjax = true;
680
        $editor->checkUnsaved(false);
0 ignored issues
show
Bug introduced by
The call to Capwelton\LibApp\Ui\AppEditor::checkUnsaved() has too few arguments starting with unsavedMessage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

680
        $editor->/** @scrutinizer ignore-call */ 
681
                 checkUnsaved(false);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
681
        
682
        $editor->setSaveAction($this->proxy()
683
            ->saveModelViewColumnSettings());
684
        $editor->setCancelAction($this->proxy()
685
            ->cancel());
686
        $editor->setResetAction($this->proxy()
687
            ->resetModelViewColumnSettings());
688
        
689
        return $page;
690
    }
691
    
692
    public function saveModelViewColumnSettings($data = null)
693
    {
694
        $this->requireSaveMethod();
695
        
696
        $W = bab_Widgets();
697
        $tableModelViewId = $data['tableModelViewId'];
698
        $sessionOnly = isset($data['inSession']) ? $data['inSession'] : false;
699
        
700
        if(isset($data['pageLength'])){
701
            $W->setUserConfiguration($tableModelViewId . '/pageLength', $data['pageLength'], 'widgets', $sessionOnly);
702
        }
703
        if(isset($data['displaySubTotalRow'])){
704
            $W->setUserConfiguration($tableModelViewId . '/displaySubTotalRow', $data['displaySubTotalRow'], 'widgets', $sessionOnly);
705
        }
706
        if(isset($data['columns'])){
707
            $W->setUserConfiguration($tableModelViewId . '/columns', $data['columns'], 'widgets', $sessionOnly);
708
        }
709
        if(isset($data['currentFilter'])){
710
            $filter = json_decode($data['currentFilter'], true);
711
            $W->setUserConfiguration($tableModelViewId . '/filter', $filter, 'widgets', $sessionOnly);
712
        }
713
        
714
        $this->addReloadSelector('.depends-' . $tableModelViewId);
715
        return true;
716
    }
717
    
718
    public function resetModelViewColumnSettings($data = null)
719
    {
720
        $this->requireSaveMethod();
721
        
722
        $W = bab_Widgets();
723
        $tableModelViewId = $data['tableModelViewId'];
724
        $sessionOnly = isset($data['inSession']) ? $data['inSession'] : false;
725
        
726
        $W->deleteUserConfiguration($data['tableModelViewId'] . '/columns', 'widgets', $sessionOnly);
727
        
728
        $this->addReloadSelector("#{$tableModelViewId}");
729
        return true;
730
    }
731
    
732
    /**
733
     * @param array $filter
734
     * @param string $type
735
     * @return array
736
     */
737
    protected function getListItemMenus($filter = null, $type = null)
738
    {
739
        $itemMenus = array();
740
        
741
        // $tabs = $this->getTabs();
742
        
743
        // if (count($tabs) > 0) {
744
        // $itemMenus['all'] = array (
745
        // 'label' => $App->translate('All'),
746
        // 'action' => $this->proxy()->setCurrentTab('all')
747
        // );
748
        // }
749
        // foreach ($tabs as $tab) {
750
        // $itemMenus[$tab] = array(
751
        // 'label' => $tab,
752
        // 'action' => $this->proxy()->setCurrentTab($tab)
753
        // );
754
        // }
755
        
756
        return $itemMenus;
757
    }
758
    
759
    /**
760
     * @param array $filter
761
     * @param string $type
762
     * @return WidgetPage
763
     */
764
    public function displayList($filter = null, $type = null)
765
    {
766
        $W = bab_Widgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $W is dead and can be removed.
Loading history...
767
        
768
        $page = $this->App()
769
            ->Ui()
770
            ->Page();
771
        $page->addClass('app-page-list');
772
        
773
        $itemMenus = $this->getListItemMenus();
774
        
775
        foreach ($itemMenus as $itemMenuId => $itemMenu){
776
            $page->addItemMenu($itemMenuId, $itemMenu['label'], $itemMenu['action']);
777
        }
778
        
779
        $page->setCurrentItemMenu('displayList');
780
        
781
        $filteredView = $this->filteredView($filter, $type);
782
        
783
        $page->addItem($filteredView);
784
        
785
        return $page;
786
    }
787
    
788
    public function displayListFilter($col = null, $key = null)
789
    {
790
        $App = $this->App();
791
        $Ui = $App->Ui();
792
        $W = bab_Widgets();
793
        
794
        $page = $Ui->Page();
795
        $page->setTitle($App->translate('Search'));
796
        
797
        session_write_close();
798
        $editor = $Ui->BasicEditor();
799
        $editor->isAjax = true;
800
        $editor->setName('data');
801
        $editor->setSaveAction($this->proxy()
802
            ->saveDisplayListFilter(), $App->translate('Search'));
803
        $editor->setCancelAction($this->proxy()
804
            ->cancel(), $App->translate('Cancel'));
805
        
806
        $editor->addItem($W->Hidden(null, 'key', $key));
807
        
808
        /* @var $tableview WidgetTableModelView */
809
        $tableview = $this->modelView();
810
        
811
        $columns = $tableview->getVisibleColumns();
812
        $column = isset($columns[$col]) ? $columns[$col] : null;
813
        
814
        if(! isset($column)){
815
            return true;
816
        }
817
        
818
        $field = $column->getField();
819
        
820
        $label = $tableview->getFilterLabelWidget($col, $field);
821
        $widget = $tableview->getFilterInputWidget($col, $field);
822
        
823
        $editor->addItem($W->LabelledWidget($label->getText(), $widget, array(
0 ignored issues
show
Bug introduced by
array('filter', $col) of type array<integer,mixed|string> is incompatible with the type string expected by parameter $fieldName of Func_Widgets::LabelledWidget(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

823
        $editor->addItem($W->LabelledWidget($label->getText(), $widget, /** @scrutinizer ignore-type */ array(
Loading history...
824
            'filter',
825
            $col
826
        )));
827
        
828
        $filter = $W->getUserConfiguration($key . '/filter', 'widgets', false);
829
        if(isset($filter[$col])){
830
            $widget->setValue($filter[$col]);
831
        }
832
        
833
        $page->addItem($editor);
834
        return $page;
835
    }
836
    
837
    public function saveDisplayListFilter($data = null)
838
    {
839
        $this->requireSaveMethod();
840
        
841
        $W = bab_Widgets();
842
        
843
        $key = $data['key'];
844
        
845
        $filter = $W->getUserConfiguration($key . '/filter', 'widgets', false);
846
        if(isset($data['moreCriteria']) && $data['moreCriteria']){
847
            $filter = array();
848
        }
849
        foreach ($data['filter'] as $filterName => $filterValue){
850
            $filter[$filterName] = $filterValue;
851
        }
852
        $W->setUserConfiguration($key . '/filter', $filter, 'widgets', false);
853
        
854
        session_start();
855
        $_SESSION['modelViewMoreCriterias'][$key] = array();
856
        unset($_SESSION['modelViewMoreCriterias'][$key]);
857
        session_write_close();
858
        
859
        $this->addReloadSelector('.depends-' . $key);
860
        
861
        return true;
862
    }
863
    
864
    public function displayListMoreCriteria($key)
865
    {
866
        $App = $this->App();
867
        $Ui = $App->Ui();
868
        
869
        $page = $Ui->Page();
870
        $page->addClass('depends-modelViewMoreCriterias-' . $key);
871
        
872
        $page->setTitle($App->translate('Search'));
873
        
874
        session_write_close();
875
        
876
        $page->addItem($this->getDisplayListMoreCriteriaEditor($key));
877
        
878
        return $page;
879
    }
880
    
881
    public function getDisplayListMoreCriteriaEditor($key, $itemId = null)
882
    {
883
        $App = $this->App();
884
        $Ui = $App->Ui();
885
        $W = bab_Widgets();
886
        
887
        $editor = $Ui->BasicEditor($itemId, $W->VBoxLayout());
888
        $editor->setReloadAction($this->proxy()
889
            ->getDisplayListMoreCriteriaEditor($key, $editor->getId()));
890
        $editor->addClass('depends-modelViewMoreCriterias-' . $key);
891
        $editor->addClass('widget-no-close');
892
        $editor->setIconFormat();
893
        $editor->isAjax = true;
894
        $editor->setName('data');
895
        $editor->checkUnsaved(false);
0 ignored issues
show
Bug introduced by
The call to Capwelton\LibApp\Ui\AppEditor::checkUnsaved() has too few arguments starting with unsavedMessage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

895
        $editor->/** @scrutinizer ignore-call */ 
896
                 checkUnsaved(false);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
896
        $editor->addItem($W->Hidden(null, 'key', $key));
897
        $editor->addItem($W->Hidden(null, 'moreCriteria', true));
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $value of Func_Widgets::Hidden(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

897
        $editor->addItem($W->Hidden(null, 'moreCriteria', /** @scrutinizer ignore-type */ true));
Loading history...
898
        
899
        /* @var $tableview WidgetTableModelView */
900
        $tableview = $this->modelView();
901
        
902
        $columns = $tableview->getVisibleColumns();
903
        $filter = $tableview->getFilterValues();
904
        
905
        if(! isset($itemId)){
906
            $editor->setSaveAction($this->proxy()
907
                ->saveDisplayListFilter(), $App->translate('Search'));
908
            $editor->setCancelAction($this->proxy()
909
                ->cancel());
910
            
911
            $fields = array();
912
            foreach ($filter as $fieldName => $value){
913
                if(empty($value)){
914
                    continue;
915
                }
916
                if(! isset($columns[$fieldName])){
917
                    continue;
918
                }
919
                
920
                $column = $columns[$fieldName];
921
                
922
                if(! $column->isSearchable()){
923
                    continue;
924
                }
925
                
926
                $fields[$fieldName] = $value;
927
            }
928
            session_start();
929
            $_SESSION['modelViewMoreCriterias'][$key] = $fields;
930
            session_write_close();
931
        }
932
        else{
933
            $fields = $_SESSION['modelViewMoreCriterias'][$key];
934
        }
935
        
936
        $alreadyAddedFilters = array();
937
        
938
        $nbAlreadyAdded = 0;
939
        
940
        foreach ($fields as $fieldName => $fieldValue){
941
            if(! isset($columns[$fieldName])){
942
                continue;
943
            }
944
            $column = $columns[$fieldName];
945
            
946
            if(! $column->isSearchable()){
947
                continue;
948
            }
949
            
950
            $field = $column->getField();
951
            
952
            if($nbAlreadyAdded >= 2){
953
                $nbAlreadyAdded = 0;
954
                $alreadyFilteredBox = null;
955
            }
956
            
957
            if(! isset($alreadyFilteredBox)){
958
                $editor->addItem($alreadyFilteredBox = $W->FlexItems()
959
                    ->setSizePolicy('customsection-field-box customsection-fieldsgroup-box'));
960
            }
961
            
962
            $label = $tableview->getFilterLabelWidget($fieldName, $field);
963
            $widget = $tableview->getFilterInputWidget($fieldName, $field);
964
            $widget->setName(array(
965
                'filter',
966
                $fieldName
967
            ));
968
            $widget->setValue($fieldValue);
969
            $alreadyFilteredBox->addItem($W->LabelledWidget($label->getText(), $W->FlexItems($widget, $W->Link('', $this->proxy()
0 ignored issues
show
Bug introduced by
$this->proxy()->removeMo...Field($key, $fieldName) of type true is incompatible with the type Widget_Action|bab_url|string expected by parameter $url of Func_Widgets::Link(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

969
            $alreadyFilteredBox->addItem($W->LabelledWidget($label->getText(), $W->FlexItems($widget, $W->Link('', /** @scrutinizer ignore-type */ $this->proxy()
Loading history...
970
                ->removeMoreCriteriaField($key, $fieldName))
971
                ->setAjaxAction()
972
                ->addClass('icon', \Func_Icons::STATUS_DIALOG_ERROR)
973
                ->addAttribute('data-removefor', $fieldName))
974
                ->setJustifyContent(WidgetFlexLayout::FLEX_JUSTIFY_CONTENT_SPACE_BETWEEN)
975
                ->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_CONTENT_CENTER))
976
                ->addClass('app-customsection-groupedfield app-displaylist-morecriteria-groupedfield'));
977
            $nbAlreadyAdded ++;
978
            
979
            $alreadyAddedFilters[$fieldName] = $fieldName;
980
        }
981
        
982
        $options = array(
983
            '',
984
            ''
985
        );
986
        
987
        foreach ($columns as $fieldName => $column){
988
            if(! $column->isSearchable()){
989
                continue;
990
            }
991
            
992
            $field = $column->getField();
993
            
994
            if(isset($alreadyAddedFilters[$fieldName])){
995
                continue;
996
            }
997
            
998
            $label = $tableview->getFilterLabelWidget($fieldName, $field);
999
            $label = trim($label->getText());
1000
            if(empty($label)){
1001
                continue;
1002
            }
1003
            $options[$fieldName] = $label;
1004
        }
1005
        
1006
        if(count($options) > 1){
1007
            $editor->addItem($W->Html('<hr/>'));
1008
            $editor->addItem($W->FlexItems($W->LabelledWidget($App->translate('Add a new criteria'), $W->Select2()
0 ignored issues
show
Bug introduced by
The method Select2() does not exist on Func_Widgets. Did you maybe mean Select()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1008
            $editor->addItem($W->FlexItems($W->LabelledWidget($App->translate('Add a new criteria'), $W->/** @scrutinizer ignore-call */ Select2()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1009
                ->setOptions($options), 'newField')
1010
                ->addClass('app-customsection-groupedfield app-displaylist-morecriteria-groupedfield'))
1011
                ->setSizePolicy('customsection-field-box customsection-fieldsgroup-box'), 0);
1012
            $editor->setAjaxAction($this->proxy()
0 ignored issues
show
Bug introduced by
$this->proxy()->addMoreCriteriaField($key) of type true is incompatible with the type Capwelton\Widgets\Widgets\Helpers\WidgetAction expected by parameter $action of Capwelton\LibApp\Ui\AppEditor::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1012
            $editor->setAjaxAction(/** @scrutinizer ignore-type */ $this->proxy()
Loading history...
1013
                ->addMoreCriteriaField($key), '', 'change');
1014
        }
1015
        
1016
        return $editor;
1017
    }
1018
    
1019
    public function addMoreCriteriaField($key, $data = null)
1020
    {
1021
        session_start();
1022
        $fields = isset($data['filter']) ? $data['filter'] : array();
1023
        if(isset($data['newField']) && ! empty($data['newField'])){
1024
            $newField = $data['newField'];
1025
            unset($data['key']);
1026
            unset($data['moreCriteria']);
1027
            $fields[$newField] = '';
1028
            $this->addReloadSelector('.depends-modelViewMoreCriterias-' . $key);
1029
        }
1030
        $_SESSION['modelViewMoreCriterias'][$key] = $fields;
1031
        return true;
1032
    }
1033
    
1034
    public function removeMoreCriteriaField($key, $field)
1035
    {
1036
        $fields = $_SESSION['modelViewMoreCriterias'][$key];
1037
        if(isset($fields[$field])){
1038
            unset($fields[$field]);
1039
            session_start();
1040
            $_SESSION['modelViewMoreCriterias'][$key] = $fields;
1041
        }
1042
        $this->addReloadSelector('.depends-modelViewMoreCriterias-' . $key);
1043
        return true;
1044
    }
1045
    
1046
    /**
1047
     * @param array $filter
1048
     * @return WidgetPage
1049
     */
1050
    public function exportSelect($filter = null)
1051
    {
1052
        $App = $this->App();
1053
        $Ui = $App->Ui();
1054
        
1055
        $page = $App->Ui()->Page();
1056
        $page->addClass('app-page-editor');
1057
        
1058
        $page->setTitle($App->translate('Export list'));
1059
        
1060
        $tableview = $this->modelView($filter, 'table');
1061
        
1062
        $editor = $Ui->ExportSelectEditor(str_replace('::', '__', __METHOD__), $tableview, $filter);
1063
        $editor->checkUnsaved(false);
0 ignored issues
show
Bug introduced by
The call to Capwelton\LibApp\Ui\AppEditor::checkUnsaved() has too few arguments starting with unsavedMessage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1063
        $editor->/** @scrutinizer ignore-call */ 
1064
                 checkUnsaved(false);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1064
        $editor->setName('data');
1065
        $editor->addAttribute('target', '_blank');
1066
        
1067
        $editor->setSaveAction($this->proxy()
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->proxy()->exportList() targeting Capwelton\LibApp\Ctrl\AppCtrlRecord::exportList() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1068
            ->exportList(), $App->translate('Export'));
1069
        
1070
        $editor->setCancelAction($this->proxy()
1071
            ->cancel());
1072
        $page->addItem($editor);
1073
        
1074
        return $page;
1075
    }
1076
    
1077
    /**
1078
     * @param array $filter
1079
     */
1080
    public function exportList($data = null, $filter = null, $format = 'csv', $columns = null, $inline = true, $filename = 'export')
1081
    {
1082
        $App = $this->App();
1083
        
1084
        $page = $App->Ui()->Page();
1085
        $page->addClass('app-page-list');
1086
        
1087
        $filter = isset($data['filter']) ? $data['filter'] : null;
1088
        $columns = isset($data['columns']) ? $data['columns'] : null;
1089
        $filename = isset($data['filename']) ? $data['filename'] : 'export';
1090
        $inline = isset($data['inline']) ? $data['inline'] : true;
1091
        $format = isset($data['format']) ? $data['format'] : 'csv';
1092
        
1093
        $tableview = $this->modelView($filter, 'table', $columns);
1094
        $tableview->allowColumnSelection(false);
1095
        
1096
        switch ($format) {
1097
            case 'xlsx':
1098
                $tableview->downloadXlsx($filename . '.xlsx');
1099
                break;
1100
            case 'xls':
1101
                $tableview->downloadExcel($filename . '.xls');
1102
                break;
1103
            case 'ssv':
1104
                $tableview->downloadCsv($filename . '.csv', ';', $inline, 'Windows-1252');
1105
                break;
1106
            case 'csv':
1107
            default:
1108
                $tableview->downloadCsv($filename . '.csv', ',', $inline, \bab_charset::getIso());
1109
                break;
1110
        }
1111
    }
1112
    
1113
    // /**
1114
    // * Returns a page with the record information.
1115
    // *
1116
    // * @param int $id
1117
    // * @return app_Page
1118
    // */
1119
    // public function display($id, $view = '')
1120
    // {
1121
    // $App = $this->App();
1122
    // $page = $App->Ui()->Page();
1123
    
1124
    // $recordSet = $this->getRecordSet();
1125
    
1126
    // $record = $recordSet->request($id);
1127
    
1128
    // if (!$record->isReadable()) {
1129
    // throw new app_AccessException($App->translate('You do not have access to this page'));
1130
    // }
1131
    
1132
    // $W = bab_Widgets();
1133
    // $Ui = $App->Ui();
1134
    
1135
    // $recordClassname = $this->getRecordClassName();
1136
    // $fullFrameClassname = $recordClassname . 'FullFrame';
1137
    // $fullFrame = $Ui->$fullFrameClassname($record, $view);
1138
    
1139
    // $maxHistory = 8;
1140
    // $historyFrame = $W->VBoxItems(
1141
    // $App->Controller()->Search(false)->history($record->getRef(), $maxHistory, 0, true)
1142
    // );
1143
    // $fullFrame->addItem(
1144
    // $W->Section(
1145
    // $App->translate('History'),
1146
    // $historyFrame,
1147
    // 2
1148
    // )->setFoldable(true)
1149
    // ->addClass('compact')
1150
    // );
1151
    
1152
    // $page->addItem($fullFrame);
1153
    
1154
    // // Actions
1155
    // $page->addContextItem($this->getDisplayActionFrame($page, $record));
1156
    
1157
    // return $page;
1158
    // }
1159
    
1160
    /**
1161
     * Returns a page with the record information.
1162
     *
1163
     * @param int $id
1164
     * @return AppPage
1165
     */
1166
    public function display($id, $view = '', $itemId = null)
1167
    {
1168
        $App = $this->App();
1169
        $Ui = $App->Ui();
1170
        
1171
        $recordSet = $this->getRecordSet();
1172
        
1173
        $record = $recordSet->request($id);
1174
        if(! $record->isReadable()){
1175
            throw new AppAccessException($App->translate('You do not have access to this page'));
1176
        }
1177
        
1178
        $W = bab_Widgets();
1179
        
1180
        $recordClassname = $this->getRecordClassName();
1181
        
1182
        $viewClassname = $recordClassname . 'FullFrame';
1183
        
1184
        $fullFrame = $Ui->$viewClassname($record);
1185
        $fullFrame->setView($view);
1186
        
1187
        $actions = $this->getActions($record);
0 ignored issues
show
Bug introduced by
The method getActions() does not exist on Capwelton\LibApp\Ctrl\AppCtrlRecord. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1187
        /** @scrutinizer ignore-call */ 
1188
        $actions = $this->getActions($record);
Loading history...
1188
        
1189
        $mainMenu = $W->Html($this->createMenu($actions));
1190
        $mainMenu->addClass('app-record-nav', 'nav', 'navbar-nav', 'pull-right');
1191
        $mainMenu->setSizePolicy(\Func_Icons::ICON_LEFT_24);
1192
        
1193
        $page = $Ui->Page();
1194
        if(isset($itemId)){
1195
            $page->setId($itemId);
1196
        }
1197
        $page->addClass('depends-' . $this->getRecordClassName());
1198
        
1199
        $page->addToolbar($mainMenu);
1200
        
1201
        $page->addItem($fullFrame);
1202
        
1203
        $page->setReloadAction($this->proxy()
1204
            ->display($id), $page->getId());
1205
        
1206
        return $page;
1207
    }
1208
    
1209
    protected function getDisplayActionFrame(WidgetPage $page, AppRecord $record)
1210
    {
1211
        $actionsFrame = $page->ActionsFrame();
1212
        return $actionsFrame;
1213
    }
1214
    
1215
    /**
1216
     * Returns a page containing an editor for the record.
1217
     *
1218
     * @param
1219
     *            string|null id A record id or null for a new record editor.
1220
     * @return WidgetPage
1221
     */
1222
    public function edit($id = null, $view = '')
1223
    {
1224
        $W = bab_Widgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $W is dead and can be removed.
Loading history...
1225
        $App = $this->App();
1226
        
1227
        $recordSet = $this->getEditRecordSet();
1228
        
1229
        $page = $App->Ui()->Page();
1230
        $page->addClass('app-page-editor');
1231
        
1232
        $page->setTitle($App->translate($recordSet->getDescription()));
1233
        
1234
        $editor = $this->recordEditor();
1235
        
1236
        if(isset($id)){
1237
            $record = $recordSet->request($id);
1238
            if(! $record->isUpdatable()){
1239
                throw new AppAccessException($App->translate('You do not have access to this page'));
1240
            }
1241
        }
1242
        else{
1243
            if(! $recordSet->isCreatable()){
1244
                throw new AppAccessException($App->translate('You do not have access to this page'));
1245
            }
1246
            $record = $recordSet->newRecord();
1247
        }
1248
        $editor->setRecord($record);
1249
        $editor->addSections($view);
1250
        
1251
        $page->addItem($editor);
1252
        
1253
        return $page;
1254
    }
1255
    
1256
    /**
1257
     * Returns a page containing an editor for the tags record.
1258
     *
1259
     * @param
1260
     *            string|null id A record id or null for a new record editor.
1261
     * @return WidgetPage
1262
     */
1263
    public function editTags($id = null, $view = '')
1264
    {
1265
        $W = bab_Widgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $W is dead and can be removed.
Loading history...
1266
        $App = $this->App();
1267
        $Ui = $App->Ui();
1268
        
1269
        $recordSet = $this->getEditRecordSet();
1270
        
1271
        $page = $Ui->Page();
1272
        $page->addClass('app-page-editor');
1273
        
1274
        $page->setTitle($App->translate($recordSet->getDescription()));
1275
        
1276
        $editor = $Ui->TagsEditor();
0 ignored issues
show
Bug introduced by
The method TagsEditor() does not exist on Capwelton\LibApp\Ui\AppUi. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1276
        /** @scrutinizer ignore-call */ 
1277
        $editor = $Ui->TagsEditor();
Loading history...
1277
        
1278
        if(isset($id)){
1279
            $record = $recordSet->request($id);
1280
            if(! $record->isUpdatable()){
1281
                throw new AppAccessException($App->translate('You do not have access to this page'));
1282
            }
1283
            $editor->setRecord($record);
1284
        }
1285
        else{
1286
            if(! $recordSet->isCreatable()){
1287
                throw new AppAccessException($App->translate('You do not have access to this page'));
1288
            }
1289
            $record = $recordSet->newRecord();
1290
            $editor->setRecord($record);
1291
        }
1292
        
1293
        $page->addItem($editor);
1294
        
1295
        return $page;
1296
    }
1297
    
1298
    public function ok()
1299
    {
1300
        return true;
1301
    }
1302
    
1303
    /**
1304
     * @param
1305
     *            $data
1306
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $data at position 0 could not be parsed: Unknown type name '$data' at position 0 in $data.
Loading history...
1307
    public function create($data)
1308
    {
1309
    }
1310
    
1311
    /**
1312
     * @param
1313
     *            $data
1314
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $data at position 0 could not be parsed: Unknown type name '$data' at position 0 in $data.
Loading history...
1315
    public function update($data)
1316
    {
1317
    }
1318
    
1319
    /**
1320
     */
1321
    public function read($id)
1322
    {
1323
    }
1324
    
1325
    /**
1326
     * Get the message to display on delete next page
1327
     *
1328
     * @return string | true
1329
     */
1330
    protected function getDeletedMessage(ORMRecord $record)
1331
    {
1332
        $App = $this->App();
1333
        $recordSet = $this->getRecordSet();
1334
        
1335
        $recordTitle = $record->getRecordTitle();
1336
        
1337
        $message = sprintf($App->translate('%s has been deleted'), $App->translate($recordSet->getDescription()) . ' "' . $recordTitle . '"');
1338
        return $message;
1339
    }
1340
    
1341
    /**
1342
     * Get the message to display on create next page
1343
     *
1344
     * @return string | true
1345
     */
1346
    protected function getCreatedMessage()
1347
    {
1348
        return true;
1349
    }
1350
    
1351
    /**
1352
     * Get the message to display on modification next page
1353
     *
1354
     * @param AppRecord $record
1355
     *            The record before the modification
1356
     * @return string | true
1357
     */
1358
    protected function getModifedMessage(ORMRecord $record)
1359
    {
1360
        return true;
1361
    }
1362
    
1363
    /**
1364
     * Method to check reord before saving
1365
     *
1366
     * @param AppRecord $record
1367
     */
1368
    protected function preSave(ORMRecord $record, $data)
1369
    {
1370
    }
1371
    
1372
    /**
1373
     * Method for post save actions on record
1374
     *
1375
     * @param AppRecord $record
1376
     */
1377
    protected function postSave(ORMRecord $record, $data)
1378
    {
1379
    }
1380
    
1381
    /**
1382
     * Save a record
1383
     *
1384
     * @requireSaveMethod
1385
     *
1386
     * @param array $data
1387
     */
1388
    public function save($data = null)
1389
    {
1390
        $this->requireSaveMethod();
1391
        $App = $this->App();
1392
        $recordSet = $this->getSaveRecordSet();
1393
        $pk = $recordSet->getPrimaryKey();
1394
        $message = null;
1395
        
1396
        if(! empty($data[$pk])){
1397
            $record = $recordSet->request($data[$pk]);
1398
            unset($data[$pk]);
1399
            
1400
            if(! $record->isUpdatable()){
1401
                throw new AppAccessException('Access denied');
1402
            }
1403
            
1404
            $message = $this->getModifedMessage($record);
1405
        }
1406
        else{
1407
            
1408
            $record = $recordSet->newRecord();
1409
            
1410
            if(! $recordSet->isCreatable()){
1411
                throw new AppAccessException('Access denied');
1412
            }
1413
            
1414
            $message = $this->getCreatedMessage();
1415
        }
1416
        
1417
        if(! isset($record)){
1418
            throw new AppSaveException($App->translate('The record does not exists'));
1419
        }
1420
        
1421
        if(! isset($data)){
1422
            throw new AppSaveException($App->translate('Nothing to save'));
1423
        }
1424
        
1425
        $record->setFormInputValues($data);
1426
        
1427
        $this->preSave($record, $data);
1428
        if($record->save()){
1429
            $this->postSave($record, $data);
1430
            if(is_string($message)){
0 ignored issues
show
introduced by
The condition is_string($message) is always false.
Loading history...
1431
                $this->addToast($message);
1432
            }
1433
            
1434
            $this->addReloadSelector('.depends-' . $this->getRecordClassName());
1435
            return true;
1436
        }
1437
        
1438
        return true;
1439
    }
1440
    
1441
    /**
1442
     * Deletes the specified record.
1443
     *
1444
     * @requireDeleteMethod
1445
     *
1446
     * @param string $id
1447
     *            The record id
1448
     * @return boolean
1449
     */
1450
    public function delete($id)
1451
    {
1452
        $this->requireDeleteMethod();
1453
        $recordSet = $this->getDeleteRecordSet();
1454
        
1455
        $record = $recordSet->request($id);
1456
        
1457
        if(! $record->isDeletable()){
1458
            throw new AppAccessException('Sorry, You are not allowed to perform this operation');
1459
        }
1460
        $deletedMessage = $this->getDeletedMessage($record);
1461
        
1462
        if($record->delete()){
1463
            $this->addToast($deletedMessage);
1464
        }
1465
        
1466
        $this->addReloadSelector('.depends-' . $record->getClassName());
1467
        
1468
        return true;
1469
    }
1470
    
1471
    /**
1472
     * Displays a page asking to confirm the deletion of a record.
1473
     *
1474
     * @param int $id
1475
     */
1476
    public function confirmDelete($id)
1477
    {
1478
        $W = bab_Widgets();
1479
        $App = $this->App();
1480
        $Ui = $App->Ui();
1481
        
1482
        $recordSet = $this->getRecordSet();
1483
        $record = $recordSet->get($id);
1484
        
1485
        $page = $Ui->Page();
1486
        
1487
        $page->addClass('app-page-editor');
1488
        $page->setTitle($App->translate('Deletion'));
1489
        
1490
        if(! isset($record)){
1491
            $page->addItem($W->Label($App->translate('This element does not exists.')));
1492
            $page->addClass('alert', 'alert-warning');
1493
            return $page;
1494
        }
1495
        
1496
        $form = new AppEditor($App);
1497
        
1498
        $form->addItem($W->Hidden()
1499
            ->setName('id'));
1500
        
1501
        $recordTitle = $record->getRecordTitle();
1502
        
1503
        $subTitle = $App->translate($recordSet->getDescription()) . ' "' . $recordTitle . '"';
1504
        $form->addItem($W->Title($subTitle, 5));
1505
        
1506
        $form->addItem($W->Title($App->translate('Confirm delete?'), 6));
1507
        
1508
        $form->addItem($W->Html(bab_toHtml($App->translate('It will not be possible to undo this deletion.'))));
1509
        
1510
        $confirmedAction = $this->proxy()->delete($id);
1511
        $parameters = $confirmedAction->getParameters();
1512
        foreach ($parameters as $key => $value){
1513
            $form->setHiddenValue($key, $value);
1514
        }
1515
        $form->addButton($W->SubmitButton()
1516
            ->setAjaxAction($confirmedAction)
0 ignored issues
show
Bug introduced by
$confirmedAction of type true is incompatible with the type Widget_Action|null expected by parameter $action of Widget_Widget::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1516
            ->setAjaxAction(/** @scrutinizer ignore-type */ $confirmedAction)
Loading history...
1517
            ->setLabel($App->translate('Delete')));
1518
        $form->addButton($W->SubmitButton()
1519
            ->setLabel($App->translate('Cancel'))
1520
            ->addClass('widget-close-dialog'));
1521
        $page->addItem($form);
1522
        
1523
        return $page;
1524
    }
1525
    
1526
    /**
1527
     * Deletes the specified record.
1528
     *
1529
     * @requireDeleteMethod
1530
     *
1531
     * @param string $id
1532
     *            The record id
1533
     * @return boolean
1534
     */
1535
    public function remove($id)
1536
    {
1537
        $this->requireDeleteMethod();
1538
        $recordSet = $this->getDeleteRecordSet();
1539
        
1540
        $record = $recordSet->request($id);
1541
        
1542
        if(! $record->isRemovable()){
1543
            throw new AppAccessException('Sorry, You are not allowed to perform this operation');
1544
        }
1545
        
1546
        $App = $this->App();
1547
        $deletedMessage = $App->translate('The element has been moved to the trash');
1548
        
1549
        if($recordSet->delete($recordSet->id->is($record->id), AppTraceableRecord::DELETED_STATUS_IN_TRASH)){
1550
            if(is_string($deletedMessage)){
0 ignored issues
show
introduced by
The condition is_string($deletedMessage) is always true.
Loading history...
1551
                $this->addToast($deletedMessage);
1552
            }
1553
        }
1554
        
1555
        $this->addReloadSelector('.depends-' . $record->getClassName());
1556
        
1557
        return true;
1558
    }
1559
    
1560
    /**
1561
     * Displays a page asking to confirm the deletion of a record.
1562
     *
1563
     * @param int $id
1564
     */
1565
    public function confirmRemove($id)
1566
    {
1567
        $W = bab_Widgets();
1568
        $App = $this->App();
1569
        $Ui = $App->Ui();
1570
        
1571
        $recordSet = $this->getRecordSet();
1572
        $record = $recordSet->get($id);
1573
        
1574
        $page = $Ui->Page();
1575
        
1576
        $page->addClass('app-page-editor');
1577
        $page->setTitle($App->translate('Move to trash'));
1578
        
1579
        $form = new AppEditor($App);
1580
        
1581
        $recordTitle = $record->getRecordTitle();
1582
        
1583
        $subTitle = $App->translate($recordSet->getDescription()) . ' "' . $recordTitle . '"';
1584
        $form->addItem($W->Title($subTitle, 5));
1585
        
1586
        $form->addItem($W->Title($App->translate('Confirm delete?'), 6));
1587
        
1588
        // $form->addItem($W->Html(bab_toHtml($App->translate('It will not be possible to undo this deletion.'))));
1589
        
1590
        $confirmedAction = $this->proxy()->remove($id);
1591
        $parameters = $confirmedAction->getParameters();
1592
        foreach ($parameters as $key => $value){
1593
            $form->setHiddenValue($key, $value);
1594
        }
1595
        $form->addButton($W->SubmitButton()
1596
            ->setAjaxAction($confirmedAction)
0 ignored issues
show
Bug introduced by
$confirmedAction of type true is incompatible with the type Widget_Action|null expected by parameter $action of Widget_Widget::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1596
            ->setAjaxAction(/** @scrutinizer ignore-type */ $confirmedAction)
Loading history...
1597
            ->setLabel($App->translate('Move to trash')));
1598
        $form->addButton($W->SubmitButton()
1599
            ->setLabel($App->translate('Cancel'))
1600
            ->addClass('widget-close-dialog'));
1601
        $page->addItem($form);
1602
        
1603
        return $page;
1604
    }
1605
    
1606
    /**
1607
     * Restores the specified record.
1608
     *
1609
     * @requireDeleteMethod
1610
     *
1611
     * @param string $id
1612
     *            The record id
1613
     * @return boolean
1614
     */
1615
    public function restore($id)
1616
    {
1617
        $this->requireSaveMethod();
1618
        $recordSet = $this->getRecordSet();
1619
        
1620
        $records = $recordSet->select($recordSet->id->is($id), true);
0 ignored issues
show
Unused Code introduced by
The call to Capwelton\LibApp\Set\AppRecordSet::select() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1620
        /** @scrutinizer ignore-call */ 
1621
        $records = $recordSet->select($recordSet->id->is($id), true);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1621
        
1622
        $record = null;
1623
        foreach ($records as $record){
1624
        }
1625
        if(! isset($record)){
1626
            throw new AppAccessException('Sorry, You are not allowed to perform this operation');
1627
        }
1628
        if(! $record->isRestorable()){
1629
            throw new AppAccessException('Sorry, You are not allowed to perform this operation');
1630
        }
1631
        
1632
        $App = $this->App();
1633
        $deletedMessage = $App->translate('The element has been restored from the trash');
1634
        
1635
        $record->deleted = AppTraceableRecord::DELETED_STATUS_EXISTING;
1636
        $record->save();
1637
        $this->addToast($deletedMessage);
1638
        
1639
        $this->addReloadSelector('.depends-' . $record->getClassName());
1640
        
1641
        return true;
1642
    }
1643
    
1644
    /**
1645
     * Displays a page asking to confirm the deletion of a record.
1646
     *
1647
     * @param int $id
1648
     */
1649
    public function confirmRestore($id)
1650
    {
1651
        $W = bab_Widgets();
1652
        $App = $this->App();
1653
        $Ui = $App->Ui();
1654
        
1655
        $recordSet = $this->getRecordSet();
1656
        $records = $recordSet->select($recordSet->id->is($id), true);
0 ignored issues
show
Unused Code introduced by
The call to Capwelton\LibApp\Set\AppRecordSet::select() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1656
        /** @scrutinizer ignore-call */ 
1657
        $records = $recordSet->select($recordSet->id->is($id), true);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1657
        
1658
        $record = null;
1659
        foreach ($records as $record){
1660
        }
1661
        if(! isset($record)){
1662
            throw new AppAccessException('Sorry, You are not allowed to perform this operation');
1663
        }
1664
        
1665
        $page = $Ui->Page();
1666
        
1667
        $page->addClass('app-page-editor');
1668
        $page->setTitle($App->translate('Restore from trash'));
1669
        
1670
        $form = new AppEditor($App);
1671
        
1672
        $recordTitle = $record->getRecordTitle();
1673
        
1674
        $subTitle = $App->translate($recordSet->getDescription()) . ' "' . $recordTitle . '"';
1675
        $form->addItem($W->Title($subTitle, 5));
1676
        
1677
        $confirmedAction = $this->proxy()->restore($id);
1678
        $parameters = $confirmedAction->getParameters();
1679
        foreach ($parameters as $key => $value){
1680
            $form->setHiddenValue($key, $value);
1681
        }
1682
        $form->addButton($W->SubmitButton()
1683
            ->setAjaxAction($confirmedAction)
0 ignored issues
show
Bug introduced by
$confirmedAction of type true is incompatible with the type Widget_Action|null expected by parameter $action of Widget_Widget::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1683
            ->setAjaxAction(/** @scrutinizer ignore-type */ $confirmedAction)
Loading history...
1684
            ->setLabel($App->translate('Restore from trash')));
1685
        $form->addButton($W->SubmitButton()
1686
            ->setLabel($App->translate('Cancel'))
1687
            ->addClass('widget-close-dialog'));
1688
        $page->addItem($form);
1689
        
1690
        return $page;
1691
    }
1692
    
1693
    /**
1694
     * @param array $filter
1695
     * @param string $type
1696
     * @param string $itemId
1697
     */
1698
    public function filteredTrash($filter = null, $type = null, $itemId = null)
1699
    {
1700
        $W = bab_Widgets();
1701
        
1702
        $view = $this->modelView($filter, $type, null, $itemId);
1703
        $view->setAjaxAction();
1704
        
1705
        if(isset($filter)){
1706
            $view->setFilterValues($filter);
1707
        }
1708
        $filter = $view->getFilterValues();
1709
        
1710
        if(isset($filter['showTotal']) && $filter['showTotal']){
1711
            $view->displaySubTotalRow(true);
1712
        }
1713
        
1714
        $recordSet = $this->getRecordSet();
1715
        $view->setRecordSet($recordSet);
1716
        $view->addDefaultColumns($recordSet);
1717
        
1718
        $conditions = $view->getFilterCriteria($filter);
1719
        $conditions = $conditions->_AND_($recordSet->isReadable());
1720
        
1721
        $conditions = $conditions->_AND_($recordSet->deleted->is(AppTraceableRecord::DELETED_STATUS_IN_TRASH));
1722
        
1723
        $records = $recordSet->select($conditions, true);
0 ignored issues
show
Unused Code introduced by
The call to Capwelton\LibApp\Set\AppRecordSet::select() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1723
        /** @scrutinizer ignore-call */ 
1724
        $records = $recordSet->select($conditions, true);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1724
        
1725
        $view->setDataSource($records);
1726
        
1727
        $view->allowColumnSelection();
1728
        
1729
        $filterPanel = $view->advancedFilterPanel($filter);
1730
        
1731
        // $toolbar = $this->toolbar($view);
1732
        
1733
        $box = $W->VBoxItems(
1734
            // $toolbar,
1735
            $filterPanel);
1736
        $box->setReloadAction($this->proxy()
0 ignored issues
show
Bug introduced by
$this->proxy()->filtered..., null, $view->getId()) of type Widget_VBoxLayout is incompatible with the type Widget_Action expected by parameter $reloadAction of Widget_Item::setReloadAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1736
        $box->setReloadAction(/** @scrutinizer ignore-type */ $this->proxy()
Loading history...
1737
            ->filteredTrash(null, null, $view->getId()));
1738
        
1739
        return $box;
1740
    }
1741
    
1742
    public function displayTrash()
1743
    {
1744
        $App = $this->App();
1745
        $Ui = $App->Ui();
1746
        
1747
        $page = $Ui->Page();
1748
        
1749
        // $page->setTitle($App->translate('Trash'));
1750
        
1751
        $trashView = $this->filteredTrash();
1752
        
1753
        $page->addItem($trashView);
1754
        
1755
        $itemMenus = $this->getListItemMenus();
1756
        foreach ($itemMenus as $itemMenuId => $itemMenu){
1757
            $page->addItemMenu($itemMenuId, $itemMenu['label'], $itemMenu['action']);
1758
        }
1759
        $page->setCurrentItemMenu('displayTrash');
1760
        
1761
        return $page;
1762
    }
1763
    
1764
    protected function getClass()
1765
    {
1766
        $rc = new \ReflectionClass($this);
1767
        return $rc->getShortName();
1768
    }
1769
    
1770
    /**
1771
     * @return string[]
1772
     */
1773
    public function getFilterNames()
1774
    {
1775
        $id = $this->getModelViewDefaultId();
1776
        
1777
        $filters = array();
1778
        
1779
        $registry = bab_getRegistryInstance();
1780
        
1781
        $userId = '0';
1782
        $registry->changeDirectory('/widgets/user/' . $userId . '/' . $id . '/filters');
1783
        
1784
        while ($filterName = $registry->fetchChildKey()){
1785
            $filters[] = $filterName;
1786
        }
1787
        
1788
        $userId = bab_getUserId();
1789
        $registry->changeDirectory('/widgets/user/' . $userId . '/' . $id . '/filters');
1790
        
1791
        while ($filterName = $registry->fetchChildKey()){
1792
            $filters[] = $filterName;
1793
        }
1794
        
1795
        return $filters;
1796
    }
1797
    
1798
    /**
1799
     * Sets the currently used filter for the page.
1800
     *
1801
     * @param string $filterName
1802
     * @return boolean
1803
     */
1804
    public function setCurrentFilterName($filterName)
1805
    {
1806
        $W = bab_Widgets();
1807
        $tableview = $this->modelView(null, 'table');
1808
        $W->setUserConfiguration($tableview->getId() . '/currentFilterName', $filterName, 'widgets', false);
1809
        
1810
        $registry = bab_getRegistryInstance();
1811
        $userId = '0';
1812
        $registry->changeDirectory('/widgets/user/' . $userId . '/' . $tableview->getId() . '/filters');
1813
        $filterValues = $registry->getValue($filterName);
1814
        
1815
        if(! $filterValues){
1816
            $filterValues = $W->getUserConfiguration($tableview->getId() . '/filters/' . $filterName, 'widgets', false);
1817
        }
1818
        
1819
        $tableview = $this->modelView($filterValues, 'table');
1820
        $tableview->setFilterValues($filterValues['values']);
1821
        
1822
        return true;
1823
    }
1824
    
1825
    /**
1826
     * @return string|null
1827
     */
1828
    protected function getCurrentFilterName()
1829
    {
1830
        $W = bab_Widgets();
1831
        $id = $this->getModelViewDefaultId();
1832
        $filter = $W->getUserConfiguration($id . '/currentFilterName', 'widgets', false);
1833
        
1834
        return $filter;
1835
    }
1836
    
1837
    /**
1838
     * @return boolean
1839
     */
1840
    public function resetFilters($name = null)
1841
    {
1842
        if(isset($name)){
1843
            $W = bab_Widgets();
1844
            $filter = $W->getUserConfiguration($tableview->getId() . '/filters/' . $name, 'widgets', false);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tableview seems to be never defined.
Loading history...
1845
            $filterValues = $filter['values'];
1846
        }
1847
        else{
1848
            $filterValues = null;
1849
        }
1850
        
1851
        $tableview = $this->modelView($filterValues, 'table');
1852
        $tableview->setFilterValues($filterValues);
1853
        
1854
        return true;
1855
    }
1856
    
1857
    /**
1858
     * Saves the values of the current view filter under the specified name.
1859
     *
1860
     * @param string $name
1861
     * @return boolean
1862
     */
1863
    public function saveCurrentFilter($name = null, $description = null)
1864
    {
1865
        $W = bab_Widgets();
1866
        $tableview = $this->modelView(null, 'table');
1867
        $filterValues = $tableview->getFilterValues();
1868
        
1869
        $data = array(
1870
            'description' => $description,
1871
            'values' => $filterValues
1872
        );
1873
        
1874
        $W->setUserConfiguration($tableview->getId() . '/filters/' . $name, $data, 'widgets', false);
1875
        
1876
        return true;
1877
    }
1878
    
1879
    /**
1880
     * Display a dialog to propose saving the current view filter under a specific name.
1881
     *
1882
     * @return AppPage
1883
     */
1884
    public function confirmSaveCurrentFilter()
1885
    {
1886
        $W = bab_Widgets();
1887
        $App = $this->App();
1888
        $Ui = $App->Ui();
1889
        
1890
        $currentFilterName = $this->getCurrentFilterName();
1891
        $filter = $W->getUserConfiguration($this->getModelViewDefaultId() . '/filters/' . $currentFilterName, 'widgets', false);
1892
        
1893
        $page = $Ui->Page();
1894
        
1895
        $page->addClass('crm-page-editor');
1896
        $page->setTitle($App->translate('Save current filter'));
1897
        
1898
        $form = new AppEditor($App);
1899
        
1900
        $form->addItem($W->Html(bab_toHtml($App->translate('Save the current filter values so that you can reuse them later.'))));
1901
        
1902
        $form->addItem($W->LabelledWidget($App->translate('Name'), $W->LineEdit()
1903
            ->setValue($currentFilterName), 'name'));
1904
        $form->addItem($W->LabelledWidget($App->translate('Description'), $W->TextEdit()
1905
            ->setValue($filter['description']), 'description'));
1906
        
1907
        $confirmedAction = $this->proxy()->saveCurrentFilter();
1908
        $form->addButton($W->SubmitButton()
1909
            ->setAjaxAction($confirmedAction)
0 ignored issues
show
Bug introduced by
$confirmedAction of type true is incompatible with the type Widget_Action|null expected by parameter $action of Widget_Widget::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1909
            ->setAjaxAction(/** @scrutinizer ignore-type */ $confirmedAction)
Loading history...
1910
            ->setLabel($App->translate('Save')));
1911
        
1912
        $page->addItem($form);
1913
        
1914
        return $page;
1915
    }
1916
    
1917
    /**
1918
     * Display a dialog to propose saving the current view filter under a specific name.
1919
     *
1920
     * @return AppPage
1921
     */
1922
    public function editFilter($name)
1923
    {
1924
        $W = bab_Widgets();
1925
        $App = $this->App();
1926
        $Ui = $App->Ui();
1927
        
1928
        $filter = $W->getUserConfiguration($this->getModelViewDefaultId() . '/filters/' . $name, 'widgets', false);
1929
        
1930
        $page = $Ui->Page();
1931
        
1932
        $page->addClass('crm-page-editor');
1933
        $page->setTitle($App->translate('Edit filter'));
1934
        
1935
        $form = new AppEditor($App);
1936
        
1937
        $form->addItem($W->LabelledWidget($App->translate('Name'), $W->LineEdit()
1938
            ->setValue($name), 'name'));
1939
        $form->addItem($W->LabelledWidget($App->translate('Description'), $W->TextEdit()
1940
            ->setValue($filter['description']), 'description'));
1941
        
1942
        $confirmedAction = $this->proxy()->saveCurrentFilter();
1943
        $form->addButton($W->SubmitButton()
1944
            ->setAjaxAction($confirmedAction)
0 ignored issues
show
Bug introduced by
$confirmedAction of type true is incompatible with the type Widget_Action|null expected by parameter $action of Widget_Widget::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1944
            ->setAjaxAction(/** @scrutinizer ignore-type */ $confirmedAction)
Loading history...
1945
            ->setLabel($App->translate('Save')));
1946
        
1947
        $page->addItem($form);
1948
        
1949
        return $page;
1950
    }
1951
    
1952
    public function manageFilters()
1953
    {
1954
        $App = $this->App();
1955
        $Ui = $App->Ui();
1956
        $W = bab_Widgets();
1957
        $page = $Ui->Page();
1958
        
1959
        $page->setTitle($App->translate('Manage filters'));
1960
        
1961
        $filtersBox = $W->VBoxItems();
1962
        
1963
        $page->addItem($filtersBox);
1964
        
1965
        $filterNames = $this->getFilterNames();
1966
        foreach ($filterNames as $filterName){
1967
            $filter = $W->getUserConfiguration($this->getModelViewDefaultId() . '/filters/' . $filterName, 'widgets', false);
1968
            
1969
            $filterBox = $W->HBoxItems()
1970
                ->setVerticalAlign('middle')
1971
                ->setSizePolicy('widget-actions-target widget-list-element');
1972
            $filterBox->addItem($W->VBoxItems($W->Label($filterName)
1973
                ->addClass('widget-strong'), $W->Label($filter['description']))
1974
                ->setSizePolicy('widget-90pc'));
1975
            $filterBox->addItem($W->HBoxItems($W->Link('', $this->proxy()
1976
                ->editFilter($filterName))
1977
                ->setOpenMode(WidgetLink::OPEN_DIALOG_AND_RELOAD)
1978
                ->addClass('icon', \Func_Icons::ACTIONS_DOCUMENT_EDIT), $W->Link('', $this->proxy()
1979
                ->confirmDeleteFilter($filterName))
1980
                ->setOpenMode(WidgetLink::OPEN_DIALOG_AND_RELOAD)
1981
                ->addClass('icon', \Func_Icons::ACTIONS_EDIT_DELETE)
1982
                ->setDialogClass('box red'))
1983
                ->setSizePolicy('widget-10pc')
1984
                ->addClass('widget-actions', \Func_Icons::ICON_LEFT_16));
1985
            $filtersBox->addItem($filterBox);
1986
        }
1987
        
1988
        $page->setReloadAction($this->proxy()
1989
            ->manageFilters());
1990
        
1991
        return $page;
1992
    }
1993
    
1994
    /**
1995
     * Display a dialog to propose deleting a view filter.
1996
     *
1997
     * @param string $name
1998
     * @return AppPage
1999
     */
2000
    public function confirmDeleteFilter($name)
2001
    {
2002
        $W = bab_Widgets();
2003
        $App = $this->App();
2004
        $Ui = $App->Ui();
2005
        
2006
        $filter = $W->getUserConfiguration($this->getModelViewDefaultId() . '/filters/' . $name, 'widgets', false);
2007
        
2008
        $page = $Ui->Page();
2009
        
2010
        $page->addClass('crm-page-editor');
2011
        $page->setTitle($App->translate('Delete filter'));
2012
        
2013
        $form = new AppEditor($App);
2014
        
2015
        $form->addItem($W->Html(bab_toHtml($filter['description'])));
2016
        
2017
        $form->setHiddenValue('name', $name);
2018
        
2019
        $confirmedAction = $this->proxy()->deleteFilter();
2020
        $form->addButton($W->SubmitButton()
2021
            ->setAjaxAction($confirmedAction)
0 ignored issues
show
Bug introduced by
$confirmedAction of type true is incompatible with the type Widget_Action|null expected by parameter $action of Widget_Widget::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2021
            ->setAjaxAction(/** @scrutinizer ignore-type */ $confirmedAction)
Loading history...
2022
            ->setLabel($App->translate('Delete')));
2023
        
2024
        $page->addItem($form);
2025
        
2026
        return $page;
2027
    }
2028
    
2029
    /**
2030
     * @param string $name
2031
     */
2032
    public function deleteFilter($name = null)
2033
    {
2034
        $this->requireDeleteMethod();
2035
        
2036
        $W = bab_Widgets();
2037
        $W->deleteUserConfiguration($this->getModelViewDefaultId() . '/filters/' . $name, 'widgets', false);
2038
        
2039
        return true;
2040
    }
2041
    
2042
    public function setHighlightedRecords($ids = array())
2043
    {
2044
        $modelView = $this->modelView();
2045
        $modelView->setHighlightedRows($ids);
2046
        
2047
        $this->addReloadSelector('.depends-' . $modelView->getId() . '-HighlightedRecords');
2048
        
2049
        return true;
2050
    }
2051
    
2052
    public function clearHighlightedRecords()
2053
    {
2054
        $modelView = $this->modelView();
2055
        $modelView->clearHighlightedRows();
2056
        
2057
        $this->addReloadSelector('.depends-' . $modelView->getId() . '-HighlightedRecords');
2058
        
2059
        return true;
2060
    }
2061
    
2062
    public function previewHighlightedRecords($view = '')
2063
    {
2064
        $W = bab_Widgets();
2065
        $App = $this->App();
2066
        
2067
        $modelView = $this->modelView();
2068
        
2069
        $highlightedRows = $modelView->getHighlightedRows();
2070
        
2071
        $recordSet = $this->getRecordSet();
2072
        $records = $recordSet->select($recordSet->id->in($highlightedRows));
2073
        $box = $W->VBoxItems();
2074
        
2075
        $isComponent = false;
2076
        if($component = $App->getCurrentComponent()){
2077
            $Ui = $component->ui();
2078
            $viewClassname = 'FullFrame';
2079
            $isComponent = true;
2080
        }
2081
        else{
2082
            $Ui = $App->Ui();
2083
            $recordClassname = $this->getRecordClassName();
2084
            $viewClassname = $recordClassname . 'FullFrame';
2085
        }
2086
        
2087
        if($records->count() > 0){
2088
            $box->addItem($W->Link('', $this->proxy()
0 ignored issues
show
Bug introduced by
$this->proxy()->clearHighlightedRecords() of type true is incompatible with the type Widget_Action|bab_url|string expected by parameter $url of Func_Widgets::Link(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2088
            $box->addItem($W->Link('', /** @scrutinizer ignore-type */ $this->proxy()
Loading history...
2089
                ->clearHighlightedRecords())
2090
                ->setAjaxAction(null, false)
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type Widget_Item|array|string expected by parameter $reloadItem of Widget_Widget::setAjaxAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2090
                ->setAjaxAction(null, /** @scrutinizer ignore-type */ false)
Loading history...
2091
                ->addClass('icon', \Func_Icons::ACTIONS_ARROW_RIGHT_DOUBLE, "app_closeHighlightButton")
2092
                ->setSizePolicy(\Func_Icons::ICON_LEFT_32 . ' pull-right'));
2093
            
2094
            foreach ($records as $record){
2095
                
2096
                if($isComponent){
2097
                    $fullFrame = $Ui->$viewClassname($record);
2098
                    if(method_exists($record, "getBlueprint")){
2099
                        $view = $record->getBlueprint();
2100
                    }
2101
                    $fullFrame->setView($view);
2102
                }
2103
                else{
2104
                    $fullFrame = $Ui->$viewClassname($record->id, $view);
2105
                }
2106
                
2107
                $box->addItem($fullFrame);
2108
            }
2109
            $box->addClass('box', 'shadow');
2110
        }
2111
        
2112
        $box->addClass('depends-' . $modelView->getId() . '-HighlightedRecords');
2113
        $box->setReloadAction($this->proxy()
0 ignored issues
show
Bug introduced by
$this->proxy()->previewHighlightedRecords($view) of type Widget_VBoxLayout is incompatible with the type Widget_Action expected by parameter $reloadAction of Widget_Item::setReloadAction(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2113
        $box->setReloadAction(/** @scrutinizer ignore-type */ $this->proxy()
Loading history...
2114
            ->previewHighlightedRecords($view));
2115
        return $box;
2116
    }
2117
2118
    public function search($q = null){
2119
        session_write_close();
2120
        $set = $this->getRecordSet();
2121
        $collection = new WidgetSelect2OptionsCollection();
2122
        if($q == null || strlen($q) <= 1){
2123
            $collection->addOption(
2124
                new WidgetSelect2Option(0,$this->App()->translate("Keyword too small"))
2125
            );
2126
            header("Content-type: application/json; charset=utf-8");
2127
            echo $collection->output();
2128
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
2129
        }
2130
        $field = $set->getDisplayNameField();
2131
        $field = $field->getName();
2132
        $records = $set->select(
2133
            $set->all(
2134
                $set->$field->contains($q)
2135
            )
2136
        );
2137
        foreach($records as $r){
2138
            $collection->addOption(
2139
                new WidgetSelect2Option($r->id, $r->$field)
2140
            );
2141
        }
2142
    
2143
        header("Content-type: application/json; charset=utf-8");
2144
	    echo $collection->output();
2145
	    die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
2146
    }
2147
}
2148