ListResponse   B
last analyzed

Complexity

Total Complexity 43

Size/Duplication

Total Lines 288
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 43
eloc 120
c 2
b 0
f 0
dl 0
loc 288
ccs 131
cts 131
cp 1
rs 8.96

10 Methods

Rating   Name   Duplication   Size   Complexity  
A addRestrictionData() 0 10 1
A whichDirection() 0 3 2
A addStock() 0 18 4
A addLimit() 0 10 1
F getXML() 0 67 19
A addOrder() 0 24 6
A addUserFilterName() 0 10 1
A addFilter() 0 10 1
A getLcFirstType() 0 8 2
B configureOptions() 0 50 6

How to fix   Complexity   

Complex Class

Complex classes like ListResponse often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ListResponse, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * This file is part of riesenia/pohoda package.
5
 *
6
 * Licensed under the MIT License
7
 * (c) RIESENIA.com
8
 */
9
10
declare(strict_types=1);
11
12
namespace Riesenia\Pohoda;
13
14
use Symfony\Component\OptionsResolver\Options;
15
16
/**
17
 * @property array{
18
 *     type: string,
19
 *     state: string,
20
 *     namespace: string,
21
 *     limit?: ListRequest\Limit,
22
 *     filter?: ListRequest\Filter,
23
 *     restrictionData?: ListRequest\RestrictionData,
24
 *     userFilterName?: ListRequest\UserFilterName,
25
 *     order?: iterable<Order>,
26
 *     stock?: iterable<Stock>,
27
 *     timestamp?: string|\DateTimeInterface,
28
 *     validFrom?: string|\DateTimeInterface,
29
 * } $data
30
 */
31
class ListResponse extends AbstractAgenda
32
{
33
    use Common\DirectionAsResponseTrait;
34
35
    /**
36
     * Add limit.
37
     *
38
     * @param array<string,mixed> $data
39
     *
40
     * @return $this
41
     */
42 1
    public function addLimit(array $data): self
43
    {
44 1
        $limit = new ListRequest\Limit($this->dependenciesFactory);
45 1
        $limit
46 1
            ->setDirectionalVariable($this->useOneDirectionalVariables)
47 1
            ->setResolveOptions($this->resolveOptions)
48 1
            ->setData($data);
49 1
        $this->data['limit'] = $limit;
50
51 1
        return $this;
52
    }
53
54
    /**
55
     * Add filter.
56
     *
57
     * @param array<string,mixed> $data
58
     *
59
     * @return $this
60
     */
61 1
    public function addFilter(array $data): self
62
    {
63 1
        $filter = new ListRequest\Filter($this->dependenciesFactory);
64 1
        $filter
65 1
            ->setDirectionalVariable($this->useOneDirectionalVariables)
66 1
            ->setResolveOptions($this->resolveOptions)
67 1
            ->setData($data);
68 1
        $this->data['filter'] = $filter;
69
70 1
        return $this;
71
    }
72
73
    /**
74
     * Add restriction data.
75
     *
76
     * @param array<string,mixed> $data
77
     *
78
     * @return $this
79
     */
80 1
    public function addRestrictionData(array $data): self
81
    {
82 1
        $restrictionData = new ListRequest\RestrictionData($this->dependenciesFactory);
83 1
        $restrictionData
84 1
            ->setDirectionalVariable($this->useOneDirectionalVariables)
85 1
            ->setResolveOptions($this->resolveOptions)
86 1
            ->setData($data);
87 1
        $this->data['restrictionData'] = $restrictionData;
88
89 1
        return $this;
90
    }
91
92
    /**
93
     * Add user filter name.
94
     *
95
     * @param string $name
96
     *
97
     * @return $this
98
     */
99 1
    public function addUserFilterName(string $name): self
100
    {
101 1
        $userFilterName = new ListRequest\UserFilterName($this->dependenciesFactory);
102 1
        $userFilterName
103 1
            ->setDirectionalVariable($this->useOneDirectionalVariables)
104 1
            ->setResolveOptions($this->resolveOptions)
105 1
            ->setData(['userFilterName' => $name]);
106 1
        $this->data['userFilterName'] = $userFilterName;
107
108 1
        return $this;
109
    }
110
111
    /**
112
     * Add Order as content
113
     *
114
     * @param array<string, mixed> $header
115
     * @param array<array<string, mixed>> $items
116
     * @param array<string, mixed> $summary
117
     *
118
     * @return Order
119
     */
120 1
    public function addOrder(array $header, array $items = [], array $summary = []): Order
121
    {
122 1
        if (!isset($this->data['order'])
123 1
            || !(
124 1
                is_array($this->data['order'])
125 1
                || (is_a($this->data['order'], \ArrayAccess::class))
126 1
            )
127
        ) {
128 1
            $this->data['order'] = [];
129
        }
130 1
        $order = new Order($this->dependenciesFactory);
131 1
        $order
132 1
            ->setDirectionalVariable($this->useOneDirectionalVariables)
133 1
            ->setResolveOptions($this->resolveOptions)
134 1
            ->setData($header);
135 1
        $this->data['order'][] = $order;
136 1
        foreach ($items as $item) {
137 1
            $order->addItem($item);
138
        }
139 1
        if (!empty($summary)) {
140 1
            $order->addSummary($summary);
141
        }
142
143 1
        return $order;
144
    }
145
146
    /**
147
     * Add Stock as content
148
     *
149
     * @param array<string, mixed> $header
150
     *
151
     * @return Stock
152
     */
153 1
    public function addStock(array $header): Stock
154
    {
155 1
        if (!isset($this->data['stock'])
156 1
            || !(
157 1
                is_array($this->data['stock'])
158 1
                || (is_a($this->data['stock'], \ArrayAccess::class))
159 1
            )
160
        ) {
161 1
            $this->data['stock'] = [];
162
        }
163 1
        $stock = new Stock($this->dependenciesFactory);
164 1
        $stock
165 1
            ->setDirectionalVariable($this->useOneDirectionalVariables)
166 1
            ->setResolveOptions($this->resolveOptions)
167 1
            ->setData($header);
168 1
        $this->data['stock'][] = $stock;
169
170 1
        return $stock;
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 17
    public function getXML(): \SimpleXMLElement
177
    {
178
        // UserList is custom
179 17
        if ('UserList' == $this->data['type']) {
180 1
            $xml = $this->createXML()->addChild($this->data['namespace'] . ':listUserCodeResponse', '', $this->namespace(strval($this->data['namespace'])));
181 1
            $xml->addAttribute('version', '1.1');
182 1
            $xml->addAttribute('listVersion', '1.1');
183
        } else {
184 16
            $xml = $this->createXML()->addChild($this->data['namespace'] . ':list' . $this->data['type'], '', $this->namespace(strval($this->data['namespace'])));
185 16
            $xml->addAttribute('version', '2.0');
186
187
            // IntParam and Order doesn't have the version attribute
188 16
            if (!in_array($this->data['type'], ['IntParam', 'Order'])) {
189 13
                if (!isset($this->data['stock'])) {
190 12
                    $xml->addAttribute($this->getLcFirstType() . 'Version', '2.0');
191
                }
192
            }
193
194 16
            if (isset($this->data[$this->getLcFirstType() . 'Type'])) {
195 5
                $xml->addAttribute($this->getLcFirstType() . 'Type', strval($this->data[$this->getLcFirstType() . 'Type']));
196
            }
197
198 16
            if ('Order' == $this->data['type'] && (isset($this->data['order']))) {
199 1
                foreach ($this->data['order'] as $orderElement) {
200 1
                    $this->appendNode($xml, $orderElement->getXML());
201
                }
202
203 15
            } elseif ('Stock' == $this->data['type'] && (isset($this->data['stock']))) {
204 1
                foreach ($this->data['stock'] as $stockElement) {
205
                    // set namespace
206 1
                    $stockElement->setNamespace('lStk');
207 1
                    $this->appendNode($xml, $stockElement->getXML());
208
                }
209
210
            } else {
211 14
                $request = $xml->addChild($this->data['namespace'] . ':' . $this->whichDirection($this->directionAsResponse) . $this->data['type']);
212
213 14
                $this->addElements($request, ['limit', 'filter', 'userFilterName'], 'ftr');
214
            }
215
216 16
            if (isset($this->data['restrictionData'])) {
217 1
                $this->addElements($xml, ['restrictionData'], 'lst');
218
            }
219
        }
220
221 17
        if (isset($this->data['timestamp'])) {
222 17
            $date = $this->data['timestamp'];
223 17
            if (is_object($date) && is_a($date, \DateTimeInterface::class)) {
224 17
                $date = $date->format('Y-m-d\TH:i:s');
225
            }
226 17
            $xml->addAttribute('dateTimeStamp', strval($date));
227
        }
228
229 17
        if (isset($this->data['validFrom'])) {
230 4
            $dateFrom = $this->data['validFrom'];
231 4
            if (is_object($dateFrom) && is_a($dateFrom, \DateTimeInterface::class)) {
232 4
                $dateFrom = $dateFrom->format('Y-m-d');
233
            }
234 4
            $xml->addAttribute('dateValidFrom', strval($dateFrom));
235
        }
236
237 17
        if (isset($this->data['state'])) {
238 17
            $xml->addAttribute('state', strval($this->data['state']));
239
        }
240
241
242 17
        return $xml;
243
    }
244
245 14
    protected function whichDirection(bool $asResponse): string
246
    {
247 14
        return $asResponse ? 'response' : 'request';
248
    }
249
250
    /**
251
     * {@inheritdoc}
252
     */
253 17
    protected function configureOptions(Common\OptionsResolver $resolver): void
254
    {
255
        // available options
256 2
        $resolver->setDefined(['type', 'namespace', 'order', 'orderType', 'invoiceType', 'timestamp', 'validFrom', 'state']);
257
258
        // validate / format options
259 2
        $resolver->setRequired('type');
260 2
        $resolver->setNormalizer('type', $this->dependenciesFactory->getNormalizerFactory()->getClosure('list_request_type'));
261 2
        $resolver->setDefault('namespace', function (Options $options) {
262 17
            if ('Stock' == $options['type']) {
263 2
                return 'lStk';
264
            }
265
266 15
            if ('AddressBook' == $options['type']) {
267 1
                return 'lAdb';
268
            }
269
            /*
270
            if ('AccountingUnit' == $options['type']) {
271
                return 'acu';
272
            }
273
            */
274 14
            if ('Contract' == $options['type']) {
275 1
                return 'lCon';
276
            }
277
            /*
278
            if ('Centre' == $options['type']) {
279
                return 'lCen';
280
            }
281
282
            if ('Activity' == $options['type']) {
283
                return 'lAcv';
284
            }
285
            */
286 13
            return 'lst';
287 2
        });
288 2
        $resolver->setAllowedValues('orderType', [null, 'receivedOrder', 'issuedOrder']);
289 2
        $resolver->setDefault('orderType', function (Options $options) {
290 17
            if ('Order' == $options['type']) {
291 2
                return 'receivedOrder';
292
            }
293
294 15
            return null;
295 2
        });
296 2
        $resolver->setAllowedValues('invoiceType', [null, 'issuedInvoice', 'issuedCreditNotice', 'issuedDebitNote', 'issuedAdvanceInvoice', 'receivable', 'issuedProformaInvoice', 'penalty', 'issuedCorrectiveTax', 'receivedInvoice', 'receivedCreditNotice', 'receivedDebitNote', 'receivedAdvanceInvoice', 'commitment', 'receivedProformaInvoice', 'receivedCorrectiveTax']);
297 2
        $resolver->setDefault('invoiceType', function (Options $options) {
298 16
            if ('Invoice' == $options['type']) {
299 2
                return 'issuedInvoice';
300
            }
301
302 14
            return null;
303 2
        });
304
    }
305
306
    /**
307
     * Get LC first type name.
308
     *
309
     * @return string
310
     */
311 16
    protected function getLcFirstType(): string
312
    {
313
        // ActionPrice is custom
314 16
        if ('ActionPrice' == $this->data['type']) {
315 1
            return 'actionPrices';
316
        }
317
318 15
        return \lcfirst(strval($this->data['type']));
319
    }
320
}
321