Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ref #11178
- Loading branch information
Showing
13 changed files
with
301 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
|
||
namespace Elgg\Http; | ||
|
||
/** | ||
* Download response builder | ||
* | ||
* @since 5.0 | ||
*/ | ||
class DownloadResponse extends OkResponse { | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getHeaders() { | ||
$headers = parent::getHeaders(); | ||
|
||
if (!isset($headers['Content-Type'])) { | ||
$headers['Content-Type'] = 'application/octet-stream; charset=utf-8'; | ||
} | ||
|
||
if (!isset($headers['Cache-Control'])) { | ||
$headers['Cache-Control'] = 'no-store'; | ||
} | ||
|
||
if (!isset($headers['Content-Disposition'])) { | ||
$headers['Content-Disposition'] = 'attachment'; | ||
} | ||
|
||
if (!empty($this->content) && !isset($headers['Content-Length'])) { | ||
$headers['Content-Length'] = strlen((string) $this->content); | ||
} | ||
|
||
return $headers; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function setForwardURL(string $forward_url = REFERRER) { | ||
return $this; | ||
} | ||
|
||
/** | ||
* Set the filename for the download | ||
* | ||
* This will only be applied if the 'Content-Disposition' header isn't already set | ||
* | ||
* @param string $filename The filename when downloaded | ||
* @param bool $inline Is this an inline download (default: false, determines the 'Content-Disposition' header) | ||
* | ||
* @return self | ||
*/ | ||
public function setFilename(string $filename = '', bool $inline = false): static { | ||
if (isset($this->headers['Content-Disposition'])) { | ||
return $this; | ||
} | ||
|
||
$disposition = $inline ? 'inline' : 'attachment'; | ||
|
||
if (!elgg_is_empty($filename)) { | ||
$disposition .= "; filename=\"{$filename}\""; | ||
} | ||
|
||
$this->headers['Content-Disposition'] = $disposition; | ||
|
||
return $this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
engine/tests/phpunit/integration/Elgg/Http/DownloadResponseIntegrationTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?php | ||
|
||
namespace Elgg\Http; | ||
|
||
use Elgg\IntegrationTestCase; | ||
|
||
class DownloadResponseIntegrationTest extends IntegrationTestCase { | ||
|
||
/** | ||
* @dataProvider getDownloadResponseProvider | ||
*/ | ||
public function testGetDownloadResponse(string $content, string $filename = '', bool $inline = false, array $headers = []) { | ||
$response = elgg_download_response($content, $filename, $inline, $headers); | ||
|
||
$this->assertInstanceOf(DownloadResponse::class, $response); | ||
$this->assertEquals($content, $response->getContent()); | ||
|
||
$response_headers = $response->getHeaders(); | ||
$this->assertIsArray($response_headers); | ||
$this->assertArrayHasKey('Content-Disposition', $response_headers); | ||
|
||
if (!isset($headers['Content-Disposition'])) { | ||
if (!empty($filename)) { | ||
$this->assertStringContainsString("filename=\"{$filename}\"", $response_headers['Content-Disposition']); | ||
} else { | ||
$this->assertStringNotContainsString('filename', $response_headers['Content-Disposition']); | ||
} | ||
|
||
if ($inline) { | ||
$this->assertStringContainsString('inline', $response_headers['Content-Disposition']); | ||
} else { | ||
$this->assertStringContainsString('attachment', $response_headers['Content-Disposition']); | ||
} | ||
} | ||
|
||
foreach ($headers as $key => $value) { | ||
$this->assertArrayHasKey($key, $response_headers); | ||
$this->assertEquals($value, $response_headers[$key]); | ||
} | ||
} | ||
|
||
public function getDownloadResponseProvider() { | ||
return [ | ||
['foo'], | ||
['foo', 'bar.txt'], | ||
['foo', 'bar.txt', true], | ||
['foo', 'bar.txt', false, ['Content-Type' => 'text/plain; charset=utf-8']], | ||
['foo', 'bar.txt', false, [ | ||
'Content-Type' => 'text/json; charset=utf-8', | ||
'Content-Disposition' => 'inline; filename="bar.json"', | ||
]], | ||
]; | ||
} | ||
} |
107 changes: 107 additions & 0 deletions
107
engine/tests/phpunit/unit/Elgg/Http/DownloadResponseUnitTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
<?php | ||
|
||
namespace Elgg\Http; | ||
|
||
class DownloadResponseUnitTest extends ResponseUnitTestCase { | ||
|
||
public function getReponseClassName(): string { | ||
return DownloadResponse::class; | ||
} | ||
|
||
public function testCanConstructWihtoutArguments() { | ||
$test_class = $this->getReponseClassName(); | ||
$response = new $test_class(); | ||
|
||
$this->assertEquals('', $response->getContent()); | ||
$this->assertEquals(ELGG_HTTP_OK, $response->getStatusCode()); | ||
$this->assertNull($response->getForwardURL()); | ||
$this->assertEquals([ | ||
'Content-Type' => 'application/octet-stream; charset=utf-8', | ||
'Cache-Control' => 'no-store', | ||
'Content-Disposition' => 'attachment', | ||
], $response->getHeaders()); | ||
} | ||
|
||
public function testCanConstructWithArguments() { | ||
$content = 'foo'; | ||
$status_code = ELGG_HTTP_PARTIAL_CONTENT; | ||
|
||
$test_class = $this->getReponseClassName(); | ||
$response = new $test_class($content, $status_code, REFERRER); | ||
|
||
$this->assertEquals($content, $response->getContent()); | ||
$this->assertEquals($status_code, $response->getStatusCode()); | ||
$this->assertNull($response->getForwardURL()); | ||
$this->assertEquals([ | ||
'Content-Type' => 'application/octet-stream; charset=utf-8', | ||
'Cache-Control' => 'no-store', | ||
'Content-Disposition' => 'attachment', | ||
'Content-Length' => strlen($content), | ||
], $response->getHeaders()); | ||
} | ||
|
||
public function testSetFilename() { | ||
$test_class = $this->getReponseClassName(); | ||
$response = new $test_class(); | ||
|
||
// test attachment | ||
$response->setFilename('foo'); | ||
|
||
$headers = $response->getHeaders(); | ||
$this->assertIsArray($headers); | ||
$this->assertArrayHasKey('Content-Disposition', $headers); | ||
$this->assertStringContainsString('filename="foo"', $headers['Content-Disposition']); | ||
$this->assertStringContainsString('attachment', $headers['Content-Disposition']); | ||
|
||
// test inline | ||
$response->setHeaders([]); // need to clean headers | ||
$response->setFilename('bar', true); | ||
|
||
$headers = $response->getHeaders(); | ||
$this->assertIsArray($headers); | ||
$this->assertArrayHasKey('Content-Disposition', $headers); | ||
$this->assertStringContainsString('filename="bar"', $headers['Content-Disposition']); | ||
$this->assertStringContainsString('inline', $headers['Content-Disposition']); | ||
|
||
// test trying to overrule filename fails | ||
$response->setFilename('notset'); | ||
|
||
$headers = $response->getHeaders(); | ||
$this->assertIsArray($headers); | ||
$this->assertArrayHasKey('Content-Disposition', $headers); | ||
$this->assertStringNotContainsString('filename="notset"', $headers['Content-Disposition']); | ||
$this->assertStringNotContainsString('attachment', $headers['Content-Disposition']); | ||
} | ||
|
||
/** | ||
* Overruled tests from parent because of changes to the DownloadResponse | ||
*/ | ||
|
||
/** | ||
* @dataProvider validForwardURLsProvider | ||
*/ | ||
public function testCanSetForwardURL($value) { | ||
$test_class = $this->getReponseClassName(); | ||
$response = new $test_class(); | ||
|
||
$response->setForwardURL($value); | ||
$this->assertNull($response->getForwardURL()); | ||
} | ||
|
||
public function testCanSetHeaders() { | ||
$test_class = $this->getReponseClassName(); | ||
$response = new $test_class(); | ||
$this->assertEquals([ | ||
'Content-Type' => 'application/octet-stream; charset=utf-8', | ||
'Cache-Control' => 'no-store', | ||
'Content-Disposition' => 'attachment', | ||
], $response->getHeaders()); | ||
|
||
$response->setHeaders(['Content-Type' => 'application/json']); | ||
$this->assertEquals([ | ||
'Content-Type' => 'application/json', | ||
'Cache-Control' => 'no-store', | ||
'Content-Disposition' => 'attachment', | ||
], $response->getHeaders()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.