Skip to content
This repository has been archived by the owner on Dec 20, 2021. It is now read-only.

Commit

Permalink
feat(Response): add getRouterBinaryFileResponse() to serve files
Browse files Browse the repository at this point in the history
  • Loading branch information
clement trumpff committed Apr 30, 2020
1 parent 6d96ed1 commit 4f8e338
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RREST;

use League\JsonGuard;
use RREST\Response\FileConfiguration;
use RREST\Validator\JsonValidator;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
Expand All @@ -18,6 +19,11 @@ class Response
*/
protected $content;

/**
* @var FileConfiguration
*/
protected $fileConfiguration;

/**
* @var string
*/
Expand Down Expand Up @@ -62,6 +68,11 @@ public function __construct(RouterInterface $router, $format, $statusCode)
$this->setStatusCode($statusCode);
}

public function setFileConfiguration(FileConfiguration $fileConfiguration)
{
$this->fileConfiguration = $fileConfiguration;
}

/**
* @return string
*/
Expand Down Expand Up @@ -220,6 +231,19 @@ public function getRouter()
*/
public function getRouterResponse($autoSerializeContent = true)
{
if ($this->hasFileConfiguration()) {
$headers = array_merge(
$this->getConfiguredHeaders(),
$this->fileConfiguration->getHttpHeadersForFileResponse()
);
return $this->router->getBinaryFileResponse(
$this->fileConfiguration->getFilePath(),
$this->getConfiguredHeaderstatusCode(),
$headers,
$this->fileConfiguration->getDeleteFileAfterSend()
);
}

$content = $this->getContent();
if ($autoSerializeContent) {
$content = $this->serialize($content, $this->getFormat());
Expand All @@ -230,6 +254,11 @@ public function getRouterResponse($autoSerializeContent = true)
);
}

private function hasFileConfiguration(): bool
{
return !empty($this->fileConfiguration);
}

/**
* @param mixed $data
* @param string $format
Expand Down
77 changes: 77 additions & 0 deletions src/Response/FileConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace RREST\Response;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

final class FileConfiguration
{
/**
* @var string
*/
private $headerContentDisposition;

/**
* @var int
*/
private $headerContentLength;

/**
* @var bool
*/
private $deleteFileAfterSend;

/**
* @var string
*/
private $filePath;

public function __construct(string $filePath, bool $deleteFileAfterSend = false)
{
$this->buildHeaderContentDisposition(pathinfo($filePath, PATHINFO_BASENAME));
$this->headerContentLength = filesize($filePath);
$this->deleteFileAfterSend = $deleteFileAfterSend;
$this->filePath = $filePath;
}

private function buildHeaderContentDisposition(string $filename)
{
$symfonyResponse = new Response();
$this->headerContentDisposition = $symfonyResponse->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$filename
);
}

public function setFile(string $filePath)
{
if (!is_readable($filePath)) {
throw new \RuntimeException('Provided file is not readable or doesn\'t exists.');
}
if (!is_file($filePath)) {
throw new \RuntimeException('Provided file is not a file');
}
$this->filePath = $filePath;
}

public function getFilePath(): string
{
return $this->filePath;
}

public function getDeleteFileAfterSend(): bool
{
return $this->deleteFileAfterSend;
}

public function getHttpHeadersForFileResponse(): array
{
return [
'Content-disposition' => $this->headerContentDisposition,
'Content-Length' => $this->headerContentLength,
];
}
}
11 changes: 11 additions & 0 deletions src/Router/RouterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,15 @@ public function setPayloadBodyValue($payloadBodyJSON);
* @return mixed
*/
public function getResponse($content = '', $statusCode = 200, $headers = array());

/**
* The router response to serve a file to be downloaded.
*
* @param string $filepath
* @param int $statusCode
* @param string[] $headers
*
* @return mixed
*/
public function getBinaryFileResponse(string $filePath, $statusCode = 200, $headers = array(), bool $deleteFileAfterSend = false);
}
13 changes: 13 additions & 0 deletions src/Router/Silex.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace RREST\Router;

use Symfony\Component\HttpFoundation\BinaryFileResponse as HttpFoundationBinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response as HttpFoundationResponse;
use RREST\Response;
Expand Down Expand Up @@ -115,4 +116,16 @@ public function getResponse($content = '', $statusCode = 200, $headers = array()
{
return new HttpFoundationResponse($content, $statusCode, $headers);
}

/**
* {@inheritdoc}
*/
public function getBinaryFileResponse(string $filePath, $statusCode = 200, $headers = array(), bool $deleteFileAfterSend = false)
{
$response = new HttpFoundationBinaryFileResponse($filePath, $statusCode, $headers);
if (!empty($deleteFileAfterResponse)) {
$response->deleteFileAfterSend(true);
}
return $response;
}
}
10 changes: 10 additions & 0 deletions tests/units/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require_once __DIR__.'/boostrap.php';

use atoum;
use RREST\Response\FileConfiguration;
use RREST\Router\Silex;
use Silex\Application;

Expand Down Expand Up @@ -48,6 +49,15 @@ function () {
;
}

public function setFileConfiguration()
{
$this
->given($this->testedInstance)
->and($this->testedInstance->setFileConfiguration(new FileConfiguration('xxx')))
->object($this->testedInstance)
->isInstanceOf('RREST\Response');
}

public function testGetConfiguredHeaders()
{
$this->newTestedInstance($this->router, 'json', 200);
Expand Down
9 changes: 9 additions & 0 deletions tests/units/Router/Silex.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ public function testGetResponse()
->isInstanceOf('Symfony\Component\HttpFoundation\Response');
}

public function testGetBinaryFileResponse()
{
$this->newTestedInstance($this->app);
$this
->given($this->testedInstance)
->object($this->testedInstance->getBinaryFileResponse(__DIR__.'/../../fixture/song.xml'))
->isInstanceOf('Symfony\Component\HttpFoundation\BinaryFileResponse');
}

public function testGetPayloadBodyValue()
{
$this->newTestedInstance($this->app);
Expand Down

0 comments on commit 4f8e338

Please sign in to comment.