Completed
Pull Request — master (#127)
by De Cramer
04:50
created

GridBuilder   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 407
Duplicated Lines 3.69 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 81.53%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 36
lcom 1
cbo 13
dl 15
loc 407
ccs 128
cts 157
cp 0.8153
rs 8.8
c 1
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 15 15 1
A setDataCollection() 0 6 1
A setManialink() 0 15 1
A setManialinkFactory() 0 6 1
A addTextColumn() 0 6 1
A addInputColumn() 0 6 1
A addActionColumn() 0 6 1
A resetColumns() 0 5 1
C build() 0 105 11
A goToFirstPage() 0 5 1
A goToPreviousPage() 0 7 2
A goToNextPage() 0 7 2
A goToLastPage() 0 5 1
B updateDataCollection() 0 22 5
A getDataCollection() 0 4 1
A changePage() 0 5 1
A sortColumn() 0 17 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
    /** @var  ActionFactory */
29
    protected $actionFactory;
30
31
    /** @var TitleLineFactory */
32
    protected $titleLineFactory;
33
34
    /** @var LineFactory */
35
    protected $lineFactory;
36
37
    /** @var PagerFactory */
38
    protected $pagerFactory;
39
40
    /** @var Factory */
41
    protected $uiFactory;
42
43
    /** @var DataCollectionInterface */
44
    protected $dataCollection;
45
46
    /** @var ManialinkInterface */
47
    protected $manialink;
48
49
    /** @var ManialinkFactory */
50
    protected $manialinkFactory;
51
52
    /** @var AbstractColumn[] */
53
    protected $columns;
54
55
    /** @var  float */
56
    protected $totalWidthCoefficency = 0.;
57
58
    /** @var int */
59
    protected $currentPage = 1;
60
61
    /** @var string */
62
    protected $pageKey;
63
64
    /** @var string */
65
    protected $actionPreviousPage;
66
    /** @var string */
67
    protected $actionNextPage;
68
    /** @var string */
69
    protected $actionLastPage;
70
    /** @var string */
71
    protected $actionFirstPage;
72
73
    /** @var string[] */
74
    protected $temporaryActions = [];
75
76
    /** @var array */
77
    protected $temporaryEntries = [];
78
79
80
    /**
81
     * GridBuilder constructor.
82
     *
83
     * @param ActionFactory $actionFactory
84
     * @param LineFactory $lineFactory
85
     * @param TitleLineFactory $titleLineFactory
86
     * @param PagerFactory $pagerFactory
87
     */
88 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...
89
        ActionFactory $actionFactory,
90
        LineFactory $lineFactory,
91
        TitleLineFactory $titleLineFactory,
92
        PagerFactory $pagerFactory,
93
        Factory $uiFactory
94
    ) {
95 5
        $this->actionFactory = $actionFactory;
96 5
        $this->titleLineFactory = $titleLineFactory;
97 5
        $this->lineFactory = $lineFactory;
98 5
        $this->pagerFactory = $pagerFactory;
99 5
        $this->uiFactory = $uiFactory;
100
101 5
        $this->pageKey = "key_".spl_object_hash($this);
102 5
    }
103
104
    /**
105
     * Set the data collection.
106
     *
107
     * @param DataCollectionInterface $dataCollection
108
     *
109
     * @return $this
110
     */
111 5
    public function setDataCollection(DataCollectionInterface $dataCollection)
112
    {
113 5
        $this->dataCollection = $dataCollection;
114
115 5
        return $this;
116
    }
117
118
    /**
119
     * Set the manialink the content is generated for.
120
     *
121
     * @param ManialinkInterface $manialink
122
     *
123
     * @return $this
124
     */
125 5
    public function setManialink(ManialinkInterface $manialink)
126
    {
127 5
        $this->manialink = $manialink;
128
129 5
        $this->actionFirstPage = $this->actionFactory
130 5
            ->createManialinkAction($manialink, array($this, 'goToFirstPage'), []);
131 5
        $this->actionPreviousPage = $this->actionFactory
132 5
            ->createManialinkAction($manialink, array($this, 'goToPreviousPage'), []);
133 5
        $this->actionNextPage = $this->actionFactory
134 5
            ->createManialinkAction($manialink, array($this, 'goToNextPage'), []);
135 5
        $this->actionLastPage = $this->actionFactory
136 5
            ->createManialinkAction($manialink, array($this, 'goToLastPage'), []);
137
138 5
        return $this;
139
    }
140
141
    /**
142
     * Set the manialink factory responsible with the manialink.
143
     *
144
     * @param ManialinkFactory $manialinkFactory
145
     *
146
     * @return $this
147
     */
148 5
    public function setManialinkFactory($manialinkFactory)
149
    {
150 5
        $this->manialinkFactory = $manialinkFactory;
151
152 5
        return $this;
153
    }
154
155
    /**
156
     * @param      string $key
157
     * @param      string $name
158
     * @param      integer $widthCoefficiency
159
     * @param bool $sortable
160
     * @param bool $translatable
161
     *
162
     * @return $this
163
     */
164 5
    public function addTextColumn($key, $name, $widthCoefficiency, $sortable = false, $translatable = false)
165
    {
166 5
        $this->columns[] = new TextColumn($key, $name, $widthCoefficiency, $sortable, $translatable);
167
168 5
        return $this;
169
    }
170
171
    /**
172
     * @param      string $key
173
     * @param      string $name
174
     * @param      integer $widthCoefficiency
175
     * @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...
176
     * @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...
177
     *
178
     * @return $this
179
     */
180
    public function addInputColumn($key, $name, $widthCoefficiency)
181
    {
182
        $this->columns[] = new InputColumn($key, $name, $widthCoefficiency);
183
184
        return $this;
185
    }
186
187
188
    /**
189
     * Add an action into a column.
190
     *
191
     * @param string $key
192
     * @param string $name
193
     * @param integer $widthCoefficiency
194
     * @param $action
195
     * @param Renderable $renderer
196
     *
197
     * @return $this
198
     */
199 5
    public function addActionColumn($key, $name, $widthCoefficiency, $action, $renderer)
200
    {
201 5
        $this->columns[] = new ActionColumn($key, $name, $widthCoefficiency, $action, $renderer);
202
203 5
        return $this;
204
    }
205
206
    /**
207
     * Remove all columns.
208
     */
209 1
    public function resetColumns()
210
    {
211 1
        $this->columns = [];
212 1
        $this->totalWidthCoefficency = 0.;
213 1
    }
214
215
    /**
216
     * Build a grid.
217
     *
218
     * @param double $width
219
     * @param double $height
220
     *
221
     * @return Frame
222
     */
223 5
    public function build($width, $height)
224
    {
225 5
        foreach ($this->temporaryActions as $action) {
226 1
            $this->actionFactory->destroyAction($action);
227
        }
228
229 5
        $lineHeight = 5 + 0.5;
230
231
232 5
        $frame = new Frame();
233 5
        $frame->setPosition(0, 0);
234 5
        $frame->setSize($width, $height);
235
236 5
        $posY = 0.;
237 5
        $tooltip = $this->uiFactory->createTooltip();
238 5
        $frame->addChild($tooltip);
239
240
        // Generating headers.
241 5
        $data = [];
242 5
        foreach ($this->columns as $columnData) {
243 5
            $action = null;
244 5
            $sort = "";
245 5
            if ($columnData->getSortable() && $columnData->getSortColumn()) {
246
                $sort = $columnData->getSortDirection();
247
248
            }
249 5
            if ($columnData->getSortable()) {
250
                $action = $this->actionFactory->createManialinkAction(
251
                    $this->manialink,
252
                    [$this, 'sortColumn'],
253
                    ["key" => $columnData->getKey()]);
254
            }
255
256 5
            $data[] = [
257 5
                'title' => $columnData->getName(),
258 5
                'width' => $columnData->getWidthCoeficiency(),
259
                'translatable' => true,
260 5
                'sort' => $sort,
261 5
                'action' => $action,
262
            ];
263
        }
264
265 5
        $frame->addChild($this->titleLineFactory->create($frame->getWidth(), $data));
266 5
        $posY -= $lineHeight + 1;
267
268
        /*
269
         * Display the main content.
270
         */
271 5
        $this->dataCollection->setPageSize(floor(($frame->getHeight() + $posY - $lineHeight - 2) / $lineHeight));
272
273 5
        $lines = $this->dataCollection->getData($this->currentPage);
274 5
        $idx = 0;
275 5
        foreach ($lines as $i => $lineData) {
276 5
            $data = [];
277 5
            foreach ($this->columns as $columnData) {
278 5
                if ($columnData instanceof TextColumn) {
279 5
                    $data[] = [
280 5
                        'text' => $this->dataCollection->getLineData($lineData, $columnData->getKey()),
281 5
                        'width' => $columnData->getWidthCoeficiency(),
282 5
                        'translatable' => $columnData->getTranslatable(),
283
                    ];
284 5
                } elseif ($columnData instanceof ActionColumn) {
285 5
                    $action = $this->actionFactory
286 5
                        ->createManialinkAction($this->manialink, $columnData->getCallable(), $lineData);
287 5
                    $this->temporaryActions[] = $action;
288 5
                    $data[] = [
289 5
                        'renderer' => clone $columnData->getRenderer(),
290 5
                        'width' => $columnData->getWidthCoeficiency(),
291 5
                        'action' => $action,
292
                    ];
293
                } elseif ($columnData instanceof InputColumn) {
294
                    $value = $this->dataCollection->getLineData($lineData, $columnData->getKey());
295
296
                    $data[] = [
297
                        'input' => $value,
298
                        'index' => $i,
299
                        'tooltip' => $tooltip,
300 5
                        'width' => $columnData->getWidthCoeficiency(),
301
                    ];
302
                }
303
            }
304 5
            $line = $this->lineFactory->create($frame->getWidth(), $data, $idx++);
305 5
            $line->setPosition(0, $posY);
306 5
            $frame->addChild($line);
307 5
            $posY -= $lineHeight;
308
        }
309
310
        /*
311
         * Handle the pager.
312
         */
313 5
        $posY = ($frame->getHeight() - 7) * -1;
314 5
        $pager = $this->pagerFactory->create(
315 5
            $frame->getWidth(),
316 5
            $this->currentPage,
317 5
            $this->dataCollection->getLastPageNumber(),
318 5
            $this->actionFirstPage,
319 5
            $this->actionPreviousPage,
320 5
            $this->actionNextPage,
321 5
            $this->actionLastPage
322
        );
323 5
        $pager->setPosition(0, $posY);
324 5
        $frame->addChild($pager);
325
326 5
        return $frame;
327
    }
328
329
    /**
330
     * Action callback to go to the first page.
331
     */
332 1
    public function goToFirstPage($login = null, $entries = [])
333
    {
334 1
        $this->updateDataCollection($entries);
335 1
        $this->changePage(1);
336 1
    }
337
338
    /**
339
     * Action callback to go to the previous page.
340
     */
341 1
    public function goToPreviousPage($login = null, $entries = [])
342
    {
343 1
        $this->updateDataCollection($entries);
344 1
        if ($this->currentPage - 1 >= 1) {
345 1
            $this->changePage($this->currentPage - 1);
346
        }
347 1
    }
348
349
    /**
350
     * Action callback to go to the next page.
351
     */
352 3
    public function goToNextPage($login = null, $entries = [])
353
    {
354 3
        $this->updateDataCollection($entries);
355 3
        if ($this->currentPage + 1 <= $this->dataCollection->getLastPageNumber()) {
356 3
            $this->changePage($this->currentPage + 1);
357
        }
358 3
    }
359
360
    /**
361
     * Action callback to go to the last page.
362
     */
363 1
    public function goToLastPage($login = null, $entries = [])
364
    {
365 1
        $this->updateDataCollection($entries);
366 1
        $this->changePage($this->dataCollection->getLastPageNumber());
367 1
    }
368
369
    /**
370
     * Updates dataCollection from entries.
371
     */
372 4
    public function updateDataCollection($entries)
373
    {
374
375 4
        $data = [];
376 4
        $start = ($this->currentPage - 1) * $this->dataCollection->getPageSize();
377 4
        foreach ($entries as $key => $value) {
378
            $array = explode("_", str_replace("entry_", "", $key));
379
            setType($value, $array[1]);
380
            $data[$array[0]] = $value;
381
        }
382
383 4
        $lines = $this->dataCollection->getData($this->currentPage);
384 4
        foreach ($lines as $i => $lineData) {
385 4
            $newData = $lineData;
386 4
            foreach ($this->columns as $columnData) {
387 4
                if ($columnData instanceof InputColumn) {
388 4
                    $newData[$columnData->getKey()] = $data[$i];
389
                }
390
            }
391 4
            $this->dataCollection->setDataByIndex($start + $i, $newData);
392
        }
393 4
    }
394
395
    /** get dataCollection
396
     *
397
     * @return DataCollectionInterface
398
     */
399
    public function getDataCollection()
400
    {
401
        return $this->dataCollection;
402
    }
403
404
    /**
405
     * Handle page change & refresh user window.
406
     *
407
     * @param integer $page
408
     */
409 4
    protected function changePage($page)
410
    {
411 4
        $this->currentPage = $page;
412 4
        $this->manialinkFactory->update($this->manialink->getUserGroup());
413 4
    }
414
415
    public function sortColumn($login, $entries, $args)
416
    {
417
        foreach ($this->columns as $columnData) {
418
            if ($columnData->getKey() == $args['key']) {
419
                if ($columnData->getSortColumn()) {
420
                    $columnData->toggleSortDirection();
421
                } else {
422
                    $columnData->setSortColumn(true);
423
                }
424
                $this->dataCollection->setFiltersAndSort([], $columnData->getKey(), $columnData->getSortDirection());
425
            } else {
426
                $columnData->setSortColumn(false);
427
            }
428
        }
429
430
        $this->manialinkFactory->update($this->manialink->getUserGroup());
431
    }
432
}
433