ShippingExportDownloadLabelAction   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 61
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 5
eloc 30
dl 0
loc 61
rs 10
c 1
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __invoke() 0 19 3
A __construct() 0 8 1
A createStreamedResponse() 0 19 1
1
<?php
2
3
/*
4
 * This file was created by developers working at BitBag
5
 * Do you need more information about us and what we do? Visit our https://bitbag.io website!
6
 * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career
7
*/
8
9
declare(strict_types=1);
10
11
namespace BitBag\SyliusShippingExportPlugin\Controller;
12
13
use BitBag\SyliusShippingExportPlugin\Repository\ShippingExportRepositoryInterface;
14
use Symfony\Component\Filesystem\Filesystem;
15
use Symfony\Component\HttpFoundation\Request;
16
use Symfony\Component\HttpFoundation\Response;
17
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
18
use Symfony\Component\HttpFoundation\StreamedResponse;
19
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
20
use Webmozart\Assert\Assert;
21
22
final class ShippingExportDownloadLabelAction
23
{
24
    /** @var Filesystem */
25
    private $filesystem;
26
27
    /** @var ShippingExportRepositoryInterface */
28
    private $repository;
29
30
    /** @var string */
31
    private $shippingLabelsPath;
32
33
    public function __construct(
34
        Filesystem $filesystem,
35
        ShippingExportRepositoryInterface $repository,
36
        string $shippingLabelsPath
37
    ) {
38
        $this->filesystem = $filesystem;
39
        $this->repository = $repository;
40
        $this->shippingLabelsPath = $shippingLabelsPath;
41
    }
42
43
    public function __invoke(Request $request): Response
44
    {
45
        $shippingExport = $this->repository->find($request->get('id'));
46
        Assert::notNull($shippingExport);
47
        $labelPath = $shippingExport->getLabelPath();
48
        Assert::notNull($labelPath);
49
50
        if (dirname($labelPath) !== $this->shippingLabelsPath) {
51
            throw new NotFoundHttpException(sprintf('Directory traversal is not allowed for label "%s"', $labelPath));
52
        }
53
54
        if (false === $this->filesystem->exists($labelPath)) {
55
            throw new NotFoundHttpException();
56
        }
57
58
        $filePathParts = explode(\DIRECTORY_SEPARATOR, $labelPath);
59
        $labelName = end($filePathParts);
60
61
        return $this->createStreamedResponse($labelPath, $labelName);
62
    }
63
64
    private function createStreamedResponse(string $filePath, string $fileName): StreamedResponse
65
    {
66
        $response = new StreamedResponse(
67
            function () use ($filePath): void {
68
                $outputStream = fopen('php://output', 'wb');
69
                Assert::resource($outputStream);
70
                $fileStream = fopen($filePath, 'rb');
71
                Assert::resource($fileStream);
72
                stream_copy_to_stream($fileStream, $outputStream);
73
            }
74
        );
75
76
        $disposition = $response->headers->makeDisposition(
77
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
78
            $fileName
79
        );
80
        $response->headers->set('Content-Disposition', $disposition);
81
82
        return $response;
83
    }
84
}
85