Passed
Pull Request — master (#20)
by
unknown
07:09
created

ShippingExportDownloadLabelAction::__invoke()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
dl 0
loc 19
rs 9.9
c 1
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
/*
4
 * This file has been created by developers from BitBag.
5
 * Feel free to contact us once you face any issues or want to start
6
 * another great project.
7
 * You can find more information about us on https://bitbag.io and write us
8
 * an email on [email protected].
9
 */
10
11
declare(strict_types=1);
12
13
namespace BitBag\SyliusShippingExportPlugin\Controller;
14
15
use BitBag\SyliusShippingExportPlugin\Repository\ShippingExportRepositoryInterface;
16
use Symfony\Component\Filesystem\Filesystem;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
20
use Symfony\Component\HttpFoundation\StreamedResponse;
21
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
22
use Webmozart\Assert\Assert;
23
24
final class ShippingExportDownloadLabelAction
25
{
26
    /** @var Filesystem */
27
    private $filesystem;
28
29
    /** @var ShippingExportRepositoryInterface */
30
    private $repository;
31
32
    /** @var string */
33
    private $shippingLabelsPath;
34
35
    public function __construct(
36
        Filesystem $filesystem,
37
        ShippingExportRepositoryInterface $repository,
38
        string $shippingLabelsPath
39
    ) {
40
        $this->filesystem = $filesystem;
41
        $this->repository = $repository;
42
        $this->shippingLabelsPath = $shippingLabelsPath;
43
    }
44
45
    public function __invoke(Request $request): Response
46
    {
47
        $shippingExport = $this->repository->find($request->get('id'));
48
        Assert::notNull($shippingExport);
49
        $labelPath = $shippingExport->getLabelPath();
50
        Assert::notNull($labelPath);
51
52
        if (dirname($labelPath) !== $this->shippingLabelsPath) {
53
            throw new NotFoundHttpException(sprintf('Directory traversal is not allowed for label "%s"', $labelPath));
54
        }
55
56
        if (false === $this->filesystem->exists($labelPath)) {
57
            throw new NotFoundHttpException();
58
        }
59
60
        $filePathParts = explode(\DIRECTORY_SEPARATOR, $labelPath);
61
        $labelName = end($filePathParts);
62
63
        return $this->createStreamedResponse($labelPath, $labelName);
64
    }
65
66
    private function createStreamedResponse(string $filePath, string $fileName): StreamedResponse
67
    {
68
        $response = new StreamedResponse(
69
            function () use ($filePath): void {
70
                $outputStream = fopen('php://output', 'wb');
71
                Assert::resource($outputStream);
72
                $fileStream = fopen($filePath, 'rb');
73
                Assert::resource($fileStream);
74
                stream_copy_to_stream($fileStream, $outputStream);
75
            }
76
        );
77
78
        $disposition = $response->headers->makeDisposition(
79
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
80
            $fileName
81
        );
82
        $response->headers->set('Content-Disposition', $disposition);
83
84
        return $response;
85
    }
86
}
87