Completed
Pull Request — master (#129)
by De Cramer
02:40
created

GridBuilder::updateDataCollection()   C

Complexity

Conditions 7
Paths 15

Size

Total Lines 28
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 21.5206

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 6.7272
c 0
b 0
f 0
ccs 7
cts 21
cp 0.3333
cc 7
eloc 20
nc 15
nop 1
crap 21.5206
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 5 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 5
        $this->actionFactory = $actionFactory;
98 5
        $this->titleLineFactory = $titleLineFactory;
99 5
        $this->lineFactory = $lineFactory;
100 5
        $this->pagerFactory = $pagerFactory;
101 5
        $this->uiFactory = $uiFactory;
102
103 5
        $this->pageKey = "key_".spl_object_hash($this);
104 5
    }
105
106
    /**
107
     * Set the data collection.
108
     *
109
     * @param DataCollectionInterface $dataCollection
110
     *
111
     * @return $this
112
     */
113 5
    public function setDataCollection(DataCollectionInterface $dataCollection)
114
    {
115 5
        $this->dataCollection = $dataCollection;
116
117 5
        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 5
    public function setManialink(ManialinkInterface $manialink)
128
    {
129 5
        $this->manialink = $manialink;
130
131 5
        $this->actionFirstPage = $this->actionFactory
132 5
            ->createManialinkAction($manialink, array($this, 'goToFirstPage'), []);
133 5
        $this->actionPreviousPage = $this->actionFactory
134 5
            ->createManialinkAction($manialink, array($this, 'goToPreviousPage'), []);
135 5
        $this->actionNextPage = $this->actionFactory
136 5
            ->createManialinkAction($manialink, array($this, 'goToNextPage'), []);
137 5
        $this->actionLastPage = $this->actionFactory
138 5
            ->createManialinkAction($manialink, array($this, 'goToLastPage'), []);
139 5
        $this->actionGotoPage = $this->actionFactory
140 5
            ->createManialinkAction($manialink, array($this, 'goToPage'), []);
141
142 5
        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 5
    public function setManialinkFactory($manialinkFactory)
153
    {
154 5
        $this->manialinkFactory = $manialinkFactory;
155
156 5
        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 5
    public function addTextColumn($key, $name, $widthCoefficiency, $sortable = false, $translatable = false)
169
    {
170 5
        $this->columns[] = new TextColumn($key, $name, $widthCoefficiency, $sortable, $translatable);
171
172 5
        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 5
    public function addActionColumn($key, $name, $widthCoefficiency, $action, $renderer)
204
    {
205 5
        $this->columns[] = new ActionColumn($key, $name, $widthCoefficiency, $action, $renderer);
206
207 5
        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 5
    public function build($width, $height)
228
    {
229 5
        foreach ($this->temporaryActions as $action) {
230 1
            $this->actionFactory->destroyAction($action);
231
        }
232
233 5
        $lineHeight = 5 + 0.5;
234
235
236 5
        $frame = new Frame();
237 5
        $frame->setPosition(0, 0);
238 5
        $frame->setSize($width, $height);
239
240 5
        $posY = 0.;
241 5
        $tooltip = $this->uiFactory->createTooltip();
242 5
        $frame->addChild($tooltip);
243
244
        // Generating headers.
245 5
        $data = [];
246 5
        foreach ($this->columns as $columnData) {
247 5
            $action = null;
248 5
            $sort = "";
249 5
            if ($columnData->getSortable() && $columnData->getSortColumn()) {
250
                $sort = $columnData->getSortDirection();
251
252
            }
253 5
            if ($columnData->getSortable()) {
254
                $action = $this->actionFactory->createManialinkAction(
255
                    $this->manialink,
256
                    [$this, 'sortColumn'],
257
                    ["key" => $columnData->getKey()]);
258
            }
259
260 5
            $data[] = [
261 5
                'title' => $columnData->getName(),
262 5
                'width' => $columnData->getWidthCoeficiency(),
263
                'translatable' => true,
264 5
                'sort' => $sort,
265 5
                'action' => $action,
266
            ];
267
        }
268
269 5
        $frame->addChild($this->titleLineFactory->create($frame->getWidth(), $data));
270 5
        $posY -= $lineHeight + 1;
271
272
        /*
273
         * Display the main content.
274
         */
275 5
        $this->dataCollection->setPageSize(floor(($frame->getHeight() + $posY - $lineHeight - 2) / $lineHeight));
276
277 5
        $lines = $this->dataCollection->getData($this->currentPage);
278 3
        $idx = 0;
279 3
        foreach ($lines as $i => $lineData) {
280 3
            $data = [];
281 3
            foreach ($this->columns as $columnData) {
282 3
                if ($columnData instanceof TextColumn) {
283 3
                    $data[] = [
284 3
                        'text' => $this->dataCollection->getLineData($lineData, $columnData->getKey()),
285 3
                        'width' => $columnData->getWidthCoeficiency(),
286 3
                        'translatable' => $columnData->getTranslatable(),
287
                    ];
288 3
                } elseif ($columnData instanceof ActionColumn) {
289 3
                    $action = $this->actionFactory
290 3
                        ->createManialinkAction($this->manialink, $columnData->getCallable(), $lineData);
291 3
                    $this->temporaryActions[] = $action;
292 3
                    $data[] = [
293 3
                        'renderer' => clone $columnData->getRenderer(),
294 3
                        'width' => $columnData->getWidthCoeficiency(),
295 3
                        '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 3
                        'width' => $columnData->getWidthCoeficiency(),
305
                    ];
306
                }
307
            }
308 3
            $line = $this->lineFactory->create($frame->getWidth(), $data, $idx++);
309 3
            $line->setPosition(0, $posY);
310 3
            $frame->addChild($line);
311 3
            $posY -= $lineHeight;
312
        }
313
314
        /*
315
         * Handle the pager.
316
         */
317 3
        $posY = ($frame->getHeight() - 9) * -1;
318 3
        $pager = $this->pagerFactory->create(
319 3
            $frame->getWidth(),
320 3
            $this->currentPage,
321 3
            $this->dataCollection->getLastPageNumber(),
322 3
            $this->actionFirstPage,
323 3
            $this->actionPreviousPage,
324 3
            $this->actionNextPage,
325 3
            $this->actionLastPage,
326 3
            $this->actionGotoPage
327
        );
328 3
        $pager->setPosition(($frame->getWidth() - $pager->getWidth()) / 2, $posY);
329 3
        $frame->addChild($pager);
330
331 3
        return $frame;
332
    }
333
334
    /**
335
     * Action callback to go to the first page.
336
     */
337 1
    public function goToFirstPage($login = null, $entries = [])
338
    {
339 1
        $this->updateDataCollection($entries);
340 1
        $this->changePage(1);
341 1
    }
342
343
    /**
344
     * Action callback to go to the previous page.
345
     */
346 1
    public function goToPreviousPage($login = null, $entries = [])
347
    {
348 1
        $this->updateDataCollection($entries);
349 1
        if ($this->currentPage - 1 >= 1) {
350 1
            $this->changePage($this->currentPage - 1);
351
        }
352 1
    }
353
354
    /**
355
     * Action callback to go to the next page.
356
     */
357 3
    public function goToNextPage($login = null, $entries = [])
358
    {
359 3
        $this->updateDataCollection($entries);
360 3
        if ($this->currentPage + 1 <= $this->dataCollection->getLastPageNumber()) {
361 3
            $this->changePage($this->currentPage + 1);
362
        }
363 3
    }
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 1
    public function goToLastPage($login = null, $entries = [])
384
    {
385 1
        $this->updateDataCollection($entries);
386 1
        $this->changePage($this->dataCollection->getLastPageNumber());
387 1
    }
388
389
    /**
390
     * Updates dataCollection from entries.
391
     */
392 4
    public function updateDataCollection($entries)
393
    {
394 4
        $process = false;
395 4
        $data = [];
396 4
        $start = ($this->currentPage - 1) * $this->dataCollection->getPageSize();
397 4
        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 4
        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 4
    }
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 4
    protected function changePage($page)
436
    {
437 4
        $this->currentPage = $page;
438 4
        $this->manialinkFactory->update($this->manialink->getUserGroup());
439 4
    }
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