ConfigConverter::getManager()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 7
c 1
b 0
f 1
nc 4
nop 2
dl 0
loc 13
ccs 0
cts 11
cp 0
crap 12
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Artprima\QueryFilterBundle\ParamConverter;
4
5
use Artprima\QueryFilterBundle\Exception\InvalidArgumentException;
6
use Artprima\QueryFilterBundle\QueryFilter\Config\ConfigInterface;
7
use Artprima\QueryFilterBundle\Request\Request;
8
use Doctrine\ORM\EntityManager;
9
use Doctrine\Persistence\ManagerRegistry;
10
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
11
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
12
use Symfony\Component\HttpFoundation\Request as HttpRequest;
13
14
class ConfigConverter implements ParamConverterInterface
15
{
16
    /**
17
     * @var ManagerRegistry
18
     */
19
    private $registry;
20
21
    public function __construct(ManagerRegistry $registry = null)
22
    {
23
        $this->registry = $registry;
24
    }
25
26
    private function getOptions(ParamConverter $configuration): array
27
    {
28
        return array_replace(array(
29
            'entity_manager' => null,
30
            'entity_class' => null,
31
            'repository_method' => null,
32
        ), $configuration->getOptions());
33
    }
34
35
    private function getManager($name, $class): EntityManager
36
    {
37
        if (null === $name) {
38
            $result = $this->registry->getManagerForClass($class);
39
        } else {
40
            $result = $this->registry->getManager($name);
41
        }
42
43
        if (!$result instanceof EntityManager) {
44
            throw new InvalidArgumentException(self::class.': expected EntityManager instance. Wrong configuration?');
45
        }
46
47
        return $result;
48
    }
49
50
    /**
51
     * Stores the object in the request.
52
     *
53
     * Usage example:
54
     * @ParamConverter("config", class="AppBundle\QueryFilter\Config\BrandFilterConfig",
55
     *                           converter="query_filter_config_converter",
56
     *                           options={"entity_class": "AppBundle:Brand", "repository_method": "findByOrderBy"})
57
     *
58
     * @param HttpRequest $request The request
59
     * @param ParamConverter $configuration Contains the name, class and options of the object
60
     *
61
     * @return bool    True if the object has been successfully set, else false
62
     * @throws \RuntimeException
63
     */
64
    public function apply(HttpRequest $request, ParamConverter $configuration): bool
65
    {
66
        $options = $this->getOptions($configuration);
67
68
        if (!isset($options['entity_class'])) {
69
            throw new InvalidArgumentException(self::class.': entity_class not provided. Wrong configuration?');
70
        }
71
72
        if (!isset($options['repository_method'])) {
73
            throw new InvalidArgumentException(self::class.': repository_method not provided. Wrong configuration?');
74
        }
75
76
        $configClassName = $configuration->getClass();
77
        $config = new $configClassName();
78
79
        if (!$config instanceof ConfigInterface) {
80
            throw new InvalidArgumentException(self::class.': config is not QueryFilterConfig descendant. Wrong configuration?');
81
        }
82
83
        $config->setRequest(new Request($request));
84
85
        $manager = $this->getManager($options['entity_manager'], $options['entity_class']);
86
        $repo = $manager->getRepository($options['entity_class']);
87
88
        if (!is_callable(array($repo, $options['repository_method']))) {
89
            throw new InvalidArgumentException(self::class.': repository_method is not callable. Wrong configuration?');
90
        }
91
92
        $config->setRepositoryCallback(array($repo, $options['repository_method']));
93
94
        $request->attributes->set($configuration->getName(), $config);
95
96
        return true;
97
    }
98
99
    /**
100
     * Checks if the object is supported.
101
     *
102
     * @param ParamConverter $configuration Should be an instance of ParamConverter
103
     *
104
     * @return bool true if the object is supported, else false
105
     */
106
    public function supports(ParamConverter $configuration): bool
107
    {
108
        // if there is no manager, this means that only Doctrine DBAL is configured
109
        if (null === $this->registry || !count($this->registry->getManagers())) {
110
            return false;
111
        }
112
113
        if (!$configuration->getClass()) {
114
            return false;
115
        }
116
117
        if (!class_exists($configuration->getClass())) {
118
            return false;
119
        }
120
121
        return in_array(ConfigInterface::class, class_implements($configuration->getClass()), true);
122
    }
123
}
124