Skip to content

Commit 25788ca

Browse files
committed
[WIP] Display links to files (2)
Related to #17
1 parent 0721cde commit 25788ca

10 files changed

+254
-11
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"require": {
77
"php": "^7.1",
88
"geo6/zend-expressive-monolog": "dev-master",
9+
"league/flysystem": "^1.0",
910
"mtymek/blast-base-url": "^1.0",
1011
"phayes/geophp": "^1.2",
1112
"sentry/sdk": "^2.0",

composer.lock

+85-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/autoload/templates.global.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
return [
66
'dependencies' => [
77
'factories' => [
8-
App\Twig\FileExtension::class => Zend\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory::class,
8+
App\Twig\FileExtension::class => App\Twig\FileExtensionFactory::class,
99
App\Twig\ValueExtension::class => Zend\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory::class,
1010
],
1111
],

config/routes.php

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
$app->get('/{config:\w+}[/map]', [TableMiddleware::class, App\Handler\MapHandler::class], 'map');
4545
$app->get('/{config:\w+}/table[/{offset:\d+}]', [TableMiddleware::class, App\Handler\TableHandler::class], 'table');
4646

47+
$app->get('/{config:\w+}/file/{id:\d+}/view/{column:\w+}', [TableMiddleware::class, App\Handler\FileHandler::class], 'file.view');
48+
$app->get('/{config:\w+}/file/{id:\d+}/download/{column:\w+}', [TableMiddleware::class, App\Handler\FileHandler::class], 'file.download');
49+
4750
$app->get('/{config:\w+}/export/{format:\w+}', [TableMiddleware::class, App\Handler\ExportHandler::class], 'export');
4851

4952
$app->get('/{config:\w+}/api/db/table', [TableMiddleware::class, App\Handler\API\Database\TableHandler::class], 'api.db.table');

src/App/Handler/FileHandler.php

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Handler;
6+
7+
use App\Middleware\ConfigMiddleware;
8+
use App\Middleware\DbAdapterMiddleware;
9+
use App\Middleware\TableMiddleware;
10+
use App\Model\Filesystem;
11+
use App\Model\Record;
12+
use App\Model\Table;
13+
use Psr\Http\Message\ResponseInterface;
14+
use Psr\Http\Message\ServerRequestInterface;
15+
use Psr\Http\Server\RequestHandlerInterface;
16+
use Zend\Diactoros\Response\EmptyResponse;
17+
use Zend\Diactoros\Response\JsonResponse;
18+
use Zend\Expressive\Router\RouterInterface;
19+
use Zend\Expressive\Router\RouteResult;
20+
use Zend\Expressive\Template\TemplateRendererInterface;
21+
22+
class FileHandler implements RequestHandlerInterface
23+
{
24+
/**
25+
* @param ServerRequestInterface $request
26+
*
27+
* @return ResponseInterface
28+
*/
29+
public function handle(ServerRequestInterface $request): ResponseInterface
30+
{
31+
$route = $request->getAttribute(RouteResult::class)->getMatchedRouteName();
32+
33+
$adapter = $request->getAttribute(DbAdapterMiddleware::DBADAPTER_ATTRIBUTE);
34+
$config = $request->getAttribute(ConfigMiddleware::CONFIG_ATTRIBUTE);
35+
$table = $request->getAttribute(TableMiddleware::TABLE_ATTRIBUTE);
36+
37+
$id = $request->getAttribute('id');
38+
$column = $request->getAttribute('column');
39+
40+
$filesystem = new Filesystem($config['config']['adapter']);
41+
42+
$record = new Record($adapter, $table, intval($id));
43+
$path = $record->properties[$column];
44+
45+
if (!is_null($path)) {
46+
$path = trim($path);
47+
}
48+
49+
if (is_null($path) || strlen($path) === 0 || $filesystem->has($path) !== true) {
50+
return new EmptyResponse(404);
51+
}
52+
53+
var_dump($route, $path, $filesystem->getMimetype($path));
54+
exit();
55+
}
56+
}

src/App/Handler/TableHandler.php

+1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface
181181
'filter' => $filter,
182182
'thematic' => new Thematic($adapter, $config['config'] ?? null),
183183
'foreignTables' => $foreignTables,
184+
'adapter' => $config['config']['adapter'],
184185
]
185186
)
186187
);

src/App/Model/Filesystem.php

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Model;
6+
7+
use League\Flysystem\Adapter\AbstractAdapter;
8+
use League\Flysystem\Adapter\Local;
9+
use League\Flysystem\Filesystem as FlysystemFilesystem;
10+
11+
class Filesystem extends FlysystemFilesystem
12+
{
13+
public function __construct(array $config, int $cursor = 0)
14+
{
15+
$mode = array_keys($config)[$cursor];
16+
17+
switch ($mode) {
18+
case 'local':
19+
$adapter = self::setLocalAdapter($config[$mode]);
20+
parent::__construct($adapter, $config[$mode]['config'] ?? []);
21+
break;
22+
23+
default:
24+
throw new Exception(sprintf('Invalid Filesystem adapter (%s).', $mode));
25+
}
26+
}
27+
28+
private static function setLocalAdapter(array $config): Local
29+
{
30+
$path = $config['path'] ?? null;
31+
32+
if (is_null($path)) {
33+
throw new Exception('Missing parameter `path` for Filesystem Local adapter.');
34+
}
35+
if (!file_exists($path) || !is_dir($path)) {
36+
throw new Exception(
37+
sprintf('Parameter `path` for Filesystem Local adapter is invalid (%s).', $path)
38+
);
39+
}
40+
41+
return new Local($path);
42+
}
43+
}

src/App/Twig/FileExtension.php

+43-6
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,48 @@
44

55
namespace App\Twig;
66

7+
use App\Model\Filesystem;
8+
use Exception;
79
use Twig\Extension\AbstractExtension;
810
use Twig\TwigFunction;
11+
use Zend\Expressive\Helper\UrlHelper;
912

1013
class FileExtension extends AbstractExtension
1114
{
15+
/** @var AbstractAdapter */
16+
private $adapter;
17+
18+
/** @var Filesystem */
19+
private $filesystem;
20+
21+
/** @var array */
22+
private $routeParams;
23+
24+
/** @var UrlHelper */
25+
private $urlHelper;
26+
27+
public function __construct(UrlHelper $urlHelper)
28+
{
29+
$this->urlHelper = $urlHelper;
30+
}
31+
1232
public function getFunctions(): array
1333
{
1434
return [
15-
new TwigFunction('file', [$this, 'file'], ['is_safe' => ['html']]),
35+
new TwigFunction('file', [$this, 'file'], ['is_safe' => ['html']]),
1636
];
1737
}
1838

19-
public function file($path, bool $preview, bool $download): string
39+
public function file($adapter, $path, array $routeParams, bool $preview, bool $download): string
2040
{
41+
$this->filesystem = new Filesystem($adapter);
42+
$this->routeParams = $routeParams;
43+
2144
if (!is_null($path)) {
2245
$path = trim($path);
2346
}
2447

25-
if (is_null($path) || strlen($path) === 0 || !file_exists($path)) {
48+
if (is_null($path) || strlen($path) === 0 || $this->filesystem->has($path) !== true) {
2649
$output = '<td';
2750
$output .= ' class="text-nowrap"';
2851
$output .= ' colspan="2"';
@@ -32,8 +55,10 @@ public function file($path, bool $preview, bool $download): string
3255
$output .= ValueExtension::null();
3356
} elseif (strlen($path) === 0) {
3457
$output .= '';
35-
} elseif (!file_exists($path)) {
58+
} elseif ($this->filesystem->has($path) !== true) {
3659
$output .= self::notexists($path);
60+
} else {
61+
$output .= '123';
3762
}
3863

3964
$output .= '</td>';
@@ -72,15 +97,27 @@ private function notexists($path) : string
7297

7398
private function preview($path, bool $displayFilename) : string
7499
{
75-
return '<a href="#" style="text-decoration: none;">'
100+
$mime = $this->filesystem->getMimetype($path);
101+
$href = $this->urlHelper->generate('file.view', $this->routeParams);
102+
103+
if ($mime === 'image/jpeg' || $mime === 'image/png') {
104+
return '<a href="'.$href.'" style="text-decoration: none;">'
76105
. '<i class="far fa-fw fa-eye"></i> '
77106
. ($displayFilename ? ' ' . basename($path) : '')
78107
. '</a>';
108+
} else {
109+
return '<a href="'.$href.'" style="text-decoration: none;" target="_blank">'
110+
. '<i class="far fa-fw fa-file"></i> '
111+
. ($displayFilename ? ' ' . basename($path) : '')
112+
. '</a>';
113+
}
79114
}
80115

81116
private function download($path, bool $displayFilename) : string
82117
{
83-
return '<a href="#" style="text-decoration: none;">'
118+
$href = $this->urlHelper->generate('file.download', $this->routeParams);
119+
120+
return '<a href="'.$href.'" style="text-decoration: none;">'
84121
. '<i class="fas fa-fw fa-file-download"></i> '
85122
. ($displayFilename ? ' ' . basename($path) : '')
86123
. '</a>';

src/App/Twig/FileExtensionFactory.php

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Twig;
6+
7+
use Psr\Container\ContainerInterface;
8+
use Zend\Expressive\Helper\UrlHelper;
9+
10+
class FileExtensionFactory
11+
{
12+
public function __invoke(ContainerInterface $container) : FileExtension
13+
{
14+
return new FileExtension(
15+
$container->get(UrlHelper::class)
16+
);
17+
}
18+
}

templates/app/table/body.html.twig

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
{% endif %}
1818

1919
{% if column.config.preview == true or column.config.download == true %}
20-
{{ file(value, column.config.preview, column.config.download) }}
20+
{{ file(adapter, value, {config: configId, id: record.id, column: column.name}, column.config.preview, column.config.download) }}
2121
{% else %}
2222
{{ value(value, column.datatype) }}
2323
{% endif %}
@@ -34,7 +34,7 @@
3434
{% set value = attribute(record.properties, foreign.name ~ '.' ~ fcolumn.name) %}
3535

3636
{% if fcolumn.config.preview == true or fcolumn.config.download == true %}
37-
{{ file(value, fcolumn.config.preview, fcolumn.config.download) }}
37+
{{ file(adapter, value, {config: configId, id: record.id, column: foreign.name ~ '.' ~ fcolumn.name}, fcolumn.config.preview, fcolumn.config.download) }}
3838
{% else %}
3939
{{ value(value, fcolumn.datatype) }}
4040
{% endif %}
@@ -44,4 +44,4 @@
4444
{% endfor %}
4545
</tr>
4646
{% endfor %}
47-
</tbody>
47+
</tbody>

0 commit comments

Comments
 (0)