ClassFilterBuilder.php 3.85 KB
Newer Older
1
<?php declare(strict_types=1);
2
/*
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
3
4
 * Copyright (C) 2016-2017 IRSTEA
 * All rights reserved.
5
6
7
8
9
10
11
12
13
14
15
16
17
 */

namespace Irstea\PlantUmlBundle\DependencyInjection\Builder;

use Irstea\PlantUmlBundle\Model\Filter\ClassFilter;
use Irstea\PlantUmlBundle\Model\Filter\Composite\AllFilter;
use Irstea\PlantUmlBundle\Model\Filter\DirectoryFilter;
use Irstea\PlantUmlBundle\Model\Filter\NamespaceFilter;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

/**
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
18
 * Description of ClassFilterBuilder.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 */
class ClassFilterBuilder
{
    /**
     * @var ContainerBuilder
     */
    private $container;

    /**
     * @var Reference[]
     */
    private $filters = [];

    /**
     * @var string[]
     */
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
35
    private static $filterClasses = [
36
37
        'classes'     => ClassFilter::class,
        'directories' => DirectoryFilter::class,
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
38
        'namespaces'  => NamespaceFilter::class,
39
40
41
42
43
44
45
46
47
48
49
50
    ];

    /**
     * @param \Irstea\PlantUmlBundle\DependencyInjection\Builder\ContainerBuilder $container
     */
    public function __construct(ContainerBuilder $container)
    {
        $this->container = $container;
    }

    /**
     * @param array $config
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
51
     *
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
     * @return Reference
     */
    public function build(array $config)
    {
        $filters = $this->normalize(array_intersect_key($config, ['include' => true, 'exclude' => true]));
        if ($filters === null) {
            return null;
        }

        $hash = sha1(serialize($filters));
        if (!key_exists($hash, $this->filters)) {
            return $this->filters[$hash] = $this->doBuild("irstea.plant_uml.filters.$hash", $filters);
        }

        return $this->filters[$hash];
    }

    /**
     * @param mixed $data
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
71
     *
72
73
74
75
76
77
78
79
80
     * @return mixed
     */
    protected function normalize($data)
    {
        if ($data === null || $data === []) {
            return null;
        }
        if (is_array($data)) {
            $res = [];
81
            $isList = true;
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
82
            foreach ($data as $k => $v) {
83
84
85
                $normalized = $this->normalize($v);
                if (!empty($normalized)) {
                    $res[$k] = $normalized;
86
87
88
                    if (!is_int($k)) {
                        $isList = false;
                    }
89
90
                }
            }
91
92
93
            if (empty($res)) {
                return null;
            }
94
95
96
97
98
            if ($isList) {
                sort($res);
            } else {
                ksort($res);
            }
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
99

100
            return $res;
101
        }
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
102

103
104
105
106
        return $data;
    }

    /**
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
107
     * @param type  $id
108
     * @param array $config
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
109
     *
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
     * @return Reference
     */
    protected function doBuild($id, array $config)
    {
        $filters = [];

        if (isset($config['include'])) {
            $this->buildSubFilter($filters, "$id.include", $config['include'], false);
        }
        if (isset($config['exclude'])) {
            $this->buildSubFilter($filters, "$id.exclude", $config['exclude'], true);
        }

        if (empty($filters)) {
            return null;
        }

        if (count($filters) === 1) {
            return $filters[0];
        }

        $this->container->setDefinition($id, new Definition(AllFilter::class, [$filters]));
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
132

133
134
135
136
        return new Reference($id);
    }

    /**
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
137
     * @param array  $filters
138
     * @param string $id
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
139
140
     * @param array  $config
     * @param bool   $notFound
141
142
143
144
145
146
147
148
149
150
151
152
153
154
     */
    protected function buildSubFilter(array &$filters, $id, array $config, $notFound)
    {
        foreach (self::$filterClasses as $key => $class) {
            if (!isset($config[$key])) {
                continue;
            }
            $subId = "$id.$key";
            $def = new Definition($class, [$config[$key], $notFound]);
            $this->container->setDefinition($subId, $def);
            $filters[] = new Reference($subId);
        }
    }
}