Completed
Push — master ( d35e44...dacbde )
by Tomasz
04:03
created

ServiceParamConverter::getOptions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 12
ccs 10
cts 10
cp 1
rs 9.4286
cc 2
eloc 9
nc 2
nop 1
crap 2
1
<?php
2
3
/*
4
 * All rights reserved
5
 * Copyright 2015 Gendoria
6
 */
7
8
namespace Gendoria\ParamConverterBundle\Request\ParamConverter;
9
10
use InvalidArgumentException;
11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
12
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
13
use Symfony\Component\DependencyInjection\Container;
14
use Symfony\Component\HttpFoundation\Request;
15
16
/**
17
 * This param converter converts parameters based on service method call.
18
 * 
19
 * Param converter invocation:
20
 * 
21
 * `@ParamConverter("parameter_name", converter="service_param_converter", options={"service" = "service_id", "method" = "service_method", "arguments" = {"%requestParamName%", "@otherServiceId", "someParameter"})`
22
 * 
23
 * Using this converter you can inject virtually any parameter into a controller, as service method call is not restricted with anything.
24
 * You should be **very cautious**, though, when passing request parameters into a service method call, as it can potentially lead to injections of malicious code.
25
 * All of the parameters injected should be properly restricted (eg to integers) using routing configuration.
26
 * 
27
 * @author Tomasz Struczyński <[email protected]>
28
 */
29
class ServiceParamConverter implements ParamConverterInterface
30
{
31
    /**
32
     * Service container.
33
     * 
34
     * @var Container
35
     */
36
    private $container;
37
    
38
    /**
39
     * Class constructor.
40
     * 
41
     * @param Container $container Service container.
42
     */
43 7
    public function __construct(Container $container)
44
    {
45 7
        $this->container = $container;
46 7
    }
47
    
48
    /**
49
     * Apply param converter.
50
     * 
51
     * @param Request $request Request
52
     * @param ParamConverter $configuration Param converter configuration.
53
     * @return boolean
54
     */
55 6
    public function apply(Request $request, ParamConverter $configuration)
56
    {
57 6
        $param = $configuration->getName();
58 6
        $options = $this->getOptions($configuration);
59
        
60 6
        foreach ($options['arguments'] as &$value) {
61 4
            if (strpos($value, '%') === 0 && strrpos($value, '%') === strlen($value)-1) {
62 1
                $value = $request->get(substr($value, 1, strlen($value)-2));
63 4
            } elseif (strpos($value, '@') === 0) {
64 2
                if (!$this->container->has(substr($value, 1))) {
65 1
                    throw new InvalidArgumentException("Unknown service requested: ".$value);
66
                }
67 1
                $value = $this->container->get(substr($value, 1));
68 1
            }
69 5
        }
70
        
71 5
        $service = $this->container->get($options['service']);
72 5
        $return = call_user_func_array(array($service, $options['method']), $options['arguments']);
73
        
74 5
        if ($configuration->getClass() && (!is_object($return) || !is_a($return, $configuration->getClass()))) {
75 1
            return false;
76
        }
77
78 4
        $request->attributes->set($param, $return);
79
        
80 4
        return true;
81
    }
82
83 1
    public function supports(ParamConverter $configuration)
84
    {
85 1
        $options = $this->getOptions($configuration);
86
        
87 1
        return $this->container->has($options['service']) && !empty($options['method']);
88
    }
89
    
90 7
    protected function getOptions(ParamConverter $configuration)
91
    {
92 7
        $options = $configuration->getOptions();
93 7
        if (!is_array($options)) {
94 1
            $options = array();
95 1
        }
96 7
        return array_replace(array(
97 7
            'service' => null,
98 7
            'method' => null,
99 7
            'arguments' => array(),
100 7
        ), $options);
101
    }    
102
}