Passed
Push — master ( bbf25b...ac0443 )
by Ludwig
17:34
created

DocumentEndpoint::createMultiple()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 20
nc 6
nop 5
dl 0
loc 33
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of datamolino client.
5
 *
6
 * (c) 2018 cwd.at GmbH <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cwd\Datamolino\Endpoints;
15
16
use Cwd\Datamolino\Model\Document;
17
use Cwd\Datamolino\Model\DocumentFile;
18
use Cwd\Datamolino\Model\OriginalFile;
19
use Cwd\Datamolino\Model\UploadFile;
20
use Symfony\Component\Finder\Finder;
21
use Symfony\Component\HttpFoundation\File\File as FileInfo;
22
use Webmozart\Assert\Assert;
23
24
class DocumentEndpoint extends AbstractEndpoint
25
{
26
    public const PAYLOAD_LIMIT = 1024 * 1024 * 20; // 20MB
27
    const ENDPOINT = 'documents';
28
29
    /**
30
     * @param string|array|Finder $source    Location of Files or Finder Instance or array of SPLFileInfo
31
     * @param int                 $agendaId
32
     * @param string              $type
33
     * @param bool                $fileSplit
34
     * @param bool                $lacyLoad
35
     *
36
     * @return Document[]
37
     *
38
     * @throws \Http\Client\Exception
39
     * @throws \LogicException
40
     */
41
    public function createMultiple($source, int $agendaId, string $type = Document::DOCTYPE_PURCHASE, $fileSplit = false, $lacyLoad = false): array
42
    {
43
        $currentFileSize = 0;
44
        $resultDocuments = [];
45
        $documentFiles = [];
46
47
        $files = $this->retrieveFiles($source);
48
49
        foreach ($files as $file) {
50
            $documentFile = new DocumentFile();
51
            $documentFile->setType($type)
52
                ->setAgendaId($agendaId)
53
                ->setFileSplit($fileSplit);
54
55
            $mimeType = (new FileInfo($file->getPathname()))->getMimeType();
56
            $currentFileSize += $file->getSize();
57
            $documentFile->setFile(
58
                new UploadFile($file->getFilename(), $mimeType, file_get_contents($file->getPathname()))
59
            );
60
61
            $documentFiles[] = $documentFile;
62
63
            if ($currentFileSize >= self::PAYLOAD_LIMIT) {
64
                $resultDocuments += $this->send($documentFiles, $lacyLoad);
65
                $documentFiles = [];
66
            }
67
        }
68
69
        if (count($documentFiles) > 0) {
70
            $resultDocuments += $this->send($documentFiles, $lacyLoad);
71
        }
72
73
        return $resultDocuments;
74
    }
75
76
    /**
77
     * @param string $fileUri
78
     * @param int    $agendaId
79
     * @param string $filename
80
     * @param string $type
81
     * @param bool   $fileSplit
82
     * @param bool   $lacyLoad
83
     *
84
     * @return Document
85
     *
86
     * @throws \Http\Client\Exception
87
     */
88
    public function create($fileUri, $agendaId, $filename, $type = Document::DOCTYPE_PURCHASE, $fileSplit = false, $lacyLoad = false): Document
89
    {
90
        $file = new FileInfo($fileUri);
91
        $mimeType = $file->getMimeType();
92
93
        $documentFile = new DocumentFile();
94
        $documentFile->setType($type)
95
            ->setAgendaId($agendaId)
96
            ->setFileSplit($fileSplit)
97
            ->setFile(
98
                new UploadFile($file->getFilename(), $mimeType, file_get_contents($file->getPathname()))
99
            )
100
        ;
101
102
        return current($this->send([$documentFile], $lacyLoad));
103
    }
104
105
    /**
106
     * @param DocumentFile[] $files
107
     *
108
     * @return array
109
     *
110
     * @throws \Http\Client\Exception
111
     */
112
    public function send(array $files, $lacyLoad = true)
113
    {
114
        $payload = $this->getClient()->getSerializer()->serialize(['documents' => $files], 'json');
115
        $documents = $this->getClient()->call($payload, null, self::ENDPOINT, Document::class, true, 'POST');
116
117
        if ($lacyLoad) {
118
            $ids = [];
119
            /** @var Document $document */
120
            foreach ($documents as $document) {
121
                $ids[] = $document->getId();
122
            }
123
124
            return $this->find(current($files)->getAgendaId(), $ids);
125
        }
126
127
        return $documents;
128
    }
129
130
    public function get(int $id): Document
131
    {
132
        return $this->getClient()->call(null, $id, self::ENDPOINT, Document::class, false, 'GET');
133
    }
134
135
    /**
136
     * @param $document
137
     *
138
     * @return OriginalFile
139
     *
140
     * @throws \Http\Client\Exception
141
     */
142
    public function getOriginalFile($document): OriginalFile
143
    {
144
        if ($document instanceof Document) {
145
            $document = $document->getId();
146
        }
147
148
        return $this->getClient()->call(null, $document, self::ENDPOINT, OriginalFile::class, false, 'GET', '/original_file');
149
    }
150
151
    /**
152
     * @param int|Document $document
153
     *
154
     * @throws \Http\Client\Exception
155
     */
156
    public function delete($document): void
157
    {
158
        if ($document instanceof Document) {
159
            $document = $document->getId();
160
        }
161
162
        $this->getClient()->call(null, $document, self::ENDPOINT, null, false, 'DELETE');
163
    }
164
165
    /**
166
     * @param Document|int $document
167
     * @param string       $text
168
     *
169
     * @throws \Http\Client\Exception
170
     */
171
    public function repair($document, $text): void
172
    {
173
        if ($document instanceof Document) {
174
            $document = $document->getId();
175
        }
176
177
        $this->getClient()->call(null, $document, self::ENDPOINT, OriginalFile::class, false, 'POST', sprintf(
178
                '/repair?repair_description=%s', urlencode($text))
179
        );
180
    }
181
182
    /**
183
     * @param int            $agendaId
184
     * @param array          $ids
185
     * @param \DateTime|null $modifiedSince
186
     * @param array          $states
187
     * @param int            $page
188
     * @param string         $type
189
     *
190
     * @return mixed
191
     *
192
     * @throws \Http\Client\Exception
193
     */
194
    public function find($agendaId, array $ids = [], ?\DateTime $modifiedSince = null, array $states = [], $page = 1, $type = Document::DOCTYPE_PURCHASE)
195
    {
196
        $queryString = [
197
            sprintf('agenda_id=%s', $agendaId),
198
            sprintf('page=%s', $page),
199
            sprintf('type=%s', $type),
200
        ];
201
202
        if (null !== $modifiedSince) {
203
            $queryString[] = sprintf('modified_since=%s', $modifiedSince->format('Y-m-d\TH:i:s\Z'));
204
        }
205
206
        if (count($states) > 0) {
207
            foreach ($states as $state) {
208
                $queryString[] = sprintf('state[]=%s', $state);
209
            }
210
        }
211
212
        if (count($ids) > 0) {
213
            foreach ($ids as $id) {
214
                $queryString[] = sprintf('ids[]=%s', $id);
215
            }
216
        }
217
218
        return $this->getClient()->call(null, sprintf('?%s', implode('&', $queryString)), self::ENDPOINT, Document::class, true, 'GET');
219
    }
220
221
    /**
222
     * @param string|array|Finder $filesProvider Location of Files or Finder Instance or array of SPLFileInfo
223
     *
224
     * @throws \LogicException
225
     *
226
     * @return \SplFileInfo[]
227
     */
228
    private function retrieveFiles($filesProvider): iterable
229
    {
230
        if ($filesProvider instanceof Finder) {
231
            return $filesProvider->files();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $filesProvider->files() returns the type Symfony\Component\Finder\Finder which is incompatible with the documented return type SplFileInfo[].
Loading history...
232
        }
233
234
        if (is_string($filesProvider)) {
235
            return (new Finder())->in($filesProvider)->files();
0 ignored issues
show
Bug Best Practice introduced by
The expression return new Symfony\Compo...filesProvider)->files() returns the type Symfony\Component\Finder\Finder which is incompatible with the documented return type SplFileInfo[].
Loading history...
236
        }
237
238
        if (is_array($filesProvider)) {
0 ignored issues
show
introduced by
The condition is_array($filesProvider) is always true.
Loading history...
239
            Assert::allIsInstanceOf($filesProvider, \SplFileInfo::class, 'When using array all files need to implement SPLFileInfo');
240
241
            return $filesProvider;
242
        }
243
244
        throw new \LogicException(sprintf('Invalid files provider type: "%s', gettype($filesProvider)));
245
    }
246
}
247