Completed
Pull Request — master (#129)
by
unknown
03:00
created

GridBuilder::updateDataCollection()   C

Complexity

Conditions 7
Paths 15

Size

Total Lines 28
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 28
ccs 0
cts 28
cp 0
rs 6.7272
cc 7
eloc 20
nc 15
nop 1
crap 56
1
<?php
2
3
namespace eXpansion\Framework\Core\Model\Gui\Grid;
4
5
use eXpansion\Framework\Core\Model\Gui\Factory\LineFactory;
6
use eXpansion\Framework\Core\Model\Gui\Factory\PagerFactory;
7
use eXpansion\Framework\Core\Model\Gui\Factory\TitleLineFactory;
8
use eXpansion\Framework\Core\Model\Gui\Grid\Column\AbstractColumn;
9
use eXpansion\Framework\Core\Model\Gui\Grid\Column\ActionColumn;
10
use eXpansion\Framework\Core\Model\Gui\Grid\Column\InputColumn;
11
use eXpansion\Framework\Core\Model\Gui\Grid\Column\TextColumn;
12
use eXpansion\Framework\Core\Model\Gui\ManialinkInterface;
13
use eXpansion\Framework\Core\Plugins\Gui\ActionFactory;
14
use eXpansion\Framework\Core\Plugins\Gui\ManialinkFactory;
15
use eXpansion\Framework\Gui\Ui\Factory;
16
use FML\Controls\Frame;
17
use FML\Types\Renderable;
18
19
20
/**
21
 * Class GridBuilder
22
 *
23
 * @package eXpansion\Framework\Core\Model\Gui\Grid;
24
 * @author  oliver de Cramer <[email protected]>
25
 */
26
class GridBuilder
27
{
28
29
    /** @var  ActionFactory */
30
    protected $actionFactory;
31
32
    /** @var TitleLineFactory */
33
    protected $titleLineFactory;
34
35
    /** @var LineFactory */
36
    protected $lineFactory;
37
38
    /** @var PagerFactory */
39
    protected $pagerFactory;
40
41
    /** @var Factory */
42
    protected $uiFactory;
43
44
    /** @var DataCollectionInterface */
45
    protected $dataCollection;
46
47
    /** @var ManialinkInterface */
48
    protected $manialink;
49
50
    /** @var ManialinkFactory */
51
    protected $manialinkFactory;
52
53
    /** @var AbstractColumn[] */
54
    protected $columns;
55
56
    /** @var  float */
57
    protected $totalWidthCoefficency = 0.;
58
59
    /** @var int */
60
    protected $currentPage = 1;
61
62
    /** @var string */
63
    protected $pageKey;
64
65
    /** @var string */
66
    protected $actionPreviousPage;
67
    /** @var string */
68
    protected $actionNextPage;
69
    /** @var string */
70
    protected $actionLastPage;
71
    /** @var string */
72
    protected $actionFirstPage;
73
    /** @var  string */
74
    protected $actionGotoPage;
75
    /** @var string[] */
76
    protected $temporaryActions = [];
77
78
    /** @var array */
79
    protected $temporaryEntries = [];
80
81
82
    /**
83
     * GridBuilder constructor.
84
     *
85
     * @param ActionFactory $actionFactory
86
     * @param LineFactory $lineFactory
87
     * @param TitleLineFactory $titleLineFactory
88
     * @param PagerFactory $pagerFactory
89
     */
90 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
91
        ActionFactory $actionFactory,
92
        LineFactory $lineFactory,
93
        TitleLineFactory $titleLineFactory,
94
        PagerFactory $pagerFactory,
95
        Factory $uiFactory
96
    ) {
97
        $this->actionFactory = $actionFactory;
98
        $this->titleLineFactory = $titleLineFactory;
99
        $this->lineFactory = $lineFactory;
100
        $this->pagerFactory = $pagerFactory;
101
        $this->uiFactory = $uiFactory;
102
103
        $this->pageKey = "key_".spl_object_hash($this);
104
    }
105
106
    /**
107
     * Set the data collection.
108
     *
109
     * @param DataCollectionInterface $dataCollection
110
     *
111
     * @return $this
112
     */
113
    public function setDataCollection(DataCollectionInterface $dataCollection)
114
    {
115
        $this->dataCollection = $dataCollection;
116
117
        return $this;
118
    }
119
120
    /**
121
     * Set the manialink the content is generated for.
122
     *
123
     * @param ManialinkInterface $manialink
124
     *
125
     * @return $this
126
     */
127
    public function setManialink(ManialinkInterface $manialink)
128
    {
129
        $this->manialink = $manialink;
130
131
        $this->actionFirstPage = $this->actionFactory
132
            ->createManialinkAction($manialink, array($this, 'goToFirstPage'), []);
133
        $this->actionPreviousPage = $this->actionFactory
134
            ->createManialinkAction($manialink, array($this, 'goToPreviousPage'), []);
135
        $this->actionNextPage = $this->actionFactory
136
            ->createManialinkAction($manialink, array($this, 'goToNextPage'), []);
137
        $this->actionLastPage = $this->actionFactory
138
            ->createManialinkAction($manialink, array($this, 'goToLastPage'), []);
139
        $this->actionGotoPage = $this->actionFactory
140
            ->createManialinkAction($manialink, array($this, 'goToPage'), []);
141
142
        return $this;
143
    }
144
145
    /**
146
     * Set the manialink factory responsible with the manialink.
147
     *
148
     * @param ManialinkFactory $manialinkFactory
149
     *
150
     * @return $this
151
     */
152
    public function setManialinkFactory($manialinkFactory)
153
    {
154
        $this->manialinkFactory = $manialinkFactory;
155
156
        return $this;
157
    }
158
159
    /**
160
     * @param      string $key
161
     * @param      string $name
162
     * @param      integer $widthCoefficiency
163
     * @param bool $sortable
164
     * @param bool $translatable
165
     *
166
     * @return $this
167
     */
168
    public function addTextColumn($key, $name, $widthCoefficiency, $sortable = false, $translatable = false)
169
    {
170
        $this->columns[] = new TextColumn($key, $name, $widthCoefficiency, $sortable, $translatable);
171
172
        return $this;
173
    }
174
175
    /**
176
     * @param      string $key
177
     * @param      string $name
178
     * @param      integer $widthCoefficiency
179
     * @param bool $sortable
0 ignored issues
show
Bug introduced by
There is no parameter named $sortable. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
180
     * @param bool $translatable
0 ignored issues
show
Bug introduced by
There is no parameter named $translatable. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
181
     *
182
     * @return $this
183
     */
184
    public function addInputColumn($key, $name, $widthCoefficiency)
185
    {
186
        $this->columns[] = new InputColumn($key, $name, $widthCoefficiency);
187
188
        return $this;
189
    }
190
191
192
    /**
193
     * Add an action into a column.
194
     *
195
     * @param string $key
196
     * @param string $name
197
     * @param integer $widthCoefficiency
198
     * @param $action
199
     * @param Renderable $renderer
200
     *
201
     * @return $this
202
     */
203
    public function addActionColumn($key, $name, $widthCoefficiency, $action, $renderer)
204
    {
205
        $this->columns[] = new ActionColumn($key, $name, $widthCoefficiency, $action, $renderer);
206
207
        return $this;
208
    }
209
210
    /**
211
     * Remove all columns.
212
     */
213
    public function resetColumns()
214
    {
215
        $this->columns = [];
216
        $this->totalWidthCoefficency = 0.;
217
    }
218
219
    /**
220
     * Build a grid.
221
     *
222
     * @param double $width
223
     * @param double $height
224
     *
225
     * @return Frame
226
     */
227
    public function build($width, $height)
228
    {
229
        foreach ($this->temporaryActions as $action) {
230
            $this->actionFactory->destroyAction($action);
231
        }
232
233
        $lineHeight = 5 + 0.5;
234
235
236
        $frame = new Frame();
237
        $frame->setPosition(0, 0);
238
        $frame->setSize($width, $height);
239
240
        $posY = 0.;
241
        $tooltip = $this->uiFactory->createTooltip();
242
        $frame->addChild($tooltip);
243
244
        // Generating headers.
245
        $data = [];
246
        foreach ($this->columns as $columnData) {
247
            $action = null;
248
            $sort = "";
249
            if ($columnData->getSortable() && $columnData->getSortColumn()) {
250
                $sort = $columnData->getSortDirection();
251
252
            }
253
            if ($columnData->getSortable()) {
254
                $action = $this->actionFactory->createManialinkAction(
255
                    $this->manialink,
256
                    [$this, 'sortColumn'],
257
                    ["key" => $columnData->getKey()]);
258
            }
259
260
            $data[] = [
261
                'title' => $columnData->getName(),
262
                'width' => $columnData->getWidthCoeficiency(),
263
                'translatable' => true,
264
                'sort' => $sort,
265
                'action' => $action,
266
            ];
267
        }
268
269
        $frame->addChild($this->titleLineFactory->create($frame->getWidth(), $data));
270
        $posY -= $lineHeight + 1;
271
272
        /*
273
         * Display the main content.
274
         */
275
        $this->dataCollection->setPageSize(floor(($frame->getHeight() + $posY - $lineHeight - 2) / $lineHeight));
276
277
        $lines = $this->dataCollection->getData($this->currentPage);
278
        $idx = 0;
279
        foreach ($lines as $i => $lineData) {
280
            $data = [];
281
            foreach ($this->columns as $columnData) {
282
                if ($columnData instanceof TextColumn) {
283
                    $data[] = [
284
                        'text' => $this->dataCollection->getLineData($lineData, $columnData->getKey()),
285
                        'width' => $columnData->getWidthCoeficiency(),
286
                        'translatable' => $columnData->getTranslatable(),
287
                    ];
288
                } elseif ($columnData instanceof ActionColumn) {
289
                    $action = $this->actionFactory
290
                        ->createManialinkAction($this->manialink, $columnData->getCallable(), $lineData);
291
                    $this->temporaryActions[] = $action;
292
                    $data[] = [
293
                        'renderer' => clone $columnData->getRenderer(),
294
                        'width' => $columnData->getWidthCoeficiency(),
295
                        'action' => $action,
296
                    ];
297
                } elseif ($columnData instanceof InputColumn) {
298
                    $value = $this->dataCollection->getLineData($lineData, $columnData->getKey());
299
300
                    $data[] = [
301
                        'input' => $value,
302
                        'index' => $i,
303
                        'tooltip' => $tooltip,
304
                        'width' => $columnData->getWidthCoeficiency(),
305
                    ];
306
                }
307
            }
308
            $line = $this->lineFactory->create($frame->getWidth(), $data, $idx++);
309
            $line->setPosition(0, $posY);
310
            $frame->addChild($line);
311
            $posY -= $lineHeight;
312
        }
313
314
        /*
315
         * Handle the pager.
316
         */
317
        $posY = ($frame->getHeight() - 9) * -1;
318
        $pager = $this->pagerFactory->create(
319
            $frame->getWidth(),
320
            $this->currentPage,
321
            $this->dataCollection->getLastPageNumber(),
322
            $this->actionFirstPage,
323
            $this->actionPreviousPage,
324
            $this->actionNextPage,
325
            $this->actionLastPage,
326
            $this->actionGotoPage
327
        );
328
        $pager->setPosition(($frame->getWidth() - $pager->getWidth()) / 2, $posY);
329
        $frame->addChild($pager);
330
331
        return $frame;
332
    }
333
334
    /**
335
     * Action callback to go to the first page.
336
     */
337
    public function goToFirstPage($login = null, $entries = [])
338
    {
339
        $this->updateDataCollection($entries);
340
        $this->changePage(1);
341
    }
342
343
    /**
344
     * Action callback to go to the previous page.
345
     */
346
    public function goToPreviousPage($login = null, $entries = [])
347
    {
348
        $this->updateDataCollection($entries);
349
        if ($this->currentPage - 1 >= 1) {
350
            $this->changePage($this->currentPage - 1);
351
        }
352
    }
353
354
    /**
355
     * Action callback to go to the next page.
356
     */
357
    public function goToNextPage($login = null, $entries = [])
358
    {
359
        $this->updateDataCollection($entries);
360
        if ($this->currentPage + 1 <= $this->dataCollection->getLastPageNumber()) {
361
            $this->changePage($this->currentPage + 1);
362
        }
363
    }
364
365
    public function goToPage($login = null, $entries = [])
366
    {
367
        if (array_key_exists("pager_gotopage", $entries)) {
368
            if (is_numeric($entries['pager_gotopage'])) {
369
                $page = (int)$entries['pager_gotopage'];
370
371
                $this->updateDataCollection($entries);
372
                if (($page >= 1) && ($page <= $this->dataCollection->getLastPageNumber())) {
373
                    $this->changePage($page);
374
                }
375
            }
376
        }
377
    }
378
379
380
    /**
381
     * Action callback to go to the last page.
382
     */
383
    public function goToLastPage($login = null, $entries = [])
384
    {
385
        $this->updateDataCollection($entries);
386
        $this->changePage($this->dataCollection->getLastPageNumber());
387
    }
388
389
    /**
390
     * Updates dataCollection from entries.
391
     */
392
    public function updateDataCollection($entries)
393
    {
394
        $process = false;
395
        $data = [];
396
        $start = ($this->currentPage - 1) * $this->dataCollection->getPageSize();
397
        foreach ($entries as $key => $value) {
398
            if (substr($key, 0, 6) == "entry_") {
399
                $array = explode("_", str_replace("entry_", "", $key));
400
                setType($value, $array[1]);
401
                $data[$array[0]] = $value;
402
                $process = true;
403
            }
404
        }
405
        if ($process) {
406
            $lines = $this->dataCollection->getData($this->currentPage);
407
            $counter = 0;
408
            foreach ($lines as $i => $lineData) {
409
                $newData = $lineData;
410
                foreach ($this->columns as $columnData) {
411
                    if ($columnData instanceof InputColumn) {
412
                        $newData[$columnData->getKey()] = $data[$counter];
413
                    }
414
                }
415
                $this->dataCollection->setDataByIndex($start + $counter, $newData);
416
                $counter++;
417
            }
418
        }
419
    }
420
421
    /** get dataCollection
422
     *
423
     * @return DataCollectionInterface
424
     */
425
    public function getDataCollection()
426
    {
427
        return $this->dataCollection;
428
    }
429
430
    /**
431
     * Handle page change & refresh user window.
432
     *
433
     * @param integer $page
434
     */
435
    protected function changePage($page)
436
    {
437
        $this->currentPage = $page;
438
        $this->manialinkFactory->update($this->manialink->getUserGroup());
439
    }
440
441
    public function sortColumn($login, $entries, $args)
442
    {
443
        foreach ($this->columns as $columnData) {
444
            if ($columnData->getKey() == $args['key']) {
445
                if ($columnData->getSortColumn()) {
446
                    $columnData->toggleSortDirection();
447
                } else {
448
                    $columnData->setSortColumn(true);
449
                }
450
                $this->dataCollection->setFiltersAndSort([], $columnData->getKey(), $columnData->getSortDirection());
451
            } else {
452
                $columnData->setSortColumn(false);
453
            }
454
        }
455
456
        $this->manialinkFactory->update($this->manialink->getUserGroup());
457
    }
458
}
459