Test Failed
Push — main ( 6b9298...8f70c4 )
by Daniel
03:22
created

TraitBackEndRomania   F

Complexity

Total Complexity 78

Size/Duplication

Total Lines 486
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 338
c 1
b 0
f 1
dl 0
loc 486
rs 2.16
wmc 78

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getElectronicInvoiceResponseFile() 0 23 2
B getElectronicInvoiceMessages() 0 66 9
A decideRelevantUniformResourceLocatorForUpload() 0 9 1
A buildHeaderAsArray() 0 5 1
A authorizeConnectionToLegalAuthority() 0 15 1
D getServerMessageParametersValidation() 0 110 30
A uploadElectronicInvoicesFromFolder() 0 43 5
A getServerDiscutionValidations() 0 12 2
A exposeFeedbackOnFileProcessed() 0 12 3
B setLabelBasedOnRule() 0 30 6
C checkPrerequisite() 0 55 16
A getMessageFilterCode() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like TraitBackEndRomania 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 TraitBackEndRomania, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * Copyright (c) 2025, Daniel Popiniuc and its licensors.
5
 *
6
 * All rights reserved. This program and the accompanying materials
7
 * are made available under the terms of the Eclipse Public License v1.0
8
 * which accompanies this distribution, and is available at
9
 * http://www.eclipse.org/legal/epl-v20.html
10
 *
11
 * Contributors:
12
 *    Daniel Popiniuc
13
 */
14
15
namespace danielgp\efactura;
16
17
/**
18
 * Configurable & Re-usable methods facilitating calls to known Romanian services for Electronic Invoice
19
 *
20
 * @author Daniel Popiniuc
21
 */
22
trait TraitBackEndRomania
23
{
24
    use \danielgp\efactura\TraitBasic;
25
26
    private array $arraystandardMesageFilters    = [
27
        [
28
            'Code'   => 'E',
29
            'Detail' => 'raspuns cu erorile si semnatura MF, livrat in urma transmiterii unei facturi'
30
            . ', daca NU este validata de sistem',
31
            'Value'  => 'ERORI FACTURA',
32
        ],
33
        [
34
            'Code'   => 'P',
35
            'Detail' => 'factura primita in calitate de cunparator de la un emitent'
36
            . ' care a folosit sistemul national'
37
            . ' privind factura electronica RO e-factura',
38
            'Value'  => 'FACTURA PRIMITA',
39
        ],
40
        [
41
            'Code'   => 'T',
42
            'Detail' => 'raspuns cu factura originala si semnatura MF'
43
            . ', transmis in urma transmiterii unei facturi, daca este validata de sistem',
44
            'Value'  => 'FACTURA TRIMISA',
45
        ],
46
        [
47
            'Code'   => 'R',
48
            'Detail' => 'mesaj de la cumparator catre emitentul facturii'
49
            . ' (încărcate în sistem prin serviciul de upload ca RASP)',
50
            'Value'  => 'MESAJ CUMPARATOR PRIMIT / MESAJ CUMPARATOR TRANSMIS',
51
        ],
52
    ];
53
    // below variable has to be initialized by class consuming this Trait
54
    protected array $arraySolutionCustomSettings = [
55
        'ArrayElectronicInvoiceSecrets'      => [
56
            'Client_ID'     => '',
57
            'Client_Secret' => '',
58
            'Token'         => '',
59
        ],
60
        'ArrayFolders'                       => [
61
            'Generated XML'  => '',
62
            'Uploaded XML'   => '',
63
            'Downloaded ZIP' => '',
64
        ],
65
        'ArrayStrategyForUpload'             => [
66
            'B2B' => 'File base name end with|__b2b.xml',
67
            'B2C' => 'File base name end with|__b2c.xml',
68
            'B2G' => 'File base name end with|__b2g.xml',
69
        ],
70
        'IntegerNumberOfDaysToCheckMessages' => 0,
71
        'IntegerTaxIdentificationNumber'     => 0,
72
        'StringElectronicInvoiceEnvironment' => '',
73
        'StringElectronicInvoiceStandard'    => 'UBL',
74
        'StringOptionalUploadParameters'     => '', // could be one of the following: extern=DA | autofactura=DA | executare=DA
75
    ];
76
77
    private function authorizeConnectionToLegalAuthority(): void
78
    {
79
        $this->checkPrerequisite([
80
            'Empty Secrets Array' => $this->arraySolutionCustomSettings['ArrayElectronicInvoiceSecrets'],
81
        ]);
82
        $strRelevantUrl = $this->arraySettings['Infrastructure']['RO']['Servers']['Login']
83
            . $this->arraySettings['Infrastructure']['RO']['Calls']['Login']['Authorisation']
84
            . '?' . implode('&', [
85
                'client_id=' . $this->arraySolutionCustomSettings['ArrayElectronicInvoiceSecrets']['Client_ID'],
86
                'client_secret=' . $this->arraySolutionCustomSettings['ArrayElectronicInvoiceSecrets']['Client_Secret'],
87
                'response_type=' . 'code',
88
                'redirect_uri=' . $this->arraySettings['Infrastructure']['RO']['Servers']['Redirect']
89
                . $this->arraySettings['Infrastructure']['RO']['Calls']['Redirect'],
90
        ]);
91
        header('Location: ' . $strRelevantUrl);
92
    }
93
94
    private function buildHeaderAsArray(): array
95
    {
96
        return [
97
            'Authorization: Bearer ' . $this->arraySolutionCustomSettings['ArrayElectronicInvoiceSecrets']['Token'],
98
            'Content-Type: text/plain',
99
        ];
100
    }
101
102
    private function checkPrerequisite(array $arrayAssignedChecks): void
103
    {
104
        foreach ($arrayAssignedChecks as $strLabelCheck => $elementChecked) {
105
            switch ($strLabelCheck) {
106
                case 'Empty Environment':
107
                    if ($elementChecked == '') {
108
                        throw \RuntimeException('Environment is NOT allowed to be empty'
0 ignored issues
show
Bug introduced by
The function RuntimeException was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
                        throw /** @scrutinizer ignore-call */ \RuntimeException('Environment is NOT allowed to be empty'
Loading history...
109
                                . ', please ensure proper environment from your custom class...');
110
                    }
111
                    break;
112
                case 'Empty Secrets Array':
113
                    if ($elementChecked == []) {
114
                        throw \RuntimeException('Secrets array is NOT allowed to be empty'
115
                                . ', please ensure proper building from your custom class...');
116
                    }
117
                    break;
118
                case 'Message Filter Value':
119
                    $arrayAllowedValues = array_column($this->arraystandardMesageFilters, 'Value');
120
                    if (($elementChecked !== '') && !in_array($elementChecked, $arrayAllowedValues)) {
121
                        throw \RuntimeException(vsprintf('Message Filter provided has a value of %s that is not allowed'
122
                                    . ' as can only be one of the following: %s'
123
                                    . ', please ensure proper value is given from your custom class...', [
124
                                $elementChecked,
125
                                '"' . implode('" or "', array_keys($arrayAllowedValues)) . '"',
126
                        ]));
127
                    }
128
                    break;
129
                case 'Message Type Value':
130
                    $arrayAllowedValues = array_keys($this->arraySettings['Infrastructure']['RO']['Calls']['Content']['Message']);
131
                    if (!in_array($elementChecked, $arrayAllowedValues)) {
132
                        throw \RuntimeException(vsprintf('Message Type provided has a value of %s that is not allowed'
133
                                    . ' as can only be one of the following: %s'
134
                                    . ', please ensure proper value is given from your custom class...', [
135
                                $elementChecked,
136
                                '"' . implode('" or "', array_keys($arrayAllowedValues)) . '"',
137
                        ]));
138
                    }
139
                    break;
140
                case 'Non-Standard Environment Value':
141
                    $arrayAllowedValues = ['prod', 'test'];
142
                    if (($elementChecked !== '') && !in_array($elementChecked, $arrayAllowedValues)) {
143
                        throw \RuntimeException(vsprintf('Environment provided has a value of %s that is not allowed'
144
                                    . ' as can only be one of the following: %s'
145
                                    . ', please ensure proper value is given from your custom class...', [
146
                                $elementChecked,
147
                                '"' . implode('" or "', $arrayAllowedValues) . '"',
148
                        ]));
149
                    }
150
                    break;
151
                case 'Zero Value':
152
                    if ($elementChecked === 0) {
153
                        throw \RuntimeException('Tax Identification Number is not allowed to be 0'
154
                                . ', please ensure you pass proper value from your custom class...');
155
                    }
156
                    break;
157
            }
158
        }
159
    }
160
161
    private function decideRelevantUniformResourceLocatorForUpload(string $strFileName): string
162
    {
163
        $strLabel        = $this->setLabelBasedOnRule($strFileName);
164
        error_log(sprintf('For given file %s following Label %s has been established!', $strFileName, $strLabel));
165
        $strUrlForUpload = $this->arraySettings['Infrastructure']['RO']['Calls']['Content']['Upload'][$strLabel];
166
        return vsprintf($strUrlForUpload, [
167
            $this->arraySolutionCustomSettings['StringElectronicInvoiceStandard'],
168
            $this->arraySolutionCustomSettings['IntegerTaxIdentificationNumber'],
169
            $this->arraySolutionCustomSettings['StringOptionalUploadParameters'],
170
        ]);
171
    }
172
173
    private function exposeFeedbackOnFileProcessed(int $intFileFoundNo, int $intFileProcessed): void
174
    {
175
        if ($intFileFoundNo === 0) {
176
            error_log('NO files were found to be processed.');
177
        } elseif ($intFileFoundNo == $intFileProcessed) {
178
            error_log(sprintf('All %u files found were processed successfully!', $intFileFoundNo));
179
        } else {
180
            error_log(vsprintf('Out of %u files found only %u were processed successfully, hence %u were missed.'
181
                    . ' Check your source folder where residual files are still there.', [
182
                $intFileFoundNo,
183
                $intFileProcessed,
184
                ($intFileFoundNo - $intFileProcessed),
185
            ]));
186
        }
187
    }
188
189
    /**
190
     * Work In Progress =================> UNIFNISHED !!!
191
     *
192
     * @param string $strType
193
     * @param array $arrayParameters
194
     * @return void
195
     */
196
    protected function getElectronicInvoiceMessages(string $strType, array $arrayParameters): void
197
    {
198
        $this->getServerDiscutionValidations([
199
            'Message Type Value', $strType,
200
            'Message Parameters' => $arrayParameters,
201
        ]);
202
        $this->getServerMessageParametersValidation($strType, $arrayParameters);
203
        $this->authorizeConnectionToLegalAuthority();
204
        $strContentBranch          = '';
205
        $arrayFinalParameterValues = [];
206
        $strFilter                 = '';
207
        switch ($strType) {
208
            case 'ListAll':
209
                $strContentBranch            = 'ListAllMessages';
210
                $arrayFinalParameterValues[] = $arrayParameters['Days'];
211
                $arrayFinalParameterValues[] = $this->arraySolutionCustomSettings['IntegerTaxIdentificationNumber'];
212
                $arrayFinalParameterValues[] = $this->getMessageFilterCode($strFilter);
213
                break;
214
            case 'ListSinglePage':
215
                $strContentBranch            = 'ListMessagesPaged';
216
                $arrayFinalParameterValues[] = $arrayParameters['StartTime'];
217
                $arrayFinalParameterValues[] = $arrayParameters['EndTime'];
218
                $arrayFinalParameterValues[] = $arrayParameters['Page'];
219
                $arrayFinalParameterValues[] = $this->getMessageFilterCode($strFilter);
220
                break;
221
            case 'Single':
222
                $strContentBranch            = 'SingleMessageStatus';
223
                $arrayFinalParameterValues[] = $arrayParameters['LoadingId'];
224
                break;
225
        }
226
        $strRelevantUrl = $this->arraySettings['Infrastructure']['RO']['Servers']['Content']['OAuth2']
227
            . $this->arraySolutionCustomSettings['StringElectronicInvoiceEnvironment']
228
            . vsprintf($this->arraySettings['Infrastructure']['RO']['Calls']['Content'][$strContentBranch], $arrayFinalParameterValues);
229
        error_log(vsprintf('Relevant URL for Message reading of type %s is %s', [
230
            $strType,
231
            $strRelevantUrl,
232
        ]));
233
        // sent XML content using CURL and capture feedback
234
        $arrayFeedback  = $this->getContentFromUrlThroughCurl($strRelevantUrl, [
0 ignored issues
show
Bug introduced by
It seems like getContentFromUrlThroughCurl() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

234
        /** @scrutinizer ignore-call */ 
235
        $arrayFeedback  = $this->getContentFromUrlThroughCurl($strRelevantUrl, [
Loading history...
235
            'HttpHeader' => $this->buildHeaderAsArray(),
236
        ]);
237
        if ($arrayFeedback['errNo'] === 0) {
238
            if (json_validate($arrayFeedback['response'])) {
239
                $arrayFeedback['response'] = json_decode($arrayFeedback['response'], JSON_OBJECT_AS_ARRAY);
0 ignored issues
show
Bug introduced by
danielgp\efactura\JSON_OBJECT_AS_ARRAY of type integer is incompatible with the type boolean|null expected by parameter $associative of json_decode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

239
                $arrayFeedback['response'] = json_decode($arrayFeedback['response'], /** @scrutinizer ignore-type */ JSON_OBJECT_AS_ARRAY);
Loading history...
240
                $intMessageNo              = 0;
241
                error_log('Response = ' . json_encode($arrayFeedback['response']));
242
                if (array_key_exists('eroare', $arrayFeedback['response'])) {
243
                    error_log('Error response = ' . $arrayFeedback['response']['eroare']);
244
                } else {
245
                    foreach ($arrayFeedback['response']['mesaje'] as $arrayMessageDetails) {
246
                        $strTargetFile = $this->arraySolutionCustomSettings['ArrayFolders']['Downloaded ZIP']
247
                            . strval($arrayMessageDetails['id']) . '.zip';
248
                        if (!file_exists($strTargetFile)) {
249
                            $this->getElectronicInvoiceResponseFile($arrayMessageDetails['id'], $strTargetFile);
250
                        }
251
                        error_log('Current message is ' . json_encode($arrayMessageDetails));
252
                        $intMessageNo++;
253
                    }
254
                    error_log(sprintf('%u messages were processed!', strval($intMessageNo)));
255
                }
256
            } else {
257
                error_log('Response is expected to be a JSON but is not...');
258
                error_log(json_encode($arrayFeedback));
259
            }
260
        } else {
261
            error_log($arrayFeedback['errNo'] . ' => ' . $arrayFeedback['errMsg']);
262
        }
263
    }
264
265
    protected function getElectronicInvoiceResponseFile(int $intResponseId, string $strTargetFile): void
266
    {
267
        error_log(sprintf('Will download the response ZIP file having ID = %s', $intResponseId));
268
        $strRelevantUrl = vsprintf($this->arraySettings['Infrastructure']['RO']['Servers']['Content']['OAuth2']
269
            . $this->arraySolutionCustomSettings['StringElectronicInvoiceEnvironment']
270
            . $this->arraySettings['Infrastructure']['RO']['Calls']['Content']['Download'], [
271
            $intResponseId,
272
        ]);
273
        error_log(vsprintf('Relevant URL for Downloading Response ZIP file havign ID = %s is %s', [
274
            strval($intResponseId),
275
            $strRelevantUrl,
276
        ]));
277
        // sent XML content using CURL and capture feedback
278
        $datafile       = $this->getContentFromUrlThroughCurl($strRelevantUrl, [
279
            'HttpHeader' => $this->buildHeaderAsArray(),
280
        ]);
281
        $ffileHandler   = fopen($strTargetFile, 'w');
282
        fwrite($ffileHandler, $datafile['response']);
283
        fclose($ffileHandler);
284
        if (file_exists($strTargetFile)) {
285
            error_log(vsprintf('Response ZIP file having ID = %s was sucessfully saved to %s', [
286
                strval($intResponseId),
287
                $strTargetFile,
288
            ]));
289
        }
290
    }
291
292
    private function getMessageFilterCode(string $strFilter): string
293
    {
294
        $strReturn = '';
295
        if ($strFilter != '') {
296
            $strReturn = '&filtru=' . array_column($this->arraystandardMesageFilters, 'Code', 'Value')[$strFilter];
297
        }
298
        return $strReturn;
299
    }
300
301
    /**
302
     * implementing strong validations to avoid issues later in the logic
303
     *
304
     * @param array $arrayAdditionalValidations
305
     */
306
    private function getServerDiscutionValidations(array $arrayAdditionalValidations = []): void
307
    {
308
        $arrayUniversalValidations = [
309
            'Zero Value'                     => $this->arraySolutionCustomSettings['IntegerTaxIdentificationNumber'],
310
            'Empty Environment'              => $this->arraySolutionCustomSettings['StringElectronicInvoiceEnvironment'],
311
            'Non-Standard Environment Value' => $this->arraySolutionCustomSettings['StringElectronicInvoiceEnvironment'],
312
        ];
313
        $arrayValidations          = $arrayUniversalValidations;
314
        if ($arrayAdditionalValidations != []) {
315
            $arrayValidations = array_merge($arrayValidations, $arrayAdditionalValidations);
316
        }
317
        $this->checkPrerequisite($arrayValidations);
318
    }
319
320
    private function getServerMessageParametersValidation(string $strType, array $arrayParameters): void
321
    {
322
        $arrayAllowedParameters = match ($strType) {
323
            'ListAll'        => [
324
                'Mandatory' => ['Days'],
325
                'Optional'  => ['Filter'],
326
            ],
327
            'ListSinglePage' => [
328
                'Mandatory' => ['StartTime', 'EndTime', 'Page'],
329
                'Optional'  => ['Filter'],
330
            ],
331
            'Single'         => [
332
                'Mandatory' => ['LoadingId'],
333
            ],
334
        };
335
        $arrayAllowedCombined   = $arrayAllowedParameters['Mandatory'];
336
        if (array_key_exists('Optional', $arrayAllowedParameters)) {
337
            $arrayAllowedCombined = array_merge($arrayAllowedParameters['Mandatory'], $arrayAllowedParameters['Optional']);
338
        }
339
        $arrayGivenKeys = array_keys($arrayParameters);
340
        $strErrors      = [];
341
        if (array_diff($arrayAllowedParameters['Mandatory'], $arrayGivenKeys) != []) {
342
            $strErrors[] = vsprintf('Provided parameters %s does contain all mandatory ones: %s...', [
343
                json_encode($arrayGivenKeys),
344
                json_encode($arrayAllowedParameters['Mandatory']),
345
            ]);
346
        } elseif (($arrayGivenKeys != $arrayAllowedParameters['Mandatory']) && (array_diff($arrayAllowedCombined, $arrayGivenKeys) != [])) {
347
            $strErrors[] = vsprintf('Provided parameters %s does contain all mandatory & optional ones: %s...', [
348
                json_encode($arrayGivenKeys),
349
                json_encode($arrayAllowedCombined),
350
            ]);
351
        } else {
352
            // here we have to validate actual value passed as parameters
353
            foreach ($arrayParameters as $strParameterKey => $strParameterValue) {
354
                switch ($strParameterKey) {
355
                    case 'Days':
356
                    case 'LoadingId':
357
                    case 'Page':
358
                        $arrayRangeAllowedPieces = explode('-', match ($strParameterKey) {
359
                            'Days'      => '1-60',
360
                            'LoadingId' => '1-' . strval(9 * pow(10, 10)),
361
                            'Page'      => '0-' . strval(9 * pow(10, 6)),
362
                        });
363
                        $regs                    = null;
364
                        preg_match('/[0-9]{1,20}/', $strParameterValue, $regs, PREG_UNMATCHED_AS_NULL);
365
                        if (is_array($regs) && ($regs !== []) && ($regs[0] != $strParameterValue)) {
366
                            $strErrors[] = vsprintf('Parameter "%s" is expected to be of integer type'
367
                                . ' but something else is given "%s"...', [
368
                                $strParameterKey,
369
                                json_encode($strParameterValue),
370
                            ]);
371
                        } elseif (($strParameterValue < $arrayRangeAllowedPieces[0]) || ($strParameterValue > $arrayRangeAllowedPieces[1])) {
372
                            $strErrors[] = vsprintf('Parameter "%s" is an integer value'
373
                                . ' and within range between 1 and 60 but %s is given...', [
374
                                $strParameterKey,
375
                                $strParameterValue,
376
                            ]);
377
                        }
378
                        break;
379
                    case 'Filter':
380
                        $arrayAllowedValues = array_column($this->arraystandardMesageFilters, 'Value');
381
                        if (($strParameterValue !== '') && !in_array($strParameterValue, $arrayAllowedValues)) {
382
                            $strErrors[] = vsprintf('Message Filter provided has a value of %s'
383
                                . ' that is not allowed'
384
                                . ' as can only be one of the following: %s'
385
                                . ', please ensure proper value is given from your custom class...', [
386
                                $elementChecked,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $elementChecked seems to be never defined.
Loading history...
387
                                '"' . implode('" or "', array_keys($arrayAllowedValues)) . '"',
388
                            ]);
389
                        }
390
                        break;
391
                    case 'StartTime':
392
                    case 'EndTime':
393
                        $arrayRangeAllowedPieces          = explode('|', strval((\DateTime::createFromFormat('Y-m-d G:i:s', '2021-01-01 00:00:00', new \DateTimeZone('UTC')))->format('U') * 1000)
394
                            . '|' . strval((new \DateTime('now', new \DateTimeZone('UTC')))->format('U') * 1000));
395
                        $arrayRangeAllowedPiecesForHumans = explode('|', (\DateTime::createFromFormat('U', intval(($arrayRangeAllowedPieces[0] / 1000)), new \DateTimeZone('UTC')))->format('Y-m-d H:i:s')
396
                            . '|' . (\DateTime::createFromFormat('U', intval(($arrayRangeAllowedPieces[1] / 1000)), new \DateTimeZone('UTC')))->format('Y-m-d H:i:s'));
397
                        $strErrors                        = [];
398
                        if (is_integer($strParameterValue) && (($strParameterValue < $arrayRangeAllowedPieces[0]) || ($strParameterValue > $arrayRangeAllowedPieces[1]))) {
399
                            $strErrors[] = vsprintf('Parameter "%s" is given as an integer value %s (which translate in %s) '
400
                                . ' but that is NOT within allowed range, which is between %s and %s...', [
401
                                $strParameterKey,
402
                                $strParameterValue,
403
                                (\DateTime::createFromFormat('U', intval(($strParameterValue / 1000)), new \DateTimeZone('UTC')))->format('Y-m-d H:i:s'),
404
                                $arrayRangeAllowedPiecesForHumans[0],
405
                                $arrayRangeAllowedPiecesForHumans[1],
406
                            ]);
407
                        } elseif (is_string($strParameterValue) && (strlen($strParameterValue) == 19)) {
408
                            $regs = null;
409
                            preg_match('/(1|2)[0-9]{3}\-((01|03|05|07|08|10|12)\-(0{1}[1-9]{1}|[1-2]{1}[0-9]{1}|3[0-1]{1})|(04|06|09|11)\-(0{1}[1-9]{1}|[1-2]{1}[0-9]{1}|30)|02\-[0-1-2]{1}[0-9]{1})\s(0[0-9]{1}|1[0-9]{1}|2[0-3]{1})\:[0-5]{1}[0-9]{1}\:[0-5]{1}[0-9]{1}/m', $strParameterValue, $regs, PREG_UNMATCHED_AS_NULL);
410
                            if (is_array($regs) && ($regs !== []) && ($regs[0] == $strParameterValue)) {
411
                                $intValueToCompare = (\DateTime::createFromFormat('Y-m-d G:i:s', $strParameterValue, new \DateTimeZone('UTC')))->format('U') * 1000;
412
                                if (($intValueToCompare < $arrayRangeAllowedPieces[0]) || ($intValueToCompare > $arrayRangeAllowedPieces[1])) {
413
                                    $strErrors[] = vsprintf('Parameter "%s" is given as a TimeStamp value of %s '
414
                                        . ' but that is NOT within allowed range, which is between %s and %s...', [
415
                                        $strParameterKey,
416
                                        $strParameterValue,
417
                                        $arrayRangeAllowedPiecesForHumans[0],
418
                                        $arrayRangeAllowedPiecesForHumans[1],
419
                                    ]);
420
                                }
421
                            }
422
                        }
423
                        break;
424
                }
425
            }
426
        }
427
        if ($strErrors != []) {
428
            error_log(implode(PHP_EOL, $strErrors));
429
            throw \RuntimeException(implode(PHP_EOL, $strErrors));
0 ignored issues
show
Bug introduced by
The function RuntimeException was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

429
            throw /** @scrutinizer ignore-call */ \RuntimeException(implode(PHP_EOL, $strErrors));
Loading history...
430
        }
431
    }
432
433
    private function setLabelBasedOnRule(string $strFileName): string
434
    {
435
        $arrayKnownLabels = ['B2B', 'B2C', 'B2G'];
436
        $arrayKnownRules  = [
437
            'File base name end with',
438
            'File base name starts with',
439
        ];
440
        $strLabel         = '';
441
        foreach ($arrayKnownLabels as $strCurrentLabel) {
442
            $arrayPieces = explode('|', $this->arraySolutionCustomSettings['ArrayStrategyForUpload'][$strCurrentLabel]);
443
            switch ($arrayPieces[0]) {
444
                case 'File base name end with':
445
                    if (str_ends_with($strFileName, $arrayPieces[1])) {
446
                        $strLabel = $strCurrentLabel;
447
                    }
448
                    break;
449
                case 'File base name starts with':
450
                    if (str_starts_with($strFileName, $arrayPieces[1])) {
451
                        $strLabel = $strCurrentLabel;
452
                    }
453
                    break;
454
                default:
455
                    throw \RuntimeException('Unknown/missconfigured rule given'
0 ignored issues
show
Bug introduced by
The function RuntimeException was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

455
                    throw /** @scrutinizer ignore-call */ \RuntimeException('Unknown/missconfigured rule given'
Loading history...
456
                            . ', please ensure only proper rules ('
457
                            . 'that is one of these values "' . implode('", "', $arrayKnownRules) . '"'
458
                            . ') are configured in your custom class...');
459
                    break;
460
            }
461
        }
462
        return $strLabel;
463
    }
464
465
    protected function uploadElectronicInvoicesFromFolder(): void
466
    {
467
        $this->getServerDiscutionValidations();
468
        $arrayHttpHeader  = $this->buildHeaderAsArray();
469
        $intFileFoundNo   = 0;
470
        $intFileProcessed = 0;
471
        $arrayFiles       = new \RecursiveDirectoryIterator($this->arraySolutionCustomSettings['Generated XML'], \FilesystemIterator::SKIP_DOTS);
472
        foreach ($arrayFiles as $strCrtFile) {
473
            if ($strCrtFile->isFile()) { // only Files are relevant for processing
474
                if ($intFileFoundNo === 0) { // authorization is only needed for 1st file
475
                    $this->authorizeConnectionToLegalAuthority();
476
                }
477
                $strRawUrl             = $this->decideRelevantUniformResourceLocatorForUpload($strCrtFile->getRealPath());
478
                $strRelevantUrl        = $this->arraySettings['Infrastructure']['RO']['Servers']['Content']['OAuth2']
479
                    . $this->arraySolutionCustomSettings['StringElectronicInvoiceEnvironment']
480
                    . $strRawUrl;
481
                error_log(vsprintf('I will be uploading content of %s file to %s url', [
482
                    $strCrtFile->getRealPath(),
483
                    $strRelevantUrl,
484
                ]));
485
                $xmlCurrentFileContent = $this->getFileJsonContent($strCrtFile->getPath(), $strCrtFile->getRealPath());
486
                // sent XML content using CURL and capture feedback
487
                $arrayFeedback         = $this->getContentFromUrlThroughCurl($strRelevantUrl, [
488
                    'HttpHeader' => $arrayHttpHeader,
489
                    'PostFields' => $xmlCurrentFileContent,
490
                ]);
491
                error_log(json_encode($arrayFeedback));
492
                if ($arrayFeedback['errNo'] === 0) {
493
                    $arrayResponse = json_decode(json_encode(simplexml_load_string($arrayFeedback['response'])), JSON_OBJECT_AS_ARRAY);
0 ignored issues
show
Bug introduced by
danielgp\efactura\JSON_OBJECT_AS_ARRAY of type integer is incompatible with the type boolean|null expected by parameter $associative of json_decode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

493
                    $arrayResponse = json_decode(json_encode(simplexml_load_string($arrayFeedback['response'])), /** @scrutinizer ignore-type */ JSON_OBJECT_AS_ARRAY);
Loading history...
494
                    error_log('Complete content of response is: ' . json_encode($arrayResponse));
495
                    error_log(vsprintf('File %s has been sucessfully loaded with %u index', [
496
                        $strCrtFile->getRealPath(),
497
                        $arrayResponse['@attributes']['index_incarcare'],
498
                    ]));
499
                    // if response has no error move the file to processed folder
500
                    rename($strCrtFile->getRealPath(), $this->arraySolutionCustomSettings['Uploaded XML']
501
                        . $strCrtFile->getBasename());
502
                    $intFileProcessed++;
503
                }
504
                $intFileFoundNo++;
505
            }
506
        }
507
        $this->exposeFeedbackOnFileProcessed($intFileFoundNo, $intFileProcessed);
508
    }
509
}
510