Completed
Push — master ( e66c58...0a0a0f )
by Daniel
9s
created

ColumnFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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
        $cell = new Cell();
27
        $cell->context = $data;
28
29
        $layers = $this->resolveLayers($column);
30
        $options = $this->resolveOptions($layers, $columnName, $options);
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($gridContext, $options['column_name'], $options['sort_field']);
45
    }
46
47
    private function resolveOptions(array $layers, $columnName, array $options)
48
    {
49
        $resolver = new OptionsResolver();
50
        $resolver->setDefault('column_name', $columnName);
51
        $resolver->setDefault('sort_field', null);
52
53
        foreach ($layers as $column) {
54
            $column->configureOptions($resolver);
55
        }
56
57
        return $resolver->resolve($options);
58
    }
59
60
    private function resolveLayers(ColumnInterface $column)
61
    {
62
        $layers = [$column];
63
        $seen = [spl_object_hash($column) => true];
64
65
        while (null !== $parentType = $column->getParent()) {
66
            $parent = $this->registry->get($parentType);
67
68
            if (isset($seen[spl_object_hash($parent)])) {
69
                throw new \RuntimeException(sprintf(
70
                    'Circular reference detected on class "%s"',
71
                    get_class($parent)
72
                ));
73
            }
74
75
            $layers[] = $parent;
76
            $column = $parent;
77
        }
78
79
        return array_reverse($layers);
80
    }
81
}
82