Passed
Push — main ( c49c6c...49fc69 )
by Gaetano
08:47
created

HTTPExecutor::resolveReferencesRecursively()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 9
ccs 0
cts 6
cp 0
crap 12
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
A HTTPExecutor::resolveReferencesInText() 0 3 1
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use Kaliop\eZMigrationBundle\API\EmbeddedReferenceResolverBagInterface;
6
use Kaliop\eZMigrationBundle\API\Exception\InvalidStepDefinitionException;
7
use Kaliop\eZMigrationBundle\API\Value\MigrationStep;
8
use Psr\Http\Message\ResponseInterface;
9
use Symfony\Component\DependencyInjection\ContainerInterface;
10
11
/**
12
 * @property EmbeddedReferenceResolverBagInterface $referenceResolver
13
 */
14
class HTTPExecutor extends AbstractExecutor
15
{
16
    use IgnorableStepExecutorTrait;
0 ignored issues
show
Bug introduced by
The trait Kaliop\eZMigrationBundle...orableStepExecutorTrait requires the property $dsl which is not provided by Kaliop\eZMigrationBundle...e\Executor\HTTPExecutor.
Loading history...
17
    use ReferenceSetterTrait;
18
19
    protected $supportedStepTypes = array('http');
20
    protected $supportedActions = array('call');
21
22
    protected $container;
23
24
    /**
25
     * @param ContainerInterface $container
26
     * @param EmbeddedReferenceResolverBagInterface $referenceResolver has to implement EmbeddedReferenceResolverInterface as well!
27 149
     */
28
    public function __construct(ContainerInterface $container, EmbeddedReferenceResolverBagInterface $referenceResolver)
29 149
    {
30 149
        $this->referenceResolver = $referenceResolver;
31 149
        $this->container = $container;
32
    }
33
34
    /**
35
     * @param MigrationStep $step
36
     * @return mixed
37
     * @throws \Exception
38
     */
39
    public function execute(MigrationStep $step)
40
    {
41
        parent::execute($step);
42
43
        if (!isset($step->dsl['mode'])) {
44
            throw new InvalidStepDefinitionException("Invalid step definition: missing 'mode'");
45
        }
46
47
        $action = $step->dsl['mode'];
48
49
        if (!in_array($action, $this->supportedActions)) {
50
            throw new InvalidStepDefinitionException("Invalid step definition: value '$action' is not allowed for 'mode'");
51
        }
52
53
        $this->skipStepIfNeeded($step);
54
55
        return $this->$action($step->dsl, $step->context);
56
    }
57
58
    /**
59
     * @param array $dsl
60
     * @param array $context
61
     * @return true
62
     * @throws \Exception
63
     */
64
    protected function call($dsl, $context)
65
    {
66
        if (!isset($dsl['uri'])) {
67
            throw new InvalidStepDefinitionException("Can not execute http call without 'uri' in the step definition");
68
        }
69
70
        $method = isset($dsl['method']) ? $this->resolveReference($dsl['method']) : 'GET';
71
72
        $uri = $this->resolveReferencesInText($dsl['uri']);
73
74
        $headers = isset($dsl['headers']) ? $this->resolveReferencesInTextRecursively($dsl['headers']) : array();
75
76
        $body = isset($dsl['body']) ? $this->resolveReferencesInText($dsl['body']) : null;
77
78
        if (isset($dsl['client'])) {
79
            $client = $this->container->get('httplug.client.'.$this->resolveReference($dsl['client']));
80
        } else {
81
            $client = $this->container->get('httplug.client');
82
        }
83
84
        $request = $this->container->get('httplug.message_factory')->createRequest($method, $uri, $headers, $body);
85
86
        $response = $client->sendRequest($request);
87
88
        $this->setReferences($response, $dsl);
89
90
        return $response;
91
    }
92
93
    /**
94
     * @param ResponseInterface $response
95
     * @param array $dsl
96
     * @return bool
97
     * @throws InvalidStepDefinitionException
98
     * @todo use jmespath syntax to allow setting refs to response headers
99
     */
100
    protected function setReferences(ResponseInterface $response, $dsl)
101
    {
102
        if (!array_key_exists('references', $dsl) || !count($dsl['references'])) {
103
            return false;
104
        }
105
106
        foreach ($dsl['references'] as $key => $reference) {
107
            $reference = $this->parseReferenceDefinition($key, $reference);
108
            switch ($reference['attribute']) {
109
                case 'status_code':
110
                    $value = $response->getStatusCode();
111
                    break;
112
                case 'reason_phrase':
113
                    $value = $response->getReasonPhrase();
114
                    break;
115
                case 'protocol_version':
116
                    $value = $response->getProtocolVersion();
117
                    break;
118
                case 'body':
119
                    $value = $response->getBody()->__toString();
120
                    break;
121
                case 'body_size':
122
                    $value = $response->getBody()->getSize();
123
                    break;
124
                default:
125
                    throw new InvalidStepDefinitionException('HTTP executor does not support setting references for attribute ' . $reference['attribute']);
126
            }
127
128
            $overwrite = false;
129
            if (isset($reference['overwrite'])) {
130
                $overwrite = $reference['overwrite'];
131
            }
132
            $this->addReference($reference['identifier'], $value, $overwrite);
133
        }
134
135
        return true;
136
    }
137
138
    /**
139
     * Replaces any references inside a string
140
     *
141
     * @param string
142
     * @return string
143
     * @throws \Exception
144
     */
145
    protected function resolveReferencesInText($text)
146
    {
147
        return $this->referenceResolver->ResolveEmbeddedReferences($text);
148
    }
149
150
    protected function resolveReferencesInTextRecursively($textOrArray)
151
    {
152
        if (is_array($textOrArray)) {
153
            foreach ($textOrArray as $condition => $values) {
154
                $textOrArray[$condition] = $this->resolveReferencesInTextRecursively($values);
155
            }
156
            return $textOrArray;
157
        } else {
158
            return $this->resolveReferencesInText($textOrArray);
159
        }
160
    }
161
}
162