Completed
Pull Request — master (#74)
by Daniel
02:22 queued 11s
created

ColumnFactory   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 4
dl 0
loc 90
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A createCell() 0 16 2
A createHeader() 0 13 1
B resolveOptions() 0 25 3
A resolveLayers() 0 21 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Psi\Component\Grid;
6
7
use Psi\Component\Grid\View\Cell;
8
use Psi\Component\Grid\View\Header;
9
use Symfony\Component\OptionsResolver\OptionsResolver;
10
11
class ColumnFactory
12
{
13
    private $registry;
14
15
    public function __construct(
16
        ColumnRegistry $registry
17
18
    ) {
19
        $this->registry = $registry;
20
    }
21
22
    public function createCell(string $columnName, string $typeName, $data, array $options): Cell
23
    {
24
        $column = $this->registry->get($typeName);
25
26
        $layers = $this->resolveLayers($column);
27
        $options = $this->resolveOptions($layers, $columnName, $options);
28
29
        $cell = new Cell($options['cell_template']);
30
        $cell->context = $data;
31
32
        foreach ($layers as $column) {
33
            $column->buildCell($cell, $options);
34
        }
35
36
        return $cell;
37
    }
38
39
    public function createHeader(GridContext $gridContext, string $columnName, string $typeName, array $options): Header
40
    {
41
        $column = $this->registry->get($typeName);
42
        $options = $this->resolveOptions($this->resolveLayers($column), $columnName, $options);
43
44
        return new Header(
45
            $gridContext,
46
            $options['column_name'],
47
            $options['label'],
48
            $options['header_template'],
49
            $options['sort_field']
50
        );
51
    }
52
53
    private function resolveOptions(array $layers, $columnName, array $options)
54
    {
55
        // resolve a default template name
56
        // TODO: Put this in a normalize step
57
        $templateColumn = end($layers);
58
        $defaultTemplate = basename(str_replace('\\', '/', get_class($templateColumn)));
59
60
        if (substr($defaultTemplate, -6) === 'Column') {
61
            $defaultTemplate = substr($defaultTemplate, 0, -6);
62
        }
63
64
        $resolver = new OptionsResolver();
65
        $resolver->setDefault('column_name', $columnName);
66
        $resolver->setDefault('sort_field', null);
67
        $resolver->setDefault('label', $columnName);
68
69
        $resolver->setDefault('header_template', $defaultTemplate);
70
        $resolver->setDefault('cell_template', $defaultTemplate);
71
72
        foreach ($layers as $column) {
73
            $column->configureOptions($resolver);
74
        }
75
76
        return $resolver->resolve($options);
77
    }
78
79
    private function resolveLayers(ColumnInterface $column)
80
    {
81
        $layers = [$column];
82
        $seen = [spl_object_hash($column) => true];
83
84
        while (null !== $parentType = $column->getParent()) {
85
            $parent = $this->registry->get($parentType);
86
87
            if (isset($seen[spl_object_hash($parent)])) {
88
                throw new \RuntimeException(sprintf(
89
                    'Circular reference detected on class "%s"',
90
                    get_class($parent)
91
                ));
92
            }
93
94
            $layers[] = $parent;
95
            $column = $parent;
96
        }
97
98
        return array_reverse($layers);
99
    }
100
}
101