Split Twig 'url' function into separate functions

This commit is contained in:
Chris Kankiewicz
2020-04-06 16:12:59 -07:00
parent 4cbc5e833a
commit fe7a239466
10 changed files with 156 additions and 75 deletions

View File

@@ -17,12 +17,14 @@ class TwigFactory
ViewFunctions\Asset::class,
ViewFunctions\Breadcrumbs::class,
ViewFunctions\Config::class,
ViewFunctions\FileUrl::class,
ViewFunctions\Icon::class,
ViewFunctions\Markdown::class,
ViewFunctions\ParentUrl::class,
ViewFunctions\SizeForHumans::class,
ViewFunctions\Translate::class,
ViewFunctions\Url::class,
ViewFunctions\ZipUrl::class,
];
/** @var Container The application container */

View File

@@ -0,0 +1,27 @@
<?php
namespace App\ViewFunctions;
class FileUrl extends Url
{
/** @var string The function name */
protected $name = 'file_url';
/**
* Return the URL for a given path and action.
*
* @param string $path
*
* @return string
*/
public function __invoke(string $path = '/'): string
{
$path = preg_replace('/^.?(\/|\\\)+/', '', $path);
if (is_file($path)) {
return $this->escape($path);
}
return empty($path) ? '' : sprintf('?dir=%s', $this->escape($path));
}
}

View File

@@ -3,7 +3,6 @@
namespace App\ViewFunctions;
use App\Support\Str;
use RuntimeException;
class Url extends ViewFunction
{
@@ -24,33 +23,17 @@ class Url extends ViewFunction
}
/**
* Return the URL for a given path and action.
* Return the URL for a given path.
*
* @param string $path
* @param string|null $action
* @param string $path
*
* @return string
*/
public function __invoke(string $path = '/', string $action = null): string
public function __invoke(string $path = '/'): string
{
$path = preg_replace('/^.?(\/|\\\)+/', '', $path);
switch ($action) {
case null:
return $this->escape($path);
case 'dir':
return empty($path) ? '' : sprintf('?dir=%s', $this->escape($path));
case 'info':
return empty($path) ? '?info=.' : sprintf('?info=%s', $this->escape($path));
case 'zip':
return empty($path) ? '?zip=.' : sprintf('?zip=%s', $this->escape($path));
default:
throw new RuntimeException(sprintf('Invalid action "%s"', $action));
}
return $this->escape($path);
}
/**

View File

@@ -0,0 +1,23 @@
<?php
namespace App\ViewFunctions;
class ZipUrl extends Url
{
/** @var string The function name */
protected $name = 'zip_url';
/**
* Return the URL for a given path and action.
*
* @param string $path
*
* @return string
*/
public function __invoke(string $path = '/'): string
{
$path = preg_replace('/^.?(\/|\\\)+/', '', $path);
return empty($path) ? '?zip=.' : sprintf('?zip=%s', $this->escape($path));
}
}

View File

@@ -1,5 +1,5 @@
<a
href="{{ parentDir ? parent_url(path) : url(file.getPathname, 'dir') }}"
href="{{ parentDir ? parent_url(path) : file_url(file.getPathname) }}"
class="flex flex-col items-center rounded-lg font-mono group hover:bg-gray-200 hover:shadow"
>
<div class="flex justify-between items-center p-4 w-full">

View File

@@ -14,7 +14,7 @@
<div class="flex justify-end items-center">
{% if path and files is not empty and config('zip_downloads') %}
<a href="{{ url(path, 'zip') }}" title="{{ translate('download') }}" class="inline-block text-white mx-2 p-1 hover:text-gray-400">
<a href="{{ zip_url(path) }}" title="{{ translate('download') }}" class="inline-block text-white mx-2 p-1 hover:text-gray-400">
<i class="fas fa-download fa-lg"></i>
</a>
{% endif %}

View File

@@ -42,6 +42,11 @@ class TwigFactoryTest extends TestCase
$twig->getEnvironment()->getFunction('config')->getCallable()
);
$this->assertInstanceOf(
ViewFunctions\FileUrl::class,
$twig->getEnvironment()->getFunction('file_url')->getCallable()
);
$this->assertInstanceOf(
ViewFunctions\Icon::class,
$twig->getEnvironment()->getFunction('icon')->getCallable()
@@ -54,7 +59,7 @@ class TwigFactoryTest extends TestCase
$this->assertInstanceOf(
ViewFunctions\ParentUrl::class,
$twig->getEnvironment()->getFunction('parent_dir')->getCallable()
$twig->getEnvironment()->getFunction('parent_url')->getCallable()
);
$this->assertInstanceOf(
@@ -71,5 +76,10 @@ class TwigFactoryTest extends TestCase
ViewFunctions\Url::class,
$twig->getEnvironment()->getFunction('url')->getCallable()
);
$this->assertInstanceOf(
ViewFunctions\ZipUrl::class,
$twig->getEnvironment()->getFunction('zip_url')->getCallable()
);
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Tests\ViewFunctions;
use App\ViewFunctions\FileUrl;
use Tests\TestCase;
class FileUrlTest extends TestCase
{
public function test_it_can_return_a_url(): void
{
$url = new FileUrl;
$this->assertEquals('', $url('/'));
$this->assertEquals('', $url('./'));
$this->assertEquals('?dir=some/path', $url('some/path'));
$this->assertEquals('?dir=some/path', $url('./some/path'));
$this->assertEquals('?dir=some/path', $url('./some/path'));
$this->assertEquals('?dir=some/file.test', $url('some/file.test'));
$this->assertEquals('?dir=some/file.test', $url('./some/file.test'));
}
public function test_it_can_return_a_url_with_back_slashes(): void
{
$url = new FileUrl('\\');
$this->assertEquals('', $url('\\'));
$this->assertEquals('', $url('.\\'));
$this->assertEquals('?dir=some\path', $url('some\path'));
$this->assertEquals('?dir=some\path', $url('.\some\path'));
$this->assertEquals('?dir=some\file.test', $url('some\file.test'));
$this->assertEquals('?dir=some\file.test', $url('.\some\file.test'));
}
public function test_url_segments_are_url_encoded(): void
{
$url = new FileUrl;
$this->assertEquals('?dir=foo/bar%2Bbaz', $url('foo/bar+baz'));
$this->assertEquals('?dir=foo/bar%23baz', $url('foo/bar#baz'));
$this->assertEquals('?dir=foo/bar%26baz', $url('foo/bar&baz'));
}
}

View File

@@ -3,7 +3,6 @@
namespace Tests\ViewFunctions;
use App\ViewFunctions\Url;
use RuntimeException;
use Tests\TestCase;
class UrlTest extends TestCase
@@ -21,43 +20,6 @@ class UrlTest extends TestCase
$this->assertEquals('some/file.test', $url('./some/file.test'));
}
public function test_it_can_return_a_directory_url(): void
{
$url = new Url;
$this->assertEquals('', $url('/', 'dir'));
$this->assertEquals('', $url('./', 'dir'));
$this->assertEquals('?dir=some/path', $url('some/path', 'dir'));
$this->assertEquals('?dir=some/path', $url('./some/path', 'dir'));
$this->assertEquals('?dir=some/path', $url('./some/path', 'dir'));
$this->assertEquals('?dir=some/file.test', $url('some/file.test', 'dir'));
$this->assertEquals('?dir=some/file.test', $url('./some/file.test', 'dir'));
}
public function test_it_can_return_a_file_info_url(): void
{
$url = new Url;
$this->assertEquals('?info=.', $url('/', 'info'));
$this->assertEquals('?info=.', $url('./', 'info'));
$this->assertEquals('?info=some/path', $url('some/path', 'info'));
$this->assertEquals('?info=some/path', $url('./some/path', 'info'));
$this->assertEquals('?info=some/path', $url('./some/path', 'info'));
$this->assertEquals('?info=some/file.test', $url('some/file.test', 'info'));
$this->assertEquals('?info=some/file.test', $url('./some/file.test', 'info'));
}
public function test_it_can_return_a_zip_url(): void
{
$url = new Url;
$this->assertEquals('?zip=.', $url('/', 'zip'));
$this->assertEquals('?zip=.', $url('./', 'zip'));
$this->assertEquals('?zip=some/path', $url('some/path', 'zip'));
$this->assertEquals('?zip=some/path', $url('./some/path', 'zip'));
$this->assertEquals('?zip=some/path', $url('./some/path', 'zip'));
}
public function test_it_can_return_a_url_with_back_slashes(): void
{
$url = new Url('\\');
@@ -68,21 +30,9 @@ class UrlTest extends TestCase
$this->assertEquals('some\path', $url('.\some\path'));
$this->assertEquals('some\file.test', $url('some\file.test'));
$this->assertEquals('some\file.test', $url('.\some\file.test'));
$this->assertEquals('?dir=some\path', $url('some\path', 'dir'));
$this->assertEquals('?info=some\path', $url('some\path', 'info'));
$this->assertEquals('?zip=some\path', $url('some\path', 'zip'));
}
public function test_it_throws_an_exception_for_an_invalid_action(): void
{
$url = new Url;
$this->expectException(RuntimeException::class);
$url('some/path', 'INVALID_ACTION');
}
public function test_segments_are_url_encoded(): void
public function test_url_segments_are_url_encoded(): void
{
$url = new Url;

View File

@@ -0,0 +1,43 @@
<?php
namespace Tests\ViewFunctions;
use App\ViewFunctions\ZipUrl;
use Tests\TestCase;
class ZipUrlTest extends TestCase
{
public function test_it_can_return_a_url(): void
{
$url = new ZipUrl;
$this->assertEquals('?zip=.', $url('/'));
$this->assertEquals('?zip=.', $url('./'));
$this->assertEquals('?zip=some/path', $url('some/path'));
$this->assertEquals('?zip=some/path', $url('./some/path'));
$this->assertEquals('?zip=some/path', $url('./some/path'));
$this->assertEquals('?zip=some/file.test', $url('some/file.test'));
$this->assertEquals('?zip=some/file.test', $url('./some/file.test'));
}
public function test_it_can_return_a_url_with_back_slashes(): void
{
$url = new ZipUrl('\\');
$this->assertEquals('?zip=.', $url('\\'));
$this->assertEquals('?zip=.', $url('.\\'));
$this->assertEquals('?zip=some\path', $url('some\path'));
$this->assertEquals('?zip=some\path', $url('.\some\path'));
$this->assertEquals('?zip=some\file.test', $url('some\file.test'));
$this->assertEquals('?zip=some\file.test', $url('.\some\file.test'));
}
public function test_url_segments_are_url_encoded(): void
{
$url = new ZipUrl;
$this->assertEquals('?zip=foo/bar%2Bbaz', $url('foo/bar+baz'));
$this->assertEquals('?zip=foo/bar%23baz', $url('foo/bar#baz'));
$this->assertEquals('?zip=foo/bar%26baz', $url('foo/bar&baz'));
}
}