Test Failed
Push — develop ( f6d190...8ff4ed )
by Daniel
04:04
created

FileUploadAction::__invoke()   B

Complexity

Conditions 9
Paths 8

Size

Total Lines 58
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 28
nc 8
nop 3
dl 0
loc 58
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Entity\Component\FileInterface;
9
use Silverback\ApiComponentBundle\FIle\Uploader\FileUploader;
10
use Symfony\Component\HttpFoundation\BinaryFileResponse;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
use Symfony\Component\PropertyAccess\PropertyAccess;
14
use Symfony\Component\Routing\Annotation\Route;
15
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
16
use Symfony\Component\Routing\RequestContext;
17
use Symfony\Component\Serializer\SerializerInterface;
18
19
class FileUploadAction
20
{
21
    private $urlMatcher;
22
    private $itemDataProvider;
23
    private $uploader;
24
    private $serializer;
25
26
    public function __construct(
27
        UrlMatcherInterface $urlMatcher,
28
        ItemDataProviderInterface $itemDataProvider,
29
        FileUploader $uploader,
30
        SerializerInterface $serializer
31
    ) {
32
        $this->urlMatcher = $urlMatcher;
33
        $this->itemDataProvider = $itemDataProvider;
34
        $this->uploader = $uploader;
35
        $this->serializer = $serializer;
36
    }
37
38
    /**
39
     * @param Request $request
40
     * @param string $field
41
     * @param string $id
42
     * @Route(
43
     *     name="files_upload",
44
     *     path="/files/{field}/{id}.{_format}",
45
     *     requirements={"field"="\w+", "id"=".+"},
46
     *     defaults={"_format"="jsonld"},
47
     *     methods={"POST", "PUT", "GET"}
48
     * )
49
     * @return Response
50
     */
51
    public function __invoke(Request $request, string $field, string $id)
52
    {
53
        $contentType = $request->headers->get('CONTENT_TYPE');
54
        $_format = $request->attributes->get('_format') ?: $request->getFormat($contentType);
55
56
        /**
57
         * MATCH THE ID TO A ROUTE TO FIND RESOURCE CLASS AND ID
58
         * @var array|null $route
59
         */
60
        $ctx = new RequestContext();
61
        $ctx->fromRequest($request);
62
        $ctx->setMethod('GET');
63
        $this->urlMatcher->setContext($ctx);
64
        $route = $this->urlMatcher->match($id);
65
        if (empty($route)) {
66
            return new Response(sprintf('No route found for id %s', $id), Response::HTTP_BAD_REQUEST);
67
        }
68
69
        /**
70
         * GET THE ENTITY
71
         */
72
        $entity = $this->itemDataProvider->getItem($route['_api_resource_class'], $route['id']);
73
        if (!$entity) {
74
            return new Response(sprintf('Entity not found from provider %s (ID: %s)', $route['_api_resource_class'], $route['id']), Response::HTTP_BAD_REQUEST);
75
        }
76
        if (!($entity instanceof FileInterface)) {
77
            return new Response(sprintf('Provider %s does not implement %s', $route['_api_resource_class'], FileInterface::class), Response::HTTP_BAD_REQUEST);
78
        }
79
80
        if ($request->getMethod() === 'GET') {
81
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
82
            $filePath = $propertyAccessor->getValue($entity, $field);
83
            return new BinaryFileResponse($filePath);
84
        }
85
86
        /**
87
         * CHECK WE HAVE A FILE - WASTE OF TIME DOING ANYTHING ELSE OTHERWISE
88
         */
89
        if (!$request->files->count()) {
90
            return new Response('No files have been submitted', Response::HTTP_BAD_REQUEST);
91
        }
92
93
        /**
94
         * UPLOAD THE FILE
95
         */
96
        $files = $request->files->all();
97
        try {
98
            $entity = $this->uploader->upload($entity, $field, reset($files));
99
        } catch (InvalidArgumentException $exception) {
100
            return new Response($exception->getMessage(), Response::HTTP_BAD_REQUEST);
101
        } catch (RuntimeException $exception) {
102
            return new Response($exception->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
103
        }
104
105
        /**
106
         * Return the entity back in the format requested
107
         */
108
        return new Response($this->serializer->serialize($entity, $_format, ['groups' => ['component']]), Response::HTTP_OK);
109
    }
110
}
111