* many things
This commit is contained in:
parent
7283d6eefb
commit
3cafc2996e
@ -11,28 +11,36 @@
|
|||||||
"prefer-stable": true,
|
"prefer-stable": true,
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1",
|
"php": "^7.1",
|
||||||
"dasprid/container-interop-doctrine": "^1.0",
|
"dasprid/container-interop-doctrine": "^1.1",
|
||||||
"imagine/imagine": "^0.7.1",
|
"imagine/imagine": "^1.0",
|
||||||
|
"los/loslog": "^3.1",
|
||||||
"roave/security-advisories": "dev-master",
|
"roave/security-advisories": "dev-master",
|
||||||
"symfony/yaml": "*",
|
"symfony/console": "^4.1",
|
||||||
"zendframework/zend-component-installer": "^1.0",
|
"symfony/yaml": "^4.1",
|
||||||
"zendframework/zend-config": "*",
|
"tuupola/cors-middleware": "^0.9.0",
|
||||||
|
"zendframework/zend-component-installer": "^2.1.1",
|
||||||
|
"zendframework/zend-config": "^3.1",
|
||||||
"zendframework/zend-config-aggregator": "^1.0",
|
"zendframework/zend-config-aggregator": "^1.0",
|
||||||
"zendframework/zend-expressive": "^2.0.2",
|
"zendframework/zend-expressive": "^3.0",
|
||||||
"zendframework/zend-expressive-fastroute": "^2.0",
|
"zendframework/zend-expressive-fastroute": "^3.0",
|
||||||
"zendframework/zend-expressive-helpers": "^4.0",
|
"zendframework/zend-expressive-helpers": "^5.0",
|
||||||
"zendframework/zend-servicemanager": "^3.3",
|
"zendframework/zend-servicemanager": "^3.3",
|
||||||
"zendframework/zend-stdlib": "^3.1"
|
"zendframework/zend-stdlib": "^3.1",
|
||||||
|
"zendframework/zend-json": "^3.1",
|
||||||
|
"ext-zip": "*",
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"ext-json": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^6.0.8 || ^5.7.15",
|
"phpunit/phpunit": "^7.0.1",
|
||||||
"squizlabs/php_codesniffer": "^2.8.1",
|
"squizlabs/php_codesniffer": "^2.9.1",
|
||||||
"zfcampus/zf-development-mode": "^3.1",
|
"zfcampus/zf-development-mode": "^3.1",
|
||||||
"filp/whoops": "^2.1.7"
|
"filp/whoops": "^2.1.12"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"App\\": "src/App/"
|
"App\\": "src/App/",
|
||||||
|
"ApiLibs\\": "src/ApiLibs/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
|
|||||||
2212
composer.lock
generated
2212
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Zend\Expressive\Application;
|
declare(strict_types=1);
|
||||||
use Zend\Expressive\Container;
|
|
||||||
use Zend\Expressive\Delegate;
|
|
||||||
use Zend\Expressive\Helper;
|
|
||||||
use Zend\Expressive\Middleware;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
// Provides application-wide services.
|
// Provides application-wide services.
|
||||||
@ -13,27 +9,12 @@ return [
|
|||||||
'dependencies' => [
|
'dependencies' => [
|
||||||
// Use 'aliases' to alias a service name to another service. The
|
// Use 'aliases' to alias a service name to another service. The
|
||||||
// key is the alias name, the value is the service to which it points.
|
// key is the alias name, the value is the service to which it points.
|
||||||
'aliases' => [
|
'aliases' => [],
|
||||||
'Zend\Expressive\Delegate\DefaultDelegate' => Delegate\NotFoundDelegate::class,
|
|
||||||
],
|
|
||||||
// Use 'invokables' for constructor-less services, or services that do
|
// Use 'invokables' for constructor-less services, or services that do
|
||||||
// not require arguments to the constructor. Map a service name to the
|
// not require arguments to the constructor. Map a service name to the
|
||||||
// class name.
|
// class name.
|
||||||
'invokables' => [
|
'invokables' => [],
|
||||||
// Fully\Qualified\InterfaceName::class => Fully\Qualified\ClassName::class,
|
|
||||||
Helper\ServerUrlHelper::class => Helper\ServerUrlHelper::class,
|
|
||||||
],
|
|
||||||
// Use 'factories' for services provided by callbacks/factory classes.
|
// Use 'factories' for services provided by callbacks/factory classes.
|
||||||
'factories' => [
|
'factories' => [],
|
||||||
Application::class => Container\ApplicationFactory::class,
|
|
||||||
Delegate\NotFoundDelegate::class => Container\NotFoundDelegateFactory::class,
|
|
||||||
Helper\ServerUrlMiddleware::class => Helper\ServerUrlMiddlewareFactory::class,
|
|
||||||
Helper\UrlHelper::class => Helper\UrlHelperFactory::class,
|
|
||||||
Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class,
|
|
||||||
|
|
||||||
Zend\Stratigility\Middleware\ErrorHandler::class => Container\ErrorHandlerFactory::class,
|
|
||||||
Middleware\ErrorResponseGenerator::class => Container\ErrorResponseGeneratorFactory::class,
|
|
||||||
Middleware\NotFoundHandler::class => Container\NotFoundHandlerFactory::class,
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Development-only configuration.
|
* Development-only configuration.
|
||||||
*
|
*
|
||||||
@ -10,6 +9,8 @@
|
|||||||
* `composer development-enable`.
|
* `composer development-enable`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Zend\Expressive\Container;
|
use Zend\Expressive\Container;
|
||||||
use Zend\Expressive\Middleware\ErrorResponseGenerator;
|
use Zend\Expressive\Middleware\ErrorResponseGenerator;
|
||||||
|
|
||||||
@ -31,4 +32,4 @@ return [
|
|||||||
'ajax_only' => true,
|
'ajax_only' => true,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
@ -6,10 +6,10 @@ return [
|
|||||||
'orm_default' => [
|
'orm_default' => [
|
||||||
'class' => \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class,
|
'class' => \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class,
|
||||||
'drivers' => [
|
'drivers' => [
|
||||||
'App\Entity' => 'my_entity',
|
'App\Entity' => 'app_entity',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'my_entity' => [
|
'app_entity' => [
|
||||||
'class' => \Doctrine\ORM\Mapping\Driver\AnnotationDriver::class,
|
'class' => \Doctrine\ORM\Mapping\Driver\AnnotationDriver::class,
|
||||||
'cache' => 'array',
|
'cache' => 'array',
|
||||||
'paths' => __DIR__ . '/../../src/App/Entity',
|
'paths' => __DIR__ . '/../../src/App/Entity',
|
||||||
|
|||||||
30
config/autoload/loslog.global.php
Normal file
30
config/autoload/loslog.global.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Zend\Stratigility\Middleware\ErrorHandler;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'dependencies' => [
|
||||||
|
'factories' => [
|
||||||
|
LosMiddleware\LosLog\LosLog::class => LosMiddleware\LosLog\LosLogFactory::class,
|
||||||
|
LosMiddleware\LosLog\HttpLog::class => LosMiddleware\LosLog\HttpLogFactory::class,
|
||||||
|
Psr\Log\LoggerInterface::class => LosMiddleware\LosLog\LoggerFactory::class,
|
||||||
|
],
|
||||||
|
'delegators' => [
|
||||||
|
ErrorHandler::class => [
|
||||||
|
LosMiddleware\LosLog\ErrorHandlerListenerDelegatorFactory::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'loslog' => [
|
||||||
|
'log_dir' => 'data/logs',
|
||||||
|
'error_logger_file' => 'error.log',
|
||||||
|
'exception_logger_file' => 'exception.log',
|
||||||
|
'static_logger_file' => 'static.log',
|
||||||
|
'http_logger_file' => 'http.log',
|
||||||
|
'log_request' => false,
|
||||||
|
'log_response' => false,
|
||||||
|
'full' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
@ -1,12 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Zend\Expressive\Router\FastRouteRouter;
|
|
||||||
use Zend\Expressive\Router\RouterInterface;
|
|
||||||
|
|
||||||
return [
|
|
||||||
'dependencies' => [
|
|
||||||
'invokables' => [
|
|
||||||
RouterInterface::class => FastRouteRouter::class,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Zend\ConfigAggregator\ConfigAggregator;
|
use Zend\ConfigAggregator\ConfigAggregator;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -13,10 +15,6 @@ return [
|
|||||||
'debug' => false,
|
'debug' => false,
|
||||||
|
|
||||||
'zend-expressive' => [
|
'zend-expressive' => [
|
||||||
// Enable programmatic pipeline: Any `middleware_pipeline` or `routes`
|
|
||||||
// configuration will be ignored when creating the `Application` instance.
|
|
||||||
'programmatic_pipeline' => true,
|
|
||||||
|
|
||||||
// Provide templates for the error handling middleware to use when
|
// Provide templates for the error handling middleware to use when
|
||||||
// generating responses.
|
// generating responses.
|
||||||
'error_handler' => [
|
'error_handler' => [
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Zend\ConfigAggregator\ArrayProvider;
|
use Zend\ConfigAggregator\ArrayProvider;
|
||||||
use Zend\ConfigAggregator\ConfigAggregator;
|
use Zend\ConfigAggregator\ConfigAggregator;
|
||||||
use Zend\ConfigAggregator\PhpFileProvider;
|
use Zend\ConfigAggregator\PhpFileProvider;
|
||||||
@ -7,15 +9,23 @@ use Zend\ConfigAggregator\PhpFileProvider;
|
|||||||
// To enable or disable caching, set the `ConfigAggregator::ENABLE_CACHE` boolean in
|
// To enable or disable caching, set the `ConfigAggregator::ENABLE_CACHE` boolean in
|
||||||
// `config/autoload/local.php`.
|
// `config/autoload/local.php`.
|
||||||
$cacheConfig = [
|
$cacheConfig = [
|
||||||
'config_cache_path' => 'data/config-cache.php',
|
'config_cache_path' => 'data/cache/config-cache.php',
|
||||||
];
|
];
|
||||||
|
|
||||||
$aggregator = new ConfigAggregator([
|
$aggregator = new ConfigAggregator([
|
||||||
|
\Zend\Expressive\ConfigProvider::class,
|
||||||
|
\Zend\Expressive\Helper\ConfigProvider::class,
|
||||||
|
\Zend\Expressive\Router\FastRouteRouter\ConfigProvider::class,
|
||||||
|
\Zend\Expressive\Router\ConfigProvider::class,
|
||||||
|
\Zend\HttpHandlerRunner\ConfigProvider::class,
|
||||||
|
\Zend\Log\ConfigProvider::class,
|
||||||
|
|
||||||
// Include cache configuration
|
// Include cache configuration
|
||||||
new ArrayProvider($cacheConfig),
|
new ArrayProvider($cacheConfig),
|
||||||
|
|
||||||
// Default App module config
|
// Default App module config
|
||||||
App\ConfigProvider::class,
|
App\ConfigProvider::class,
|
||||||
|
ApiLibs\ConfigProvider::class,
|
||||||
|
|
||||||
// Load application config in a pre-defined order in such a way that local settings
|
// Load application config in a pre-defined order in such a way that local settings
|
||||||
// overwrite global settings. (Loaded as first to last):
|
// overwrite global settings. (Loaded as first to last):
|
||||||
@ -23,10 +33,10 @@ $aggregator = new ConfigAggregator([
|
|||||||
// - `*.global.php`
|
// - `*.global.php`
|
||||||
// - `local.php`
|
// - `local.php`
|
||||||
// - `*.local.php`
|
// - `*.local.php`
|
||||||
new PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
|
new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'),
|
||||||
|
|
||||||
// Load development config if it exists
|
// Load development config if it exists
|
||||||
new PhpFileProvider('config/development.config.php'),
|
new PhpFileProvider(realpath(__DIR__) . '/development.config.php'),
|
||||||
], $cacheConfig['config_cache_path']);
|
], $cacheConfig['config_cache_path']);
|
||||||
|
|
||||||
return $aggregator->getMergedConfig();
|
return $aggregator->getMergedConfig();
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Zend\ServiceManager\Config;
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Zend\ServiceManager\ServiceManager;
|
use Zend\ServiceManager\ServiceManager;
|
||||||
|
|
||||||
// Load configuration
|
// Load configuration
|
||||||
$config = require __DIR__ . '/config.php';
|
$config = require __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
$dependencies = $config['dependencies'];
|
||||||
|
$dependencies['services']['config'] = $config;
|
||||||
|
|
||||||
// Build container
|
// Build container
|
||||||
$container = new ServiceManager();
|
return new ServiceManager($dependencies);
|
||||||
(new Config($config['dependencies']))->configureServiceManager($container);
|
|
||||||
|
|
||||||
// Inject config
|
|
||||||
$container->setService('config', $config);
|
|
||||||
|
|
||||||
return $container;
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File required to allow enablement of development mode.
|
* File required to allow enablement of development mode.
|
||||||
*
|
*
|
||||||
@ -21,6 +20,8 @@
|
|||||||
* - Configuration caching is _disabled_.
|
* - Configuration caching is _disabled_.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Zend\ConfigAggregator\ConfigAggregator;
|
use Zend\ConfigAggregator\ConfigAggregator;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -1,56 +1,76 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
use Tuupola\Middleware\CorsMiddleware;
|
||||||
|
use Zend\Expressive\Application;
|
||||||
|
use Zend\Expressive\Handler\NotFoundHandler;
|
||||||
use Zend\Expressive\Helper\ServerUrlMiddleware;
|
use Zend\Expressive\Helper\ServerUrlMiddleware;
|
||||||
use Zend\Expressive\Helper\UrlHelperMiddleware;
|
use Zend\Expressive\Helper\UrlHelperMiddleware;
|
||||||
use Zend\Expressive\Middleware\ImplicitHeadMiddleware;
|
use Zend\Expressive\MiddlewareFactory;
|
||||||
use Zend\Expressive\Middleware\ImplicitOptionsMiddleware;
|
use Zend\Expressive\Router\Middleware\DispatchMiddleware;
|
||||||
use Zend\Expressive\Middleware\NotFoundHandler;
|
use Zend\Expressive\Router\Middleware\ImplicitHeadMiddleware;
|
||||||
|
use Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware;
|
||||||
|
use Zend\Expressive\Router\Middleware\RouteMiddleware;
|
||||||
use Zend\Stratigility\Middleware\ErrorHandler;
|
use Zend\Stratigility\Middleware\ErrorHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup middleware pipeline:
|
* Setup middleware pipeline:
|
||||||
*/
|
*/
|
||||||
|
return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void {
|
||||||
|
// The error handler should be the first (most outer) middleware to catch
|
||||||
|
// all Exceptions.
|
||||||
|
$app->pipe(ErrorHandler::class);
|
||||||
|
$app->pipe(ServerUrlMiddleware::class);
|
||||||
|
|
||||||
// The error handler should be the first (most outer) middleware to catch
|
// Pipe more middleware here that you want to execute on every request:
|
||||||
// all Exceptions.
|
// - bootstrapping
|
||||||
$app->pipe(ErrorHandler::class);
|
// - pre-conditions
|
||||||
$app->pipe(App\Middleware\PreFlightMiddleware::class);
|
// - modifications to outgoing responses
|
||||||
$app->pipe(ServerUrlMiddleware::class);
|
//
|
||||||
|
// Piped Middleware may be either callables or service names. Middleware may
|
||||||
|
// also be passed as an array; each item in the array must resolve to
|
||||||
|
// middleware eventually (i.e., callable or service name).
|
||||||
|
//
|
||||||
|
// Middleware can be attached to specific paths, allowing you to mix and match
|
||||||
|
// applications under a common domain. The handlers in each middleware
|
||||||
|
// attached this way will see a URI with the matched path segment removed.
|
||||||
|
//
|
||||||
|
// i.e., path of "/api/member/profile" only passes "/member/profile" to $apiMiddleware
|
||||||
|
// - $app->pipe('/api', $apiMiddleware);
|
||||||
|
// - $app->pipe('/docs', $apiDocMiddleware);
|
||||||
|
// - $app->pipe('/files', $filesMiddleware);
|
||||||
|
|
||||||
// Pipe more middleware here that you want to execute on every request:
|
// Register the routing middleware in the middleware pipeline.
|
||||||
// - bootstrapping
|
// This middleware registers the Zend\Expressive\Router\RouteResult request attribute.
|
||||||
// - pre-conditions
|
$app->pipe(RouteMiddleware::class);
|
||||||
// - modifications to outgoing responses
|
|
||||||
//
|
|
||||||
// Piped Middleware may be either callables or service names. Middleware may
|
|
||||||
// also be passed as an array; each item in the array must resolve to
|
|
||||||
// middleware eventually (i.e., callable or service name).
|
|
||||||
//
|
|
||||||
// Middleware can be attached to specific paths, allowing you to mix and match
|
|
||||||
// applications under a common domain. The handlers in each middleware
|
|
||||||
// attached this way will see a URI with the MATCHED PATH SEGMENT REMOVED!!!
|
|
||||||
//
|
|
||||||
// - $app->pipe('/api', $apiMiddleware);
|
|
||||||
// - $app->pipe('/docs', $apiDocMiddleware);
|
|
||||||
// - $app->pipe('/files', $filesMiddleware);
|
|
||||||
|
|
||||||
// Register the routing middleware in the middleware pipeline
|
// The following handle routing failures for common conditions:
|
||||||
$app->pipeRoutingMiddleware();
|
// - HEAD request but no routes answer that method
|
||||||
$app->pipe(ImplicitHeadMiddleware::class);
|
// - OPTIONS request but no routes answer that method
|
||||||
$app->pipe(ImplicitOptionsMiddleware::class);
|
// - method not allowed
|
||||||
$app->pipe(UrlHelperMiddleware::class);
|
// Order here matters; the MethodNotAllowedMiddleware should be placed
|
||||||
|
// after the Implicit*Middleware.
|
||||||
|
$app->pipe(ImplicitHeadMiddleware::class);
|
||||||
|
$app->pipe(CorsMiddleware::class);
|
||||||
|
$app->pipe(MethodNotAllowedMiddleware::class);
|
||||||
|
|
||||||
// Add more middleware here that needs to introspect the routing results; this
|
// Seed the UrlHelper with the routing results:
|
||||||
// might include:
|
$app->pipe(UrlHelperMiddleware::class);
|
||||||
//
|
|
||||||
// - route-based authentication
|
|
||||||
// - route-based validation
|
|
||||||
// - etc.
|
|
||||||
|
|
||||||
// Register the dispatch middleware in the middleware pipeline
|
// Add more middleware here that needs to introspect the routing results; this
|
||||||
$app->pipeDispatchMiddleware();
|
// might include:
|
||||||
|
//
|
||||||
|
// - route-based authentication
|
||||||
|
// - route-based validation
|
||||||
|
// - etc.
|
||||||
|
|
||||||
// At this point, if no Response is return by any middleware, the
|
// Register the dispatch middleware in the middleware pipeline
|
||||||
// NotFoundHandler kicks in; alternately, you can provide other fallback
|
$app->pipe(DispatchMiddleware::class);
|
||||||
// middleware to execute.
|
|
||||||
$app->pipe(NotFoundHandler::class);
|
// At this point, if no Response is returned by any middleware, the
|
||||||
|
// NotFoundHandler kicks in; alternately, you can provide other fallback
|
||||||
|
// middleware to execute.
|
||||||
|
$app->pipe(NotFoundHandler::class);
|
||||||
|
};
|
||||||
|
|||||||
@ -1,32 +1,44 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
use Zend\Expressive\Application;
|
||||||
|
use Zend\Expressive\MiddlewareFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup routes with a single request method:
|
* Setup routes with a single request method:
|
||||||
*
|
*
|
||||||
* $app->get('/', App\Action\HomePageAction::class, 'home');
|
* $app->get('/', App\Handler\HomePageHandler::class, 'home');
|
||||||
* $app->post('/album', App\Action\AlbumCreateAction::class, 'album.create');
|
* $app->post('/album', App\Handler\AlbumCreateHandler::class, 'album.create');
|
||||||
* $app->put('/album/:id', App\Action\AlbumUpdateAction::class, 'album.put');
|
* $app->put('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.put');
|
||||||
* $app->patch('/album/:id', App\Action\AlbumUpdateAction::class, 'album.patch');
|
* $app->patch('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.patch');
|
||||||
* $app->delete('/album/:id', App\Action\AlbumDeleteAction::class, 'album.delete');
|
* $app->delete('/album/:id', App\Handler\AlbumDeleteHandler::class, 'album.delete');
|
||||||
*
|
*
|
||||||
* Or with multiple request methods:
|
* Or with multiple request methods:
|
||||||
*
|
*
|
||||||
* $app->route('/contact', App\Action\ContactAction::class, ['GET', 'POST', ...], 'contact');
|
* $app->route('/contact', App\Handler\ContactHandler::class, ['GET', 'POST', ...], 'contact');
|
||||||
*
|
*
|
||||||
* Or handling all request methods:
|
* Or handling all request methods:
|
||||||
*
|
*
|
||||||
* $app->route('/contact', App\Action\ContactAction::class)->setName('contact');
|
* $app->route('/contact', App\Handler\ContactHandler::class)->setName('contact');
|
||||||
*
|
*
|
||||||
* or:
|
* or:
|
||||||
*
|
*
|
||||||
* $app->route(
|
* $app->route(
|
||||||
* '/contact',
|
* '/contact',
|
||||||
* App\Action\ContactAction::class,
|
* App\Handler\ContactHandler::class,
|
||||||
* Zend\Expressive\Router\Route::HTTP_METHOD_ANY,
|
* Zend\Expressive\Router\Route::HTTP_METHOD_ANY,
|
||||||
* 'contact'
|
* 'contact'
|
||||||
* );
|
* );
|
||||||
*/
|
*/
|
||||||
|
return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void {
|
||||||
|
$app->get('/', App\Handler\HomePage::class, 'home');
|
||||||
|
$app->get('/api/galleries', App\Handler\ListGalleries::class, 'api.galleries');
|
||||||
|
$app->get('/image/{slug}/{image}[/{thumb}]', App\Handler\GetImage::class, 'download.image');
|
||||||
|
$app->get('/export-album/{slug}.zip', App\Handler\ExportAlbum::class, 'export.album');
|
||||||
|
|
||||||
$app->get('/', App\Action\HomePageAction::class, 'home');
|
$app->get('/api/album[/{id:\d+}]', App\Handler\Album::class, 'api.album');
|
||||||
$app->get('/api/galleries', App\Action\ListGalleriesAction::class, 'api.galleries');
|
$app->get('/api/image[/{id:\d+}]', App\Handler\Image::class, 'api.image');
|
||||||
$app->get('/image/{slug}/{image}[/{thumb}]', App\Action\GetImageAction::class, 'download.image');
|
$app->get('/api/collection[/{id:\d+}]', App\Handler\Collection::class, 'api.gallery');
|
||||||
$app->get('/export-album/{slug}.zip', App\Action\ExportAlbumAction::class, 'export.album');
|
};
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
// Delegate static file requests back to the PHP built-in webserver
|
// Delegate static file requests back to the PHP built-in webserver
|
||||||
if (php_sapi_name() === 'cli-server'
|
if (PHP_SAPI === 'cli-server' && $_SERVER['SCRIPT_FILENAME'] !== __FILE__) {
|
||||||
&& is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,17 +13,18 @@ require 'vendor/autoload.php';
|
|||||||
/**
|
/**
|
||||||
* Self-called anonymous function that creates its own scope and keep the global namespace clean.
|
* Self-called anonymous function that creates its own scope and keep the global namespace clean.
|
||||||
*/
|
*/
|
||||||
call_user_func(function () {
|
(function () {
|
||||||
/** @var \Interop\Container\ContainerInterface $container */
|
/** @var \Psr\Container\ContainerInterface $container */
|
||||||
$container = require 'config/container.php';
|
$container = require 'config/container.php';
|
||||||
|
|
||||||
/** @var \Zend\Expressive\Application $app */
|
/** @var \Zend\Expressive\Application $app */
|
||||||
$app = $container->get(\Zend\Expressive\Application::class);
|
$app = $container->get(\Zend\Expressive\Application::class);
|
||||||
|
$factory = $container->get(\Zend\Expressive\MiddlewareFactory::class);
|
||||||
|
|
||||||
// Import programmatic/declarative middleware pipeline and routing
|
// Execute programmatic/declarative middleware pipeline and routing
|
||||||
// configuration statements
|
// configuration statements
|
||||||
require 'config/pipeline.php';
|
(require 'config/pipeline.php')($app, $factory, $container);
|
||||||
require 'config/routes.php';
|
(require 'config/routes.php')($app, $factory, $container);
|
||||||
|
|
||||||
$app->run();
|
$app->run();
|
||||||
});
|
})();
|
||||||
|
|||||||
166
src/ApiLibs/AbstractHandler/CrudHandler.php
Normal file
166
src/ApiLibs/AbstractHandler/CrudHandler.php
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ApiLibs\AbstractHandler;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Zend\Diactoros\Response\EmptyResponse;
|
||||||
|
use Zend\Diactoros\Response\JsonResponse;
|
||||||
|
use Zend\Json\Json;
|
||||||
|
|
||||||
|
abstract class CrudHandler implements RequestHandlerInterface
|
||||||
|
{
|
||||||
|
const IDENTIFIER_NAME = 'id';
|
||||||
|
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$requestMethod = strtoupper($request->getMethod());
|
||||||
|
$id = $request->getAttribute(static::IDENTIFIER_NAME);
|
||||||
|
|
||||||
|
switch ($requestMethod) {
|
||||||
|
case 'GET':
|
||||||
|
return isset($id)
|
||||||
|
? $this->get($request)
|
||||||
|
: $this->getList($request);
|
||||||
|
case 'POST':
|
||||||
|
return $this->create($request);
|
||||||
|
case 'PUT':
|
||||||
|
return $this->update($request);
|
||||||
|
case 'DELETE':
|
||||||
|
return isset($id)
|
||||||
|
? $this->delete($request)
|
||||||
|
: $this->deleteList($request);
|
||||||
|
case 'HEAD':
|
||||||
|
return $this->head($request);
|
||||||
|
case 'OPTIONS':
|
||||||
|
return $this->options($request);
|
||||||
|
case 'PATCH':
|
||||||
|
return $this->patch($request);
|
||||||
|
default:
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getList(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteList(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function head(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function options(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return new EmptyResponse(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function patch(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->notAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function notAllowed(): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->createResponse(['content' => 'Method not allowed'], 405);
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function createResponse($data, $status = 200): ResponseInterface
|
||||||
|
{
|
||||||
|
return new JsonResponse($data, $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return array|object
|
||||||
|
*/
|
||||||
|
public function getRequestData(ServerRequestInterface $request)
|
||||||
|
{
|
||||||
|
$body = $request->getParsedBody();
|
||||||
|
|
||||||
|
if (!empty($body)) {
|
||||||
|
return $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parseRequestData(
|
||||||
|
$request->getBody()->getContents(),
|
||||||
|
$request->getHeaderLine('content-type')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @param string $contentType
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function parseRequestData($input, $contentType)
|
||||||
|
{
|
||||||
|
$contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType);
|
||||||
|
$parser = $this->returnParserContentType($contentTypeParts[0]);
|
||||||
|
|
||||||
|
return $parser($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $contentType
|
||||||
|
* @return callable
|
||||||
|
*/
|
||||||
|
private function returnParserContentType(string $contentType): callable
|
||||||
|
{
|
||||||
|
if ($contentType === 'application/x-www-form-urlencoded') {
|
||||||
|
return function ($input) {
|
||||||
|
parse_str($input, $data);
|
||||||
|
return $data;
|
||||||
|
};
|
||||||
|
} elseif ($contentType === 'application/json') {
|
||||||
|
return function ($input) {
|
||||||
|
$jsonDecoder = new Json();
|
||||||
|
try {
|
||||||
|
return $jsonDecoder->decode($input, Json::TYPE_ARRAY);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} elseif ($contentType === 'multipart/form-data') {
|
||||||
|
return function ($input) {
|
||||||
|
return $input;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return function ($input) {
|
||||||
|
return $input;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/ApiLibs/ConfigProvider.php
Normal file
43
src/ApiLibs/ConfigProvider.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ApiLibs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration provider for the App module
|
||||||
|
*
|
||||||
|
* @see https://docs.zendframework.com/zend-component-installer/
|
||||||
|
*/
|
||||||
|
class ConfigProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the configuration array
|
||||||
|
*
|
||||||
|
* To add a bit of a structure, each section is defined in a separate
|
||||||
|
* method which returns an array with its configuration.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function __invoke()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'dependencies' => $this->getDependencies(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the container dependencies
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDependencies()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'invokables' => [],
|
||||||
|
'factories' => [
|
||||||
|
\Tuupola\Middleware\CorsMiddleware::class => Middleware\CorsMiddlewareFactory::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/ApiLibs/Middleware/CorsMiddlewareFactory.php
Normal file
23
src/ApiLibs/Middleware/CorsMiddlewareFactory.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ApiLibs\Middleware;
|
||||||
|
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
use Tuupola\Middleware\CorsMiddleware;
|
||||||
|
|
||||||
|
class CorsMiddlewareFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): CorsMiddleware
|
||||||
|
{
|
||||||
|
return new CorsMiddleware([
|
||||||
|
"headers.allow" => [
|
||||||
|
"Authorization",
|
||||||
|
"If-Match",
|
||||||
|
"If-Unmodified-Since",
|
||||||
|
"Content-type",
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Action;
|
|
||||||
|
|
||||||
use App\Service\GalleryService;
|
|
||||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
|
||||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use Zend\Diactoros\Response;
|
|
||||||
|
|
||||||
class ExportAlbumAction implements ServerMiddlewareInterface
|
|
||||||
{
|
|
||||||
private $galleryService;
|
|
||||||
|
|
||||||
public function __construct(GalleryService $galleryService)
|
|
||||||
{
|
|
||||||
$this->galleryService = $galleryService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
|
||||||
{
|
|
||||||
$slug = $request->getAttribute('slug', false);
|
|
||||||
$this->galleryService->getExportFileName($slug);
|
|
||||||
return new Response\RedirectResponse("/export/{$slug}.zip");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Action;
|
|
||||||
|
|
||||||
use App\Service\GalleryService;
|
|
||||||
use Interop\Container\ContainerInterface;
|
|
||||||
|
|
||||||
class ExportAlbumFactory
|
|
||||||
{
|
|
||||||
public function __invoke(ContainerInterface $container)
|
|
||||||
{
|
|
||||||
$galleryService = $container->get(GalleryService::class);
|
|
||||||
return new ExportAlbumAction($galleryService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Action;
|
|
||||||
|
|
||||||
use App\Service\GalleryService;
|
|
||||||
use Interop\Container\ContainerInterface;
|
|
||||||
|
|
||||||
class GetImageFactory
|
|
||||||
{
|
|
||||||
public function __invoke(ContainerInterface $container)
|
|
||||||
{
|
|
||||||
$galleryService = $container->get(GalleryService::class);
|
|
||||||
return new GetImageAction($galleryService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Action;
|
|
||||||
|
|
||||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
|
||||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use Zend\Diactoros\Response\JsonResponse;
|
|
||||||
|
|
||||||
class HomePageAction implements ServerMiddlewareInterface
|
|
||||||
{
|
|
||||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
|
||||||
{
|
|
||||||
return new JsonResponse([
|
|
||||||
'welcome' => 'Congratulations! You have reahced the end of the internet.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Action;
|
|
||||||
|
|
||||||
use App\Response\JsonCorsResponse;
|
|
||||||
use App\Service\GalleryService;
|
|
||||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
|
||||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
|
|
||||||
class ListGalleriesAction implements ServerMiddlewareInterface
|
|
||||||
{
|
|
||||||
private $galleryService;
|
|
||||||
|
|
||||||
public function __construct(GalleryService $galleryService)
|
|
||||||
{
|
|
||||||
$this->galleryService = $galleryService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
|
||||||
{
|
|
||||||
return new JsonCorsResponse($this->galleryService->loadGalleryData(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Action;
|
|
||||||
|
|
||||||
use App\Service\GalleryService;
|
|
||||||
use Interop\Container\ContainerInterface;
|
|
||||||
|
|
||||||
class ListGalleriesFactory
|
|
||||||
{
|
|
||||||
public function __invoke(ContainerInterface $container)
|
|
||||||
{
|
|
||||||
$galleryService = $container->get(GalleryService::class);
|
|
||||||
return new ListGalleriesAction($galleryService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use ContainerInteropDoctrine\EntityManagerFactory;
|
use ContainerInteropDoctrine\EntityManagerFactory;
|
||||||
@ -36,15 +38,19 @@ class ConfigProvider
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'invokables' => [
|
'invokables' => [
|
||||||
Action\HomePageAction::class => Action\HomePageAction::class,
|
Handler\HomePage::class => Handler\HomePage::class,
|
||||||
],
|
],
|
||||||
'factories' => [
|
'factories' => [
|
||||||
'doctrine.entity_manager.orm_default' => EntityManagerFactory::class,
|
'doctrine.entity_manager.orm_default' => EntityManagerFactory::class,
|
||||||
'doctrine.hydrator' => Hydrator\DoctrineObjectFactory::class,
|
'doctrine.hydrator' => Hydrator\DoctrineObjectFactory::class,
|
||||||
|
|
||||||
Action\ListGalleriesAction::class => Action\ListGalleriesFactory::class,
|
Handler\ListGalleries::class => Handler\ListGalleriesFactory::class,
|
||||||
Action\GetImageAction::class => Action\GetImageFactory::class,
|
Handler\GetImage::class => Handler\GetImageFactory::class,
|
||||||
Action\ExportAlbumAction::class => Action\ExportAlbumFactory::class,
|
Handler\ExportAlbum::class => Handler\ExportAlbumFactory::class,
|
||||||
|
|
||||||
|
Handler\Album::class => Handler\AlbumFactory::class,
|
||||||
|
Handler\Collection::class => Handler\CollectionFactory::class,
|
||||||
|
Handler\Image::class => Handler\ImageFactory::class,
|
||||||
|
|
||||||
Service\GalleryService::class => Service\GalleryServiceFactory::class,
|
Service\GalleryService::class => Service\GalleryServiceFactory::class,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,20 +1,274 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection as DoctrineCollection;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use JsonSerializable;
|
||||||
|
|
||||||
class Album
|
/**
|
||||||
|
* @ORM\Entity
|
||||||
|
* @ORM\Table(
|
||||||
|
* name="albums",
|
||||||
|
* indexes={
|
||||||
|
* @ORM\Index(name="alb_slug_idx", columns={"slug"}),
|
||||||
|
* @ORM\Index(name="alb_public_idx", columns={"public"})
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
class Album implements JsonSerializable
|
||||||
{
|
{
|
||||||
const TYPE_STANDARD = 0;
|
const TYPE_STANDARD = 0;
|
||||||
const TYPE_PANORAMA = 1;
|
const TYPE_PANORAMA = 1;
|
||||||
|
|
||||||
protected $slug;
|
/**
|
||||||
protected $dir;
|
* @ORM\Id
|
||||||
protected $name;
|
* @ORM\Column(name="id", type="integer")
|
||||||
protected $coverImage;
|
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||||
protected $type;
|
* @var int
|
||||||
protected $new;
|
*/
|
||||||
protected $public;
|
private $id;
|
||||||
protected $images;
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="name", type="string", length=255, nullable=false)
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="slug", type="string", length=255, nullable=false)
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $slug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="dir", type="string", length=255, nullable=false)
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $dir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="type", type="integer", nullable=false, options={"default" = 0})
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="public", type="boolean", nullable=false)
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\OneToOne(targetEntity="Image")
|
||||||
|
* @ORM\JoinColumn(name="cover_image_id", referencedColumnName="id")
|
||||||
|
* @var Image
|
||||||
|
*/
|
||||||
|
private $coverImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\OneToMany(targetEntity="Image", mappedBy="album")
|
||||||
|
* @var Image[]|DoctrineCollection
|
||||||
|
*/
|
||||||
|
private $images;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $deepSerialize = false;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->images = new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getId(): int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setId(int $id): Album
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setName(string $name): Album
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSlug(): string
|
||||||
|
{
|
||||||
|
return $this->slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $slug
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setSlug(string $slug): Album
|
||||||
|
{
|
||||||
|
$this->slug = $slug;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDir(): string
|
||||||
|
{
|
||||||
|
return $this->dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $dir
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setDir(string $dir): Album
|
||||||
|
{
|
||||||
|
$this->dir = $dir;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getType(): int
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $type
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setType(int $type): Album
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPublic(): bool
|
||||||
|
{
|
||||||
|
return $this->public;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $public
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setPublic(bool $public): Album
|
||||||
|
{
|
||||||
|
$this->public = $public;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function getCoverImage(): Image
|
||||||
|
{
|
||||||
|
return $this->coverImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Image $coverImage
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setCoverImage(Image $coverImage): Album
|
||||||
|
{
|
||||||
|
$this->coverImage = $coverImage;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Image[]|DoctrineCollection
|
||||||
|
*/
|
||||||
|
public function getImages(): DoctrineCollection
|
||||||
|
{
|
||||||
|
return $this->images;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Image[]|DoctrineCollection $images
|
||||||
|
* @return Album
|
||||||
|
*/
|
||||||
|
public function setImages($images): Album
|
||||||
|
{
|
||||||
|
$this->images = $images;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addImage(Image $image): Album
|
||||||
|
{
|
||||||
|
if (!$this->images->contains($image)) {
|
||||||
|
$this->images->add($image);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeImage(Image $image): Album
|
||||||
|
{
|
||||||
|
if ($this->images->contains($image)) {
|
||||||
|
$this->images->removeElement($image);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDeepSerialize(bool $val): Album
|
||||||
|
{
|
||||||
|
$this->deepSerialize = $val;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data for json serializer
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function jsonSerialize(): array
|
||||||
|
{
|
||||||
|
$serialized = [
|
||||||
|
'id' => $this->getId(),
|
||||||
|
'name' => $this->getName(),
|
||||||
|
'slug' => $this->getSlug(),
|
||||||
|
'dir' => $this->getDir(),
|
||||||
|
'type' => $this->getType(),
|
||||||
|
'public' => $this->isPublic(),
|
||||||
|
'coverImage' => $this->getCoverImage(),
|
||||||
|
];
|
||||||
|
if ($this->deepSerialize) {
|
||||||
|
array_push($serialized, [
|
||||||
|
'images' => $this->getImages()->getValues(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return $serialized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
238
src/App/Entity/Collection.php
Normal file
238
src/App/Entity/Collection.php
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection as DoctrineCollection;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use JsonSerializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Entity
|
||||||
|
* @ORM\Table(
|
||||||
|
* name="collections",
|
||||||
|
* indexes={
|
||||||
|
* @ORM\Index(name="coll_slug_idx", columns={"slug"}),
|
||||||
|
* @ORM\Index(name="coll_public_idx", columns={"public"})
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
class Collection implements JsonSerializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\Column(name="id", type="integer")
|
||||||
|
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="name", type="string", length=255, nullable=false)
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="slug", type="string", length=255, nullable=false)
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $slug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="share_hash", type="string", length=255, nullable=true)
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $shareHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="public", type="boolean", nullable=false, options={"default" = true})
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToMany(targetEntity="Image", mappedBy="images")
|
||||||
|
* @ORM\JoinTable(
|
||||||
|
* name="collection_images",
|
||||||
|
* joinColumns={@ORM\JoinColumn(name="collection_id", referencedColumnName="id")},
|
||||||
|
* inverseJoinColumns={@ORM\JoinColumn(name="image_id", referencedColumnName="id")}
|
||||||
|
* )
|
||||||
|
* @var Image[]|DoctrineCollection
|
||||||
|
*/
|
||||||
|
private $images;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $deepSerialize = false;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->images = new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getId(): int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function setId(int $id): Collection
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function setName(string $name): Collection
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSlug(): string
|
||||||
|
{
|
||||||
|
return $this->slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $slug
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function setSlug(string $slug): Collection
|
||||||
|
{
|
||||||
|
$this->slug = $slug;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getShareHash(): ?string
|
||||||
|
{
|
||||||
|
return $this->shareHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $shareHash
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function setShareHash(?string $shareHash): Collection
|
||||||
|
{
|
||||||
|
$this->shareHash = $shareHash;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPublic(): bool
|
||||||
|
{
|
||||||
|
return $this->public;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $public
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function setPublic(bool $public): Collection
|
||||||
|
{
|
||||||
|
$this->public = $public;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Image[]|DoctrineCollection
|
||||||
|
*/
|
||||||
|
public function getImages(): DoctrineCollection
|
||||||
|
{
|
||||||
|
return $this->images;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Image[]|DoctrineCollection $images
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function setImages(DoctrineCollection $images): Collection
|
||||||
|
{
|
||||||
|
$this->images = $images;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Image $image
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function addImage(Image $image): Collection
|
||||||
|
{
|
||||||
|
if (!$this->images->contains($image)) {
|
||||||
|
$this->images->add($image);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Image $image
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function removeImage(Image $image): Collection
|
||||||
|
{
|
||||||
|
if ($this->images->contains($image)) {
|
||||||
|
$this->images->removeElement($image);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param bool $val
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function setDeepSerialize(bool $val): Collection
|
||||||
|
{
|
||||||
|
$this->deepSerialize = $val;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data for json serializer
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function jsonSerialize(): array
|
||||||
|
{
|
||||||
|
$serialized = [
|
||||||
|
'id' => $this->getId(),
|
||||||
|
'name' => $this->getName(),
|
||||||
|
'slug' => $this->getSlug(),
|
||||||
|
'shareHash' => $this->getShareHash(),
|
||||||
|
'public' => $this->isPublic(),
|
||||||
|
];
|
||||||
|
if ($this->deepSerialize) {
|
||||||
|
array_push($serialized, [
|
||||||
|
'images' => $this->getImages()->getValues(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return $serialized;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,227 +1,258 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use JsonSerializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
* @ORM\Table(
|
* @ORM\Table(
|
||||||
* name="images",
|
* name="images",
|
||||||
* indexes={
|
* indexes={
|
||||||
* @ORM\Index(name="dir_idx", columns={"dir"}),
|
* @ORM\Index(name="img_dir_idx", columns={"dir"}),
|
||||||
* @ORM\Index(name="path_idx", columns={"path"})
|
* @ORM\Index(name="img_path_idx", columns={"path"})
|
||||||
* }
|
* }
|
||||||
* )
|
* )
|
||||||
* @ORM\HasLifecycleCallbacks
|
* @ORM\HasLifecycleCallbacks
|
||||||
*/
|
*/
|
||||||
class Image implements \JsonSerializable
|
class Image implements JsonSerializable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\Column(name="id", type="integer")
|
||||||
|
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Id
|
* @ORM\Column(name="dir", type="string", length=255, nullable=false)
|
||||||
* @ORM\Column(name="id", type="integer")
|
* @var string
|
||||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
*/
|
||||||
* @var int
|
private $dir = "";
|
||||||
*/
|
|
||||||
private $id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(name="dir", type="string", length=255, nullable=false)
|
* @ORM\Column(name="label", type="string", length=250, nullable=true)
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $dir = "";
|
private $label = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(name="label", type="string", length=250, nullable=true)
|
* @ORM\Column(name="path", type="string", length=250, nullable=false)
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $label = "";
|
private $path = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(name="path", type="string", length=250, nullable=false)
|
* @ORM\Column(name="width", type="integer")
|
||||||
* @var string
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $path = "";
|
private $width = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(name="width", type="integer")
|
* @ORM\Column(name="height", type="integer")
|
||||||
* @var string
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $width = 0;
|
private $height = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(name="type", type="integer")
|
* @ORM\Column(name="thumb_width", type="integer")
|
||||||
* @var string
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $height = 0;
|
private $thumbWidth = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(name="thumb_width", type="integer")
|
* @ORM\Column(name="thumb_height", type="integer")
|
||||||
* @var string
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $thumbWidth = 0;
|
private $thumbHeight = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(name="thumb_type", type="integer")
|
* @ORM\ManyToOne(targetEntity="Album", inversedBy="images")
|
||||||
* @var string
|
* @ORM\JoinColumn(name="album_id", referencedColumnName="id")
|
||||||
*/
|
* @var Album
|
||||||
private $thumbHeight = 0;
|
*/
|
||||||
|
private $album;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $id
|
* @param mixed $id
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setId(?int $id): Image
|
public function setId(?int $id): Image
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getDir(): ?string
|
public function getDir(): ?string
|
||||||
{
|
{
|
||||||
return $this->dir;
|
return $this->dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $dir
|
* @param string $dir
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setDir(?string $dir): Image
|
public function setDir(?string $dir): Image
|
||||||
{
|
{
|
||||||
$this->dir = $dir;
|
$this->dir = $dir;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getLabel(): ?string
|
public function getLabel(): ?string
|
||||||
{
|
{
|
||||||
return $this->label;
|
return $this->label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $label
|
* @param string $label
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setLabel(?string $label): Image
|
public function setLabel(?string $label): Image
|
||||||
{
|
{
|
||||||
$this->label = $label;
|
$this->label = $label;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getPath(): ?string
|
public function getPath(): ?string
|
||||||
{
|
{
|
||||||
return $this->path;
|
return $this->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setPath(?string $path): Image
|
public function setPath(?string $path): Image
|
||||||
{
|
{
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getWidth(): ?int
|
public function getWidth(): ?int
|
||||||
{
|
{
|
||||||
return $this->width;
|
return $this->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $width
|
* @param int $width
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setWidth(?int $width): Image
|
public function setWidth(?int $width): Image
|
||||||
{
|
{
|
||||||
$this->width = $width;
|
$this->width = $width;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getHeight(): ?int
|
public function getHeight(): ?int
|
||||||
{
|
{
|
||||||
return $this->height;
|
return $this->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $height
|
* @param int $height
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setHeight(?int $height): Image
|
public function setHeight(?int $height): Image
|
||||||
{
|
{
|
||||||
$this->height = $height;
|
$this->height = $height;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getThumbWidth(): ?int
|
public function getThumbWidth(): ?int
|
||||||
{
|
{
|
||||||
return $this->thumbWidth;
|
return $this->thumbWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $width
|
* @param int $width
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setThumbWidth(?int $width): Image
|
public function setThumbWidth(?int $width): Image
|
||||||
{
|
{
|
||||||
$this->thumbWidth = $width;
|
$this->thumbWidth = $width;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getThumbHeight(): ?int
|
public function getThumbHeight(): ?int
|
||||||
{
|
{
|
||||||
return $this->thumbHeight;
|
return $this->thumbHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $height
|
* @param int $height
|
||||||
* @return Image
|
* @return Image
|
||||||
*/
|
*/
|
||||||
public function setThumbHeight(?int $height): Image
|
public function setThumbHeight(?int $height): Image
|
||||||
{
|
{
|
||||||
$this->thumbHeight = $height;
|
$this->thumbHeight = $height;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function jsonSerialize()
|
/**
|
||||||
{
|
* @return Album
|
||||||
return [
|
*/
|
||||||
'dir' => $this->getDir(),
|
public function getAlbum(): Album
|
||||||
'label' => $this->getLabel(),
|
{
|
||||||
'path' => $this->getPath(),
|
return $this->album;
|
||||||
'width' => $this->getWidth(),
|
}
|
||||||
'height' => $this->getHeight(),
|
|
||||||
'thumbWidth' => $this->getThumbWidth(),
|
/**
|
||||||
'thumbHeight' => $this->getThumbHeight(),
|
* @param Album $album
|
||||||
];
|
* @return Image
|
||||||
}
|
*/
|
||||||
|
public function setAlbum(Album $album): Image
|
||||||
|
{
|
||||||
|
$this->album = $album;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data for json serializer
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function jsonSerialize(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'dir' => $this->getDir(),
|
||||||
|
'label' => $this->getLabel(),
|
||||||
|
'path' => $this->getPath(),
|
||||||
|
'width' => $this->getWidth(),
|
||||||
|
'height' => $this->getHeight(),
|
||||||
|
'thumbWidth' => $this->getThumbWidth(),
|
||||||
|
'thumbHeight' => $this->getThumbHeight(),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
35
src/App/Handler/Album.php
Normal file
35
src/App/Handler/Album.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use ApiLibs\AbstractHandler\CrudHandler;
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Zend\Diactoros\Response\JsonResponse;
|
||||||
|
|
||||||
|
class Album extends CrudHandler
|
||||||
|
{
|
||||||
|
private $galleryService;
|
||||||
|
|
||||||
|
public function __construct(GalleryService $galleryService)
|
||||||
|
{
|
||||||
|
$this->galleryService = $galleryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws \Doctrine\ORM\ORMException
|
||||||
|
* @throws \Doctrine\ORM\OptimisticLockException
|
||||||
|
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||||
|
*/
|
||||||
|
public function get(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$id = (int)$request->getAttribute('id');
|
||||||
|
return new JsonResponse($this->galleryService->getAlbum($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
src/App/Handler/AlbumFactory.php
Normal file
18
src/App/Handler/AlbumFactory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class AlbumFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): RequestHandlerInterface
|
||||||
|
{
|
||||||
|
$galleryService = $container->get(GalleryService::class);
|
||||||
|
return new Album($galleryService);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/App/Handler/Collection.php
Normal file
35
src/App/Handler/Collection.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use ApiLibs\AbstractHandler\CrudHandler;
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Zend\Diactoros\Response\JsonResponse;
|
||||||
|
|
||||||
|
class Collection extends CrudHandler
|
||||||
|
{
|
||||||
|
private $galleryService;
|
||||||
|
|
||||||
|
public function __construct(GalleryService $galleryService)
|
||||||
|
{
|
||||||
|
$this->galleryService = $galleryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws \Doctrine\ORM\ORMException
|
||||||
|
* @throws \Doctrine\ORM\OptimisticLockException
|
||||||
|
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||||
|
*/
|
||||||
|
public function get(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$id = (int)$request->getAttribute('id');
|
||||||
|
return new JsonResponse($this->galleryService->getCollection($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
src/App/Handler/CollectionFactory.php
Normal file
18
src/App/Handler/CollectionFactory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class CollectionFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): RequestHandlerInterface
|
||||||
|
{
|
||||||
|
$galleryService = $container->get(GalleryService::class);
|
||||||
|
return new Collection($galleryService);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/App/Handler/ExportAlbum.php
Normal file
29
src/App/Handler/ExportAlbum.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Zend\Diactoros\Response\RedirectResponse;
|
||||||
|
|
||||||
|
class ExportAlbum implements RequestHandlerInterface
|
||||||
|
{
|
||||||
|
private $galleryService;
|
||||||
|
|
||||||
|
public function __construct(GalleryService $galleryService)
|
||||||
|
{
|
||||||
|
$this->galleryService = $galleryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$slug = $request->getAttribute('slug', false);
|
||||||
|
$this->galleryService->getExportFileName($slug);
|
||||||
|
return new RedirectResponse("/export/{$slug}.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
src/App/Handler/ExportAlbumFactory.php
Normal file
18
src/App/Handler/ExportAlbumFactory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class ExportAlbumFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): RequestHandlerInterface
|
||||||
|
{
|
||||||
|
$galleryService = $container->get(GalleryService::class);
|
||||||
|
return new ExportAlbum($galleryService);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,15 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Action;
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
use App\Service\GalleryService;
|
use App\Service\GalleryService;
|
||||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
use Zend\Diactoros\Response;
|
use Zend\Diactoros\Response;
|
||||||
use Zend\Diactoros\Stream;
|
use Zend\Diactoros\Stream;
|
||||||
|
|
||||||
class GetImageAction implements ServerMiddlewareInterface
|
class GetImage implements RequestHandlerInterface
|
||||||
{
|
{
|
||||||
private $galleryService;
|
private $galleryService;
|
||||||
|
|
||||||
@ -18,7 +20,7 @@ class GetImageAction implements ServerMiddlewareInterface
|
|||||||
$this->galleryService = $galleryService;
|
$this->galleryService = $galleryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
{
|
{
|
||||||
$slug = $request->getAttribute('slug', false);
|
$slug = $request->getAttribute('slug', false);
|
||||||
$image = $request->getAttribute('image', false);
|
$image = $request->getAttribute('image', false);
|
||||||
@ -33,8 +35,6 @@ class GetImageAction implements ServerMiddlewareInterface
|
|||||||
->withHeader('Content-Transfer-Encoding', 'Binary')
|
->withHeader('Content-Transfer-Encoding', 'Binary')
|
||||||
->withHeader('Content-Description', 'File Transfer')
|
->withHeader('Content-Description', 'File Transfer')
|
||||||
->withHeader('Pragma', 'public')
|
->withHeader('Pragma', 'public')
|
||||||
// ->withHeader('Expires', '0')
|
|
||||||
// ->withHeader('Cache-Control', 'must-revalidate')
|
|
||||||
->withBody($imageStream)
|
->withBody($imageStream)
|
||||||
->withHeader('Content-Length', "{$imageStream->getSize()}");
|
->withHeader('Content-Length', "{$imageStream->getSize()}");
|
||||||
}
|
}
|
||||||
18
src/App/Handler/GetImageFactory.php
Normal file
18
src/App/Handler/GetImageFactory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class GetImageFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): RequestHandlerInterface
|
||||||
|
{
|
||||||
|
$galleryService = $container->get(GalleryService::class);
|
||||||
|
return new GetImage($galleryService);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/App/Handler/HomePage.php
Normal file
20
src/App/Handler/HomePage.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Zend\Diactoros\Response\JsonResponse;
|
||||||
|
|
||||||
|
class HomePage implements RequestHandlerInterface
|
||||||
|
{
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return new JsonResponse([
|
||||||
|
'welcome' => 'Congratulations! You have reahced the end of the internet.',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/App/Handler/Image.php
Normal file
35
src/App/Handler/Image.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use ApiLibs\AbstractHandler\CrudHandler;
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Zend\Diactoros\Response\JsonResponse;
|
||||||
|
|
||||||
|
class Image extends CrudHandler
|
||||||
|
{
|
||||||
|
private $galleryService;
|
||||||
|
|
||||||
|
public function __construct(GalleryService $galleryService)
|
||||||
|
{
|
||||||
|
$this->galleryService = $galleryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws \Doctrine\ORM\ORMException
|
||||||
|
* @throws \Doctrine\ORM\OptimisticLockException
|
||||||
|
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||||
|
*/
|
||||||
|
public function get(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$id = (int)$request->getAttribute('id');
|
||||||
|
return new JsonResponse($this->galleryService->getImage($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
src/App/Handler/ImageFactory.php
Normal file
18
src/App/Handler/ImageFactory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class ImageFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): RequestHandlerInterface
|
||||||
|
{
|
||||||
|
$galleryService = $container->get(GalleryService::class);
|
||||||
|
return new Image($galleryService);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/App/Handler/ListGalleries.php
Normal file
26
src/App/Handler/ListGalleries.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Zend\Diactoros\Response\JsonResponse;
|
||||||
|
|
||||||
|
class ListGalleries implements RequestHandlerInterface
|
||||||
|
{
|
||||||
|
private $galleryService;
|
||||||
|
|
||||||
|
public function __construct(GalleryService $galleryService)
|
||||||
|
{
|
||||||
|
$this->galleryService = $galleryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return new JsonResponse($this->galleryService->loadGalleryData(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/App/Handler/ListGalleriesFactory.php
Normal file
18
src/App/Handler/ListGalleriesFactory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Handler;
|
||||||
|
|
||||||
|
use App\Service\GalleryService;
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class ListGalleriesFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container): RequestHandlerInterface
|
||||||
|
{
|
||||||
|
$galleryService = $container->get(GalleryService::class);
|
||||||
|
return new ListGalleries($galleryService);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Middleware;
|
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
class PreFlightMiddleware
|
|
||||||
{
|
|
||||||
const ALLOW_HEADERS = [
|
|
||||||
'DNT',
|
|
||||||
'X-CustomHeader',
|
|
||||||
'Keep-Alive',
|
|
||||||
'User-Agent',
|
|
||||||
'X-Requested-With',
|
|
||||||
'If-Modified-Since',
|
|
||||||
'Cache-Control',
|
|
||||||
'Content-Type',
|
|
||||||
'Authorization',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __invoke(RequestInterface $request, ResponseInterface $response, callable $next)
|
|
||||||
{
|
|
||||||
$requestMethod = strtoupper($request->getMethod());
|
|
||||||
if ($requestMethod == 'OPTIONS') {
|
|
||||||
return $response
|
|
||||||
->withHeader('Accept', 'OPTIONS,GET,POST,PUT,PATCH,DELETE')
|
|
||||||
->withHeader('Access-Control-Allow-Origin', '*')
|
|
||||||
->withHeader('Access-Control-Allow-Methods', 'OPTIONS,GET,POST,PUT,PATCH,DELETE')
|
|
||||||
->withHeader('Access-Control-Allow-Headers', implode(",", self::ALLOW_HEADERS));
|
|
||||||
}
|
|
||||||
return $next($request, $response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Response;
|
|
||||||
|
|
||||||
use Zend\Diactoros\Response\JsonResponse;
|
|
||||||
|
|
||||||
class JsonCorsResponse extends JsonResponse
|
|
||||||
{
|
|
||||||
const ALLOW_HEADERS = [
|
|
||||||
'DNT',
|
|
||||||
'X-CustomHeader',
|
|
||||||
'Keep-Alive',
|
|
||||||
'User-Agent',
|
|
||||||
'X-Requested-With',
|
|
||||||
'If-Modified-Since',
|
|
||||||
'Cache-Control',
|
|
||||||
'Content-Type',
|
|
||||||
'Authorization',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
$data,
|
|
||||||
$status = 200,
|
|
||||||
array $headers = [],
|
|
||||||
$encodingOptions = self::DEFAULT_JSON_FLAGS
|
|
||||||
) {
|
|
||||||
$headers['Access-Control-Allow-Origin'] = '*';
|
|
||||||
$headers['Access-Control-Allow-Methods'] = 'OPTIONS,GET,POST,PUT,PATCH,DELETE';
|
|
||||||
$headers['Access-Control-Allow-Headers'] = implode(",", self::ALLOW_HEADERS);
|
|
||||||
parent::__construct($data, $status, $headers, $encodingOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
|
use App\Entity\Album;
|
||||||
|
use App\Entity\Collection;
|
||||||
use App\Entity\Image;
|
use App\Entity\Image;
|
||||||
use Doctrine\ORM\EntityManager;
|
use Doctrine\ORM\EntityManager;
|
||||||
use Imagine\Gd\Imagine;
|
use Imagine\Gd\Imagine;
|
||||||
@ -14,195 +17,239 @@ use Zend\Config\Reader\Yaml;
|
|||||||
class GalleryService
|
class GalleryService
|
||||||
{
|
{
|
||||||
|
|
||||||
const CONFIG_FILE = 'data/galleries/config.yaml';
|
const CONFIG_FILE = 'data/galleries/config.yaml';
|
||||||
const IMAGE_BASEDIR = 'data/galleries/%s/';
|
const IMAGE_BASEDIR = 'data/galleries/%s/';
|
||||||
const EXPORT_DIR = 'data/export/';
|
const EXPORT_DIR = 'data/export/';
|
||||||
const THUMBNAIL_SIZE = 750;
|
const THUMBNAIL_SIZE = 750;
|
||||||
|
|
||||||
protected $contentTypeMap = [
|
protected $contentTypeMap = [
|
||||||
'jpg' => 'image/jpeg',
|
'jpg' => 'image/jpeg',
|
||||||
'jpeg' => 'image/jpeg',
|
'jpeg' => 'image/jpeg',
|
||||||
'png' => 'image/png',
|
'png' => 'image/png',
|
||||||
];
|
];
|
||||||
protected $config;
|
protected $config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var EntityManager
|
* @var EntityManager
|
||||||
*/
|
*/
|
||||||
protected $em;
|
protected $em;
|
||||||
|
|
||||||
public function __construct(EntityManager $entityManager)
|
public function __construct(EntityManager $entityManager)
|
||||||
{
|
{
|
||||||
$this->em = $entityManager;
|
$this->em = $entityManager;
|
||||||
}
|
|
||||||
|
|
||||||
public function getExportFileName(string $slug)
|
|
||||||
{
|
|
||||||
$config = $this->getConfig();
|
|
||||||
if (!isset($config['galleries'][$slug])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$dir = $config['galleries'][$slug]['dir'];
|
|
||||||
return $this->ensureExportFileExists($dir, "{$slug}.zip");
|
|
||||||
}
|
|
||||||
|
|
||||||
private function ensureExportFileExists(string $dir, string $filename)
|
|
||||||
{
|
|
||||||
$exportName = self::EXPORT_DIR . $filename;
|
|
||||||
if(file_exists($exportName)) {
|
|
||||||
return $exportName;
|
|
||||||
}
|
|
||||||
$exportLock = sprintf("data/tmp/%s.lock", $dir);
|
|
||||||
|
|
||||||
if(file_exists($exportLock)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$images = array_map('basename', glob($this->getImageDir($dir) . "*.{jpg,jpeg,png}", GLOB_BRACE));
|
/**
|
||||||
|
* @param int $id
|
||||||
$zipName = tempnam("data/tmp", "export");
|
* @return Album|null
|
||||||
touch($exportLock);
|
* @throws \Doctrine\ORM\ORMException
|
||||||
$zipArchive = new \ZipArchive();
|
* @throws \Doctrine\ORM\OptimisticLockException
|
||||||
$zipArchive->open($zipName, \ZipArchive::CREATE);
|
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||||
foreach ($images as $image) {
|
*/
|
||||||
ini_set("max_execution_time", 60);
|
public function getAlbum(int $id): ?Album
|
||||||
$zipArchive->addFile(
|
{
|
||||||
sprintf(self::IMAGE_BASEDIR,$dir) . $image,
|
/** @var Album|null $result */
|
||||||
"{$dir}/{$image}"
|
$result = $this->em->find(Album::class, $id);
|
||||||
);
|
return $result;
|
||||||
}
|
|
||||||
$zipArchive->close();
|
|
||||||
rename($zipName, $exportName);
|
|
||||||
unlink($exportLock);
|
|
||||||
return $exportName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadGalleryData($includeHidden = false)
|
|
||||||
{
|
|
||||||
$config = $this->getConfig();
|
|
||||||
$albums = [];
|
|
||||||
foreach ($config['galleries'] as $id => $data) {
|
|
||||||
if ($includeHidden || $data['public']) {
|
|
||||||
$galleryImages = $this->loadGalleryImages($data['dir']);
|
|
||||||
$albums[] = [
|
|
||||||
'slug' => $id,
|
|
||||||
'name' => $data['name'],
|
|
||||||
'coverImage' => isset($data['cover'])
|
|
||||||
? $this->getCoverImage($galleryImages, $data['cover'])
|
|
||||||
: null,
|
|
||||||
'date' => $this->getGalleryDate($data['dir']),
|
|
||||||
'type' => $data['type'],
|
|
||||||
'isNew' => $data['new'],
|
|
||||||
'isPublic' => $data['public'],
|
|
||||||
'images' => $galleryImages,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $albums;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getCoverImage(array &$images, string $coverFileName): Image
|
|
||||||
{
|
|
||||||
$filtered = array_values(array_filter($images, function(Image $image) use ($coverFileName) {
|
|
||||||
return $image->getPath() == $coverFileName;
|
|
||||||
}));
|
|
||||||
return array_pop($filtered);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getGalleryDate(string $dir): string
|
|
||||||
{
|
|
||||||
$timestamp = sprintf("@%s", filemtime($this->getImageDir($dir)));
|
|
||||||
$date = new \DateTime($timestamp);
|
|
||||||
return $date->format("Y-m-d");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $dir
|
|
||||||
* @return Image[]
|
|
||||||
* @todo implement label for image in some way
|
|
||||||
*/
|
|
||||||
private function loadGalleryImages(string $dir): array
|
|
||||||
{
|
|
||||||
$images = array_map('basename', glob(
|
|
||||||
sprintf(self::IMAGE_BASEDIR . "*.{jpg,jpeg,png}", $dir),
|
|
||||||
GLOB_BRACE
|
|
||||||
));
|
|
||||||
$imagine = new Imagine();
|
|
||||||
return array_map(function ($imagePath) use ($dir, $imagine) {
|
|
||||||
$imageEntity = $this->em->getRepository(Image::class)->findOneBy([
|
|
||||||
'dir' => $dir,
|
|
||||||
'path' => $imagePath,
|
|
||||||
]);
|
|
||||||
$this->ensureThumbnailExists($dir, $imagePath);
|
|
||||||
if (null === $imageEntity) {
|
|
||||||
$image = $imagine->open($this->getImageDir($dir) . $imagePath);
|
|
||||||
$imageSize = $image->getSize();
|
|
||||||
unset($image);
|
|
||||||
|
|
||||||
$thumb = $imagine->open($this->getThumbDir($dir) . $imagePath);
|
|
||||||
$thumbSize = $thumb->getSize();
|
|
||||||
unset($thumb);
|
|
||||||
|
|
||||||
$imageEntity = new Image();
|
|
||||||
$imageEntity->setLabel("")
|
|
||||||
->setDir($dir)
|
|
||||||
->setPath($imagePath)
|
|
||||||
->setWidth($imageSize->getWidth())
|
|
||||||
->setHeight($imageSize->getHeight())
|
|
||||||
->setThumbWidth($thumbSize->getWidth())
|
|
||||||
->setThumbHeight($thumbSize->getHeight())
|
|
||||||
;
|
|
||||||
$this->em->persist($imageEntity);
|
|
||||||
$this->em->flush();
|
|
||||||
}
|
|
||||||
return $imageEntity;
|
|
||||||
}, $images);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function ensureThumbnailExists(string $dir, string $imageName) {
|
|
||||||
set_time_limit(30);
|
|
||||||
$imageDir = $this->getImageDir($dir);
|
|
||||||
$thumbPath = $imageDir . "thumb_" . self::THUMBNAIL_SIZE;
|
|
||||||
@mkdir($thumbPath);
|
|
||||||
$thumbImageName = $thumbPath . "/" . $imageName;
|
|
||||||
|
|
||||||
if (!file_exists($thumbImageName)) {
|
|
||||||
$thumbSize = new Box(self::THUMBNAIL_SIZE, self::THUMBNAIL_SIZE * 10);
|
|
||||||
$imagine = new Imagine();
|
|
||||||
$image = $imagine->open($imageDir . $imageName)
|
|
||||||
->thumbnail($thumbSize, ImageInterface::THUMBNAIL_INSET);
|
|
||||||
$image->effects()->sharpen();
|
|
||||||
$image->save($thumbImageName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $thumbImageName;
|
/**
|
||||||
}
|
* @param int $id
|
||||||
|
* @return Collection|null
|
||||||
public function getImageFileName(string $slug, string $image, $isThumbnail = false): string
|
* @throws \Doctrine\ORM\ORMException
|
||||||
{
|
* @throws \Doctrine\ORM\OptimisticLockException
|
||||||
$config = $this->getConfig();
|
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||||
$dir = $config['galleries'][$slug]['dir'];
|
*/
|
||||||
$this->ensureThumbnailExists($config['galleries'][$slug]['dir'], $image);
|
public function getCollection(int $id): ?Collection
|
||||||
return $isThumbnail
|
{
|
||||||
? ($this->getThumbDir($dir) . $image)
|
/** @var Collection|null $result */
|
||||||
: ($this->getImageDir($dir) . $image);
|
$result = $this->em->find(Collection::class, $id);
|
||||||
}
|
return $result;
|
||||||
|
}
|
||||||
private function getImageDir($dir): string {
|
|
||||||
return sprintf(self::IMAGE_BASEDIR, $dir);
|
/**
|
||||||
}
|
* @param int $id
|
||||||
|
* @return Image|null
|
||||||
private function getThumbDir($dir): string {
|
* @throws \Doctrine\ORM\ORMException
|
||||||
return sprintf(self::IMAGE_BASEDIR, "{$dir}/thumb_" . self::THUMBNAIL_SIZE);
|
* @throws \Doctrine\ORM\OptimisticLockException
|
||||||
}
|
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||||
|
*/
|
||||||
private function getConfig()
|
public function getImage(int $id): ?Image
|
||||||
{
|
{
|
||||||
if (null === $this->config) {
|
/** @var Image|null $result */
|
||||||
$parser = new Parser();
|
$result = $this->em->find(Image::class, $id);
|
||||||
$configReader = new Yaml([$parser, 'parse']);
|
return $result;
|
||||||
$this->config = $configReader->fromFile(self::CONFIG_FILE);
|
}
|
||||||
|
|
||||||
|
public function getExportFileName(string $slug)
|
||||||
|
{
|
||||||
|
$config = $this->getConfig();
|
||||||
|
if (!isset($config['galleries'][$slug])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$dir = $config['galleries'][$slug]['dir'];
|
||||||
|
return $this->ensureExportFileExists($dir, "{$slug}.zip");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function ensureExportFileExists(string $dir, string $filename)
|
||||||
|
{
|
||||||
|
$exportName = self::EXPORT_DIR . $filename;
|
||||||
|
if (file_exists($exportName)) {
|
||||||
|
return $exportName;
|
||||||
|
}
|
||||||
|
$exportLock = sprintf("data/tmp/%s.lock", $dir);
|
||||||
|
|
||||||
|
if (file_exists($exportLock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$images = array_map('basename', glob($this->getImageDir($dir) . "*.{jpg,jpeg,png}", GLOB_BRACE));
|
||||||
|
|
||||||
|
$zipName = tempnam("data/tmp", "export");
|
||||||
|
touch($exportLock);
|
||||||
|
$zipArchive = new \ZipArchive();
|
||||||
|
$zipArchive->open($zipName, \ZipArchive::CREATE);
|
||||||
|
foreach ($images as $image) {
|
||||||
|
ini_set("max_execution_time", 60);
|
||||||
|
$zipArchive->addFile(
|
||||||
|
sprintf(self::IMAGE_BASEDIR, $dir) . $image,
|
||||||
|
"{$dir}/{$image}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$zipArchive->close();
|
||||||
|
rename($zipName, $exportName);
|
||||||
|
unlink($exportLock);
|
||||||
|
return $exportName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadGalleryData($includeHidden = false)
|
||||||
|
{
|
||||||
|
$config = $this->getConfig();
|
||||||
|
$albums = [];
|
||||||
|
foreach ($config['galleries'] as $id => $data) {
|
||||||
|
if ($includeHidden || $data['public']) {
|
||||||
|
$galleryImages = $this->loadGalleryImages($data['dir']);
|
||||||
|
$albums[] = [
|
||||||
|
'slug' => $id,
|
||||||
|
'name' => $data['name'],
|
||||||
|
'coverImage' => isset($data['cover'])
|
||||||
|
? $this->getCoverImage($galleryImages, $data['cover'])
|
||||||
|
: null,
|
||||||
|
'date' => $this->getGalleryDate($data['dir']),
|
||||||
|
'type' => $data['type'],
|
||||||
|
'isNew' => $data['new'],
|
||||||
|
'isPublic' => $data['public'],
|
||||||
|
'images' => $galleryImages,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $albums;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCoverImage(array &$images, string $coverFileName): Image
|
||||||
|
{
|
||||||
|
$filtered = array_values(array_filter($images, function (Image $image) use ($coverFileName) {
|
||||||
|
return $image->getPath() == $coverFileName;
|
||||||
|
}));
|
||||||
|
return array_pop($filtered);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getGalleryDate(string $dir): string
|
||||||
|
{
|
||||||
|
$timestamp = sprintf("@%s", filemtime($this->getImageDir($dir)));
|
||||||
|
$date = new \DateTime($timestamp);
|
||||||
|
return $date->format("Y-m-d");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $dir
|
||||||
|
* @return Image[]
|
||||||
|
* @todo implement label for image in some way
|
||||||
|
*/
|
||||||
|
private function loadGalleryImages(string $dir): array
|
||||||
|
{
|
||||||
|
$images = array_map('basename', glob(
|
||||||
|
sprintf(self::IMAGE_BASEDIR . "*.{jpg,jpeg,png}", $dir),
|
||||||
|
GLOB_BRACE
|
||||||
|
));
|
||||||
|
$imagine = new Imagine();
|
||||||
|
return array_map(function ($imagePath) use ($dir, $imagine) {
|
||||||
|
$imageEntity = $this->em->getRepository(Image::class)->findOneBy([
|
||||||
|
'dir' => $dir,
|
||||||
|
'path' => $imagePath,
|
||||||
|
]);
|
||||||
|
$this->ensureThumbnailExists($dir, $imagePath);
|
||||||
|
if (null === $imageEntity) {
|
||||||
|
$image = $imagine->open($this->getImageDir($dir) . $imagePath);
|
||||||
|
$imageSize = $image->getSize();
|
||||||
|
unset($image);
|
||||||
|
|
||||||
|
$thumb = $imagine->open($this->getThumbDir($dir) . $imagePath);
|
||||||
|
$thumbSize = $thumb->getSize();
|
||||||
|
unset($thumb);
|
||||||
|
|
||||||
|
$imageEntity = new Image();
|
||||||
|
$imageEntity->setLabel("")
|
||||||
|
->setDir($dir)
|
||||||
|
->setPath($imagePath)
|
||||||
|
->setWidth($imageSize->getWidth())
|
||||||
|
->setHeight($imageSize->getHeight())
|
||||||
|
->setThumbWidth($thumbSize->getWidth())
|
||||||
|
->setThumbHeight($thumbSize->getHeight());
|
||||||
|
$this->em->persist($imageEntity);
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
return $imageEntity;
|
||||||
|
}, $images);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function ensureThumbnailExists(string $dir, string $imageName)
|
||||||
|
{
|
||||||
|
set_time_limit(30);
|
||||||
|
$imageDir = $this->getImageDir($dir);
|
||||||
|
$thumbPath = $imageDir . "thumb_" . self::THUMBNAIL_SIZE;
|
||||||
|
@mkdir($thumbPath);
|
||||||
|
$thumbImageName = $thumbPath . "/" . $imageName;
|
||||||
|
|
||||||
|
if (!file_exists($thumbImageName)) {
|
||||||
|
$thumbSize = new Box(self::THUMBNAIL_SIZE, self::THUMBNAIL_SIZE * 10);
|
||||||
|
$imagine = new Imagine();
|
||||||
|
$image = $imagine->open($imageDir . $imageName)
|
||||||
|
->thumbnail($thumbSize, ImageInterface::THUMBNAIL_INSET);
|
||||||
|
$image->effects()->sharpen();
|
||||||
|
$image->save($thumbImageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $thumbImageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getImageFileName(string $slug, string $image, $isThumbnail = false): string
|
||||||
|
{
|
||||||
|
$config = $this->getConfig();
|
||||||
|
$dir = $config['galleries'][$slug]['dir'];
|
||||||
|
$this->ensureThumbnailExists($config['galleries'][$slug]['dir'], $image);
|
||||||
|
return $isThumbnail
|
||||||
|
? ($this->getThumbDir($dir) . $image)
|
||||||
|
: ($this->getImageDir($dir) . $image);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getImageDir($dir): string
|
||||||
|
{
|
||||||
|
return sprintf(self::IMAGE_BASEDIR, $dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getThumbDir($dir): string
|
||||||
|
{
|
||||||
|
return sprintf(self::IMAGE_BASEDIR, "{$dir}/thumb_" . self::THUMBNAIL_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getConfig()
|
||||||
|
{
|
||||||
|
if (null === $this->config) {
|
||||||
|
$parser = new Parser();
|
||||||
|
$configReader = new Yaml([$parser, 'parse']);
|
||||||
|
$this->config = $configReader->fromFile(self::CONFIG_FILE);
|
||||||
|
}
|
||||||
|
return $this->config;
|
||||||
}
|
}
|
||||||
return $this->config;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
use Interop\Container\ContainerInterface;
|
use Interop\Container\ContainerInterface;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace AppTest\Action;
|
namespace AppTest\Action;
|
||||||
|
|
||||||
use App\Action\HomePageAction;
|
use App\Handler\HomePage;
|
||||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
use Prophecy\Argument;
|
||||||
@ -24,7 +24,7 @@ class HomePageActionTest extends TestCase
|
|||||||
|
|
||||||
public function testReturnsJsonResponseWhenNoTemplateRendererProvided()
|
public function testReturnsJsonResponseWhenNoTemplateRendererProvided()
|
||||||
{
|
{
|
||||||
$homePage = new HomePageAction($this->router->reveal(), null);
|
$homePage = new HomePage($this->router->reveal(), null);
|
||||||
$response = $homePage->process(
|
$response = $homePage->process(
|
||||||
$this->prophesize(ServerRequestInterface::class)->reveal(),
|
$this->prophesize(ServerRequestInterface::class)->reveal(),
|
||||||
$this->prophesize(DelegateInterface::class)->reveal()
|
$this->prophesize(DelegateInterface::class)->reveal()
|
||||||
@ -40,7 +40,7 @@ class HomePageActionTest extends TestCase
|
|||||||
->render('app::home-page', Argument::type('array'))
|
->render('app::home-page', Argument::type('array'))
|
||||||
->willReturn('');
|
->willReturn('');
|
||||||
|
|
||||||
$homePage = new HomePageAction($this->router->reveal(), $renderer->reveal());
|
$homePage = new HomePage($this->router->reveal(), $renderer->reveal());
|
||||||
|
|
||||||
$response = $homePage->process(
|
$response = $homePage->process(
|
||||||
$this->prophesize(ServerRequestInterface::class)->reveal(),
|
$this->prophesize(ServerRequestInterface::class)->reveal(),
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace AppTest\Action;
|
namespace AppTest\Action;
|
||||||
|
|
||||||
use App\Action\HomePageAction;
|
use App\Handler\HomePage;
|
||||||
use App\Action\HomePageFactory;
|
use App\Handler\HomePageFactory;
|
||||||
use Interop\Container\ContainerInterface;
|
use Interop\Container\ContainerInterface;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Zend\Expressive\Router\RouterInterface;
|
use Zend\Expressive\Router\RouterInterface;
|
||||||
@ -31,7 +31,7 @@ class HomePageFactoryTest extends TestCase
|
|||||||
|
|
||||||
$homePage = $factory($this->container->reveal());
|
$homePage = $factory($this->container->reveal());
|
||||||
|
|
||||||
$this->assertInstanceOf(HomePageAction::class, $homePage);
|
$this->assertInstanceOf(HomePage::class, $homePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFactoryWithTemplate()
|
public function testFactoryWithTemplate()
|
||||||
@ -46,6 +46,6 @@ class HomePageFactoryTest extends TestCase
|
|||||||
|
|
||||||
$homePage = $factory($this->container->reveal());
|
$homePage = $factory($this->container->reveal());
|
||||||
|
|
||||||
$this->assertInstanceOf(HomePageAction::class, $homePage);
|
$this->assertInstanceOf(HomePage::class, $homePage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace AppTest\Action;
|
namespace AppTest\Action;
|
||||||
|
|
||||||
use App\Action\PingAction;
|
use App\Handler\PingAction;
|
||||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user