Passed
Push — master ( a040f6...1671cd )
by Jan
04:44
created

SEPAXMLExportResult   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 46
dl 0
loc 157
rs 10
c 2
b 0
f 0
wmc 24

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getXMLFiles() 0 15 3
A getSEPAExports() 0 3 1
A offsetGet() 0 3 1
A count() 0 3 1
A persistSEPAExports() 0 4 2
A __construct() 0 22 6
A getGroupUlid() 0 3 1
A offsetExists() 0 3 1
A generateFilename() 0 3 1
A offsetUnset() 0 3 1
A offsetSet() 0 3 1
A getDownloadResponse() 0 14 3
A getXMLString() 0 10 2
1
<?php
2
/*
3
 * Copyright (C) 2020  Jan Böhmer
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Affero General Public License as published
7
 * by the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Affero General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Affero General Public License
16
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
namespace App\Helpers\SEPAXML;
20
21
use App\Entity\SEPAExport;
22
use App\Helpers\ZIPBinaryFileResponseFacade;
23
use Doctrine\ORM\EntityManagerInterface;
24
use JetBrains\PhpStorm\Internal\LanguageLevelTypeAware;
25
use JetBrains\PhpStorm\Internal\TentativeType;
0 ignored issues
show
Bug introduced by
The type JetBrains\PhpStorm\Internal\TentativeType was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
use Symfony\Component\HttpFoundation\BinaryFileResponse;
27
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
28
use Symfony\Component\Uid\Ulid;
29
30
final class SEPAXMLExportResult implements \Countable, \ArrayAccess
31
{
32
    /** @var SEPAExport[] */
33
    private $sepa_exports;
34
35
    /** @var Ulid */
36
    private $group_ulid;
37
38
    /**
39
     * @param  SEPAExport[]  $sepa_exports
40
     */
41
    public function __construct(array $sepa_exports)
42
    {
43
        if (count($sepa_exports) === 0) {
44
            throw new \InvalidArgumentException('$sepa_exports must not be empty!');
45
        }
46
47
        //Perform some checks on the sepa exports
48
        foreach($sepa_exports as $sepa_export) {
49
            if (!$sepa_export instanceof SEPAExport) {
50
                throw new \InvalidArgumentException('$sepa_exports must all be of type SEPAExport!');
51
            }
52
            if ($sepa_export->getXmlFile() === null) {
53
                throw new \InvalidArgumentException('Every Export in $sepa_exports must have an associated XML file!');
54
            }
55
        }
56
57
        $this->sepa_exports = $sepa_exports;
58
        $this->group_ulid = new Ulid();
59
60
        //Apply group ulid to all SEPA exports
61
        foreach ($this->sepa_exports as $export) {
62
            $export->setGroupUlid($this->group_ulid);
63
        }
64
    }
65
66
    public function getGroupUlid(): Ulid
67
    {
68
        return $this->group_ulid;
69
    }
70
71
    /**
72
     * Returns the number of SEPAExports contained
73
     * @return int|void
74
     */
75
    public function count()
76
    {
77
        return count($this->sepa_exports);
78
    }
79
80
81
    /**
82
     * Returns the SEPA Exports contained in this result
83
     * @return SEPAExport[]
84
     */
85
    public function getSEPAExports(): array
86
    {
87
        return $this->sepa_exports;
88
    }
89
90
    /**
91
     * Returns an array of all XML files contained in this result.
92
     * The array keys contains suggested filenames for the files
93
     * @return \SplFileInfo[]
94
     */
95
    public function getXMLFiles(): array
96
    {
97
        $result = [];
98
99
        foreach ($this->sepa_exports as $sepa_export) {
100
            $filename = $this->generateFilename($sepa_export);
101
            //Ensure that filename is not existing yet (add an increment suffix)
102
            $i = 2;
103
            while (isset($result[$filename])) {
104
                $filename = basename($filename) . '_' . sprintf("%d", $i++) . '.xml';
105
            }
106
            $result[$filename] = $sepa_export->getXmlFile();
107
        }
108
109
        return $result;
110
    }
111
112
    /**
113
     * Returns an array of the contained XML files as strings.
114
     * The array keys contains suggested filenames for the files.
115
     * @return string[]
116
     */
117
    public function getXMLString(): array
118
    {
119
        $result = [];
120
        $files = $this->getXMLFiles();
121
122
        foreach ($files as $filename => $file) {
123
            $result[$filename] = file_get_contents($file->getPathname());
124
        }
125
126
        return $result;
127
    }
128
129
    /**
130
     * Generates a download response for the contained XML files. If only a single XML is contained, it will be downloaded
131
     * as XML file, otherwise as ZIP containing all files.
132
     * @param  string  $disposition_filename The filename that should be used (without extension)
133
     * @param  bool  $force_zip
134
     * @return BinaryFileResponse
135
     */
136
    public function getDownloadResponse(string $disposition_filename, bool $force_zip = false): BinaryFileResponse
137
    {
138
        //If we have only one file, we can just return the file
139
        if ($force_zip === false && $this->count() === 1) {
140
            $response = new BinaryFileResponse($this->sepa_exports[0]->getXmlFile());
141
            $response->setPrivate();
142
            $response->headers->set('Content-Type', 'application/xml');
143
            $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $disposition_filename . '.xml');
144
        } else { //Otherwise we download the file as ZIP
145
            $response = ZIPBinaryFileResponseFacade::createZIPResponseFromFiles($this->getXMLFiles(), $disposition_filename . '.zip');
146
            $response->headers->set('Content-Type', 'application/zip');
147
        }
148
149
        return $response;
150
    }
151
152
    /**
153
     * Persist all contained SEPAExport entities using the given EntityManager.
154
     * @param  EntityManagerInterface  $entityManager
155
     * @return void
156
     */
157
    public function persistSEPAExports(EntityManagerInterface $entityManager): void
158
    {
159
        foreach($this->sepa_exports as $sepa_export) {
160
            $entityManager->persist($sepa_export);
161
        }
162
    }
163
164
    private function generateFilename(SEPAExport $export): string
165
    {
166
        return $export->getDescription() . '_' . $export->getCreationDate()->format('Y-m-d-His') . '.xml';
167
    }
168
169
    public function offsetExists($offset): bool
170
    {
171
        return isset($this->sepa_exports[$offset]);
172
    }
173
174
    public function offsetGet($offset): SEPAExport
175
    {
176
        return $this->sepa_exports[$offset];
177
    }
178
179
    public function offsetSet($offset, $value)
180
    {
181
        throw new \LogicException('Write access is not allowed!');
182
    }
183
184
    public function offsetUnset($offset)
185
    {
186
        throw new \LogicException('Write access is not allowed!');
187
    }
188
}