Passed
Push — develop ( c023ce...9576d7 )
by Daniel
06:40
created

FileUpload::__invoke()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 45
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 18
nc 6
nop 3
dl 0
loc 45
ccs 0
cts 18
cp 0
crap 56
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
namespace Silverback\ApiComponentBundle\Controller;
4
5
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
6
use InvalidArgumentException;
7
use RuntimeException;
8
use Silverback\ApiComponentBundle\Uploader\FileUploader;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpFoundation\Response;
11
use Symfony\Component\Routing\Annotation\Route;
12
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
13
use Symfony\Component\Serializer\SerializerInterface;
14
15
class FileUpload
16
{
17
    private $urlMatcher;
18
    private $itemDataProvider;
19
    private $uploader;
20
    private $serializer;
21
22
    public function __construct(
23
        UrlMatcherInterface $urlMatcher,
24
        ItemDataProviderInterface $itemDataProvider,
25
        FileUploader $uploader,
26
        SerializerInterface $serializer
27
    )
28
    {
29
        $this->urlMatcher = $urlMatcher;
30
        $this->itemDataProvider = $itemDataProvider;
31
        $this->uploader = $uploader;
32
        $this->serializer = $serializer;
33
    }
34
35
    /**
36
     * @param Request $request
37
     * @param string $field
38
     * @param string $id
39
     * @Route(
40
     *     name="files_upload",
41
     *     path="/files/{field}/{id}.{_format}",
42
     *     requirements={"field"="\w+", "id"=".+"},
43
     *     defaults={"_format"="jsonld"},
44
     *     methods={"POST", "PUT"}
45
     * )
46
     * @return Response
47
     * @throws \ApiPlatform\Core\Exception\ResourceClassNotSupportedException
48
     */
49
    public function __invoke(Request $request, string $field, string $id)
50
    {
51
        $contentType = $request->headers->get('CONTENT_TYPE');
52
        $_format = $request->attributes->get('_format') ?: $request->getFormat($contentType);
53
54
        /**
55
         * CHECK WE HAVE A FILE - WASTE OF TIME DOING ANYTHING ELSE OTHERWISE
56
         */
57
        if (!$request->files->count()) {
58
            return new Response('No files have been submitted', Response::HTTP_BAD_REQUEST);
59
        }
60
61
        /**
62
         * MATCH THE ID TO A ROUTE TO FIND RESOURCE CLASS AND ID
63
         * @var array|null $route
64
         */
65
        $route = $this->urlMatcher->match($id);
66
        if (!$route) {
67
            return new Response(sprintf('No route found for id %s', $id), Response::HTTP_BAD_REQUEST);
68
        }
69
70
        /**
71
         * GET THE ENTITY
72
         */
73
        $entity = $this->itemDataProvider->getItem($route['_api_resource_class'], $route['id']);
74
        if (!$entity) {
75
            return new Response(sprintf('Entity not found from provider %s (ID: %s)', $route['_api_resource_class'], $route['id']), Response::HTTP_BAD_REQUEST);
76
        }
77
78
        /**
79
         * UPLOAD THE FILE
80
         */
81
        $files = $request->files->all();
82
        try {
83
            $entity = $this->uploader->upload($entity, $field, reset($files));
84
        }catch(InvalidArgumentException $exception) {
85
            return new Response($exception->getMessage(), Response::HTTP_BAD_REQUEST);
86
        }catch (RuntimeException $exception) {
87
            return new Response($exception->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
88
        }
89
90
        /**
91
         * Return the entity back in the format requested
92
         */
93
        return new Response($this->serializer->serialize($entity, $_format, ['groups' => ['component']]), Response::HTTP_OK);
94
    }
95
}
96