first commit
This commit is contained in:
commit
cb8ac3a08e
13
.env.example
Normal file
13
.env.example
Normal file
@ -0,0 +1,13 @@
|
||||
# DB Configuration
|
||||
DB_DRIVER=pdo_mysql
|
||||
DB_HOST=myTube-backend-mysql
|
||||
DB_PORT=3306
|
||||
DB_USER=myTube
|
||||
DB_PASSWORD=pass
|
||||
DB_NAME=myTube
|
||||
DB_NAME_LOG=log
|
||||
|
||||
# MyTube Setup
|
||||
INIT_USER_NAME=admin
|
||||
INIT_USER_PASSWORD=password
|
||||
INIT_USER_MAIL=admin@test.com
|
||||
7
.gitattributes
vendored
Normal file
7
.gitattributes
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/.gitattributes export-ignore
|
||||
/.github/ export-ignore
|
||||
/.laminas-ci.json export-ignore
|
||||
/phpcs.xml.dist export-ignore
|
||||
/psalm.xml.dist export-ignore
|
||||
/psalm-baseline.xml export-ignore
|
||||
/renovate.json export-ignore
|
||||
40
.github/workflows/create branch on issue.yml
vendored
Normal file
40
.github/workflows/create branch on issue.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: Create Branch on Issue Transition to In Progress
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- edited
|
||||
|
||||
jobs:
|
||||
create-branch:
|
||||
if: github.event.changes.issue.labels
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get issue details
|
||||
run: |
|
||||
issue_title=$(jq -r ".issue.number" "$GITHUB_EVENT_PATH")
|
||||
previous_labels=$(jq -r ".changes.labels.from" "$GITHUB_EVENT_PATH")
|
||||
current_labels=$(jq -r ".issue.labels | map(.name) | join(\", \")" "$GITHUB_EVENT_PATH")
|
||||
branch_name=""
|
||||
|
||||
# Check if the issue transitioned from 'Todo' to 'In Progress'
|
||||
if [[ "$previous_labels" == *"Todo"* && "$current_labels" == *"In Progress"* ]]; then
|
||||
project_name="hp-be" # Verwende "hp-be" als Projektnamen
|
||||
branch_name="${project_name}-${issue_title}"
|
||||
echo "Branch name: $branch_name"
|
||||
fi
|
||||
|
||||
echo "::set-output name=branch_name::$branch_name"
|
||||
shell: bash
|
||||
|
||||
- name: Create and switch to new branch
|
||||
run: |
|
||||
branch_name="${{ steps.create-branch.outputs.branch_name }}"
|
||||
if [ -n "$branch_name" ]; then
|
||||
git checkout -b "$branch_name"
|
||||
git push origin "$branch_name"
|
||||
fi
|
||||
working-directory: ${{ github.workspace }}
|
||||
39
.github/workflows/php.yml
vendored
Normal file
39
.github/workflows/php.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: PHP Composer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate --strict
|
||||
|
||||
- name: Cache Composer packages
|
||||
id: composer-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vendor
|
||||
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-php-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress
|
||||
|
||||
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
|
||||
# Docs: https://getcomposer.org/doc/articles/scripts.md
|
||||
|
||||
# - name: Run test suite
|
||||
# run: composer run-script test
|
||||
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/.phpcs-cache
|
||||
/.phpunit.result.cache
|
||||
/.idea
|
||||
/clover.xml
|
||||
/coveralls-upload.json
|
||||
/phpunit.xml
|
||||
|
||||
/data/cache/
|
||||
/data/db/
|
||||
/public/data/
|
||||
/var/
|
||||
/vendor/
|
||||
|
||||
*.env
|
||||
composer.lock
|
||||
3
.htaccess
Normal file
3
.htaccess
Normal file
@ -0,0 +1,3 @@
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
RewriteRule ^pages/([^/]*)/(.*)$ pages.php?$1=$2
|
||||
1
COPYRIGHT.md
Normal file
1
COPYRIGHT.md
Normal file
@ -0,0 +1 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
|
||||
26
LICENSE.md
Normal file
26
LICENSE.md
Normal file
@ -0,0 +1,26 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
39
bin/clear-config-cache.php
Normal file
39
bin/clear-config-cache.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
chdir(__DIR__ . '/../');
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
$config = include 'config/config.php';
|
||||
|
||||
if (! isset($config['config_cache_path'])) {
|
||||
echo "No configuration cache path found" . PHP_EOL;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (! file_exists($config['config_cache_path'])) {
|
||||
printf(
|
||||
"Configured config cache file '%s' not found%s",
|
||||
$config['config_cache_path'],
|
||||
PHP_EOL
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (false === unlink($config['config_cache_path'])) {
|
||||
printf(
|
||||
"Error removing config cache file '%s'%s",
|
||||
$config['config_cache_path'],
|
||||
PHP_EOL
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf(
|
||||
"Removed configured config cache file '%s'%s",
|
||||
$config['config_cache_path'],
|
||||
PHP_EOL
|
||||
);
|
||||
exit(0);
|
||||
30
bin/console.php
Normal file
30
bin/console.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use MyTube\Infrastructure\Logging\Logger\Logger;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
require_once __DIR__ . '/../config/autoload/defines.php';
|
||||
require APP_ROOT . '/vendor/autoload.php';
|
||||
|
||||
call_user_func(function() {
|
||||
$container = require APP_ROOT . '/config/container.php';
|
||||
|
||||
$config = $container->get('config');
|
||||
$commands = $config['console']['commands'];
|
||||
|
||||
$app = new Application();
|
||||
foreach ($commands as $command) {
|
||||
$app->add($container->get($command));
|
||||
}
|
||||
|
||||
try {
|
||||
$app->setCatchExceptions(false);
|
||||
$app->run();
|
||||
} catch (Throwable $e) {
|
||||
$logger = new Logger();
|
||||
$logger->error(
|
||||
$e->getMessage(),
|
||||
['exception' => $e]
|
||||
);
|
||||
}
|
||||
});
|
||||
312
bin/createApi.php
Normal file
312
bin/createApi.php
Normal file
@ -0,0 +1,312 @@
|
||||
<?php
|
||||
|
||||
if (count($argv) !== 6) {
|
||||
echo 'Use of this Command:' . PHP_EOL
|
||||
. 'createApi API_IsExternal API_Namespace API_Name CQRS_IsCommand CQRS_Namespace' . PHP_EOL;
|
||||
die;
|
||||
}
|
||||
|
||||
$projectSourceDirectory = 'src/';
|
||||
$projectNamespace = 'MyTube';
|
||||
|
||||
$apiType = strtolower($argv[1]) === 'true' ? 'External' : 'Internal';
|
||||
$apiNamespace = $argv[2];
|
||||
$apiName = $argv[3];
|
||||
$cqrsType = strtolower($argv[4]) === 'true' ? 'Command' : 'Query';
|
||||
$cqrsNamespace = $argv[5];
|
||||
$originalCqrsNamespace = $cqrsNamespace;
|
||||
|
||||
$apiDirectoryPath = $projectSourceDirectory . 'ApiDomain/' . $apiType . '/' . $apiNamespace . '/';
|
||||
$cqrsDirectoryPath = $projectSourceDirectory . 'HandlingDomain/' . $cqrsNamespace . '/';
|
||||
|
||||
# API Handler
|
||||
$apiHandlerName = $apiName . 'Handler';
|
||||
$apiHandlerNamespace = $projectNamespace . '\\API\\' . $apiType . '\\' . $apiNamespace . '\\Handler';
|
||||
$apiHandlerUsingNamespace = $apiHandlerNamespace . '\\' . $apiHandlerName;
|
||||
$apiHandlerFilePath = $apiDirectoryPath . 'src/Handler/' . $apiHandlerName . '.php';
|
||||
|
||||
# Response Formatter
|
||||
$apiResponseFormatterName = $apiName . 'ResponseFormatter';
|
||||
$apiResponseFormatterNamespace = $projectNamespace . '\\API\\' . $apiType . '\\' . $apiNamespace . '\\ResponseFormatter';
|
||||
$apiResponseFormatterUsingNamespace = $apiResponseFormatterNamespace . '\\' . $apiResponseFormatterName;
|
||||
$apiResponseFormatterFilePath = $apiDirectoryPath . 'src/ResponseFormatter/' . $apiResponseFormatterName . '.php';
|
||||
|
||||
# CQRS
|
||||
$cqrsFilePath = $cqrsDirectoryPath . 'src/Handler/' . $cqrsType . '/' . $apiName . '/';
|
||||
$cqrsName = $apiName . $cqrsType;
|
||||
$cqrsVariableName = lcfirst($cqrsName);
|
||||
$cqrsNamespace = $projectNamespace . '\\Handling\\' . $cqrsNamespace . '\\Handler\\' . $cqrsType . '\\' . $apiName;
|
||||
|
||||
# Command / Query
|
||||
$cqrsPath = $cqrsFilePath . $cqrsName . '.php';
|
||||
$cqrsUsingNamespace = $cqrsNamespace . '\\' . $cqrsName;
|
||||
|
||||
# Result
|
||||
$cqrsResultName = $cqrsName . 'Result';
|
||||
$cqrsResultVariableName = lcfirst($cqrsResultName);
|
||||
$cqrsResultPath = $cqrsFilePath . $cqrsResultName . '.php';
|
||||
$cqrsResultUsingNamespace = $cqrsNamespace . '\\' . $cqrsResultName;
|
||||
|
||||
# Handler
|
||||
$cqrsHandlerName = $cqrsName . 'Handler';
|
||||
$cqrsHandlerVariableName = lcfirst($cqrsHandlerName);
|
||||
$cqrsHandlerPath = $cqrsFilePath . $cqrsName . 'Handler' . '.php';
|
||||
$cqrsHandlerUsingNamespace = $cqrsNamespace . '\\' . $cqrsHandlerName;
|
||||
|
||||
# Builder
|
||||
$cqrsBuilderName = $cqrsName . 'Builder';
|
||||
$cqrsBuilderVariableName = lcfirst($cqrsBuilderName);
|
||||
$cqrsBuilderPath = $cqrsFilePath . $cqrsName . 'Builder' . '.php';
|
||||
$cqrsBuilderUsingNamespace = $cqrsNamespace . '\\' . $cqrsBuilderName;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
########## WRITE FILES ###############
|
||||
function writeToFile($path, $content) {
|
||||
echo 'Writing contents to file ' . $path . PHP_EOL;
|
||||
|
||||
$directory = pathinfo($path, PATHINFO_DIRNAME);
|
||||
if (!is_dir($directory)) {
|
||||
mkdir($directory, 0755, true);
|
||||
}
|
||||
|
||||
file_put_contents($path, $content);
|
||||
}
|
||||
|
||||
if (!file_exists($apiDirectoryPath)) {
|
||||
|
||||
$routesFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use {$apiHandlerUsingNamespace};
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'TODO.TODO',
|
||||
'path' => '/api/TODO/TODO[/]',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
{$apiHandlerName}::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
";
|
||||
$routesFilePath = $apiDirectoryPath . 'config/routes.php';
|
||||
writeToFile($routesFilePath, $routesFileContent);
|
||||
|
||||
$serviceManagerFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use {$apiHandlerUsingNamespace};
|
||||
use {$apiResponseFormatterUsingNamespace};
|
||||
use Reinfi\\DependencyInjection\\Factory\\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Handler
|
||||
{$apiHandlerName}::class => AutoWiringFactory::class,
|
||||
|
||||
// Response Formatter
|
||||
{$apiResponseFormatterName}::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
";
|
||||
$serviceManagerFilePath = $apiDirectoryPath . 'config/service_manager.php';
|
||||
writeToFile($serviceManagerFilePath, $serviceManagerFileContent);
|
||||
|
||||
$configProviderFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\\API\\{$apiType}\\{$apiNamespace};
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
";
|
||||
$configProviderFilePath = $apiDirectoryPath . 'src/ConfigProvider.php';
|
||||
writeToFile($configProviderFilePath, $configProviderFileContent);
|
||||
}
|
||||
|
||||
if (!file_exists($cqrsDirectoryPath)) {
|
||||
$serviceManagerFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use {$cqrsHandlerUsingNamespace};
|
||||
use {$cqrsBuilderUsingNamespace};
|
||||
use Reinfi\\DependencyInjection\\Factory\\AutoWiringFactory;
|
||||
use Reinfi\\DependencyInjection\\Factory\\InjectionFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
/// CQRS
|
||||
// {$apiName}
|
||||
{$cqrsBuilderName}::class => AutoWiringFactory::class,
|
||||
{$cqrsHandlerName}::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
";
|
||||
$serviceManagerFilePath = $cqrsDirectoryPath . 'config/service_manager.php';
|
||||
writeToFile($serviceManagerFilePath, $serviceManagerFileContent);
|
||||
|
||||
$configProviderFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\\Handling\\{$originalCqrsNamespace};
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
";
|
||||
$configProviderFilePath = $cqrsDirectoryPath . 'src/ConfigProvider.php';
|
||||
writeToFile($configProviderFilePath, $configProviderFileContent);
|
||||
|
||||
}
|
||||
|
||||
$apiHandlerFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$apiHandlerNamespace};
|
||||
|
||||
use {$cqrsHandlerUsingNamespace};
|
||||
use {$cqrsBuilderUsingNamespace};
|
||||
use {$apiResponseFormatterUsingNamespace};
|
||||
use {$projectNamespace}\\Infrastructure\\Request\\Middleware\\AnalyzeBodyMiddleware;
|
||||
use {$projectNamespace}\\Infrastructure\\Response\\SuccessResponse;
|
||||
use Psr\\Http\\Message\\ResponseInterface;
|
||||
use Psr\\Http\\Message\\ServerRequestInterface;
|
||||
use Psr\\Http\\Server\\RequestHandlerInterface;
|
||||
|
||||
class {$apiHandlerName} implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly {$cqrsHandlerName} \${$cqrsHandlerVariableName},
|
||||
private readonly {$cqrsBuilderName} \${$cqrsBuilderVariableName},
|
||||
private readonly {$apiResponseFormatterName} \$responseFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface \$request): ResponseInterface
|
||||
{
|
||||
\$data = \$request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
\${$cqrsVariableName} = \$this->{$cqrsBuilderVariableName}->build(
|
||||
\$data
|
||||
);
|
||||
\$result = \$this->{$cqrsHandlerVariableName}->execute(\${$cqrsVariableName});
|
||||
|
||||
return new SuccessResponse(\$this->responseFormatter->format(\$result));
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($apiHandlerFilePath, $apiHandlerFileContent);
|
||||
|
||||
$apiResponseFormatterFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$apiResponseFormatterNamespace};
|
||||
|
||||
use {$cqrsResultUsingNamespace};
|
||||
|
||||
class {$apiResponseFormatterName}
|
||||
{
|
||||
public function format({$cqrsResultName} \${$cqrsResultVariableName}): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($apiResponseFormatterFilePath, $apiResponseFormatterFileContent);
|
||||
|
||||
$cqrsFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$cqrsNamespace};
|
||||
|
||||
class {$cqrsName}
|
||||
{
|
||||
public function __construct(
|
||||
#TODO
|
||||
) {
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($cqrsPath, $cqrsFileContent);
|
||||
|
||||
$cqrsResultFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$cqrsNamespace};
|
||||
|
||||
class {$cqrsResultName}
|
||||
{
|
||||
public function __construct(
|
||||
#TODO
|
||||
) {
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($cqrsResultPath, $cqrsResultFileContent);
|
||||
|
||||
$cqrsHandlerFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$cqrsNamespace};
|
||||
|
||||
class {$cqrsHandlerName}
|
||||
{
|
||||
public function __construct(
|
||||
#TODO
|
||||
) {
|
||||
}
|
||||
|
||||
public function execute({$cqrsName} \${$cqrsVariableName}): {$cqrsResultName}
|
||||
{
|
||||
return new {$cqrsResultName}();
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($cqrsHandlerPath, $cqrsHandlerFileContent);
|
||||
|
||||
$cqrsBuilderFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$cqrsNamespace};
|
||||
|
||||
class {$cqrsBuilderName}
|
||||
{
|
||||
public function build(
|
||||
#TODO
|
||||
): {$cqrsName} {
|
||||
return new {$cqrsName}(
|
||||
#TODO
|
||||
);
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($cqrsBuilderPath, $cqrsBuilderFileContent);
|
||||
194
bin/createPipeline.php
Normal file
194
bin/createPipeline.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
if (count($argv) < 4) {
|
||||
echo 'Use of this Command:' . PHP_EOL
|
||||
. 'createPipeline Handling_Namespace Pipeline_Name Step_1_Name Step_2_Name' . PHP_EOL;
|
||||
die;
|
||||
}
|
||||
|
||||
$projectSourceDirectory = 'src/';
|
||||
$projectNamespace = 'MyTube';
|
||||
|
||||
$pipelineNamespace = $argv[1];
|
||||
$pipelineName = $argv[2];
|
||||
$stepNames = array_slice($argv, 3);
|
||||
|
||||
# Pipeline
|
||||
$pipelineClassName = $pipelineName . 'Pipeline';
|
||||
$pipelineVariableName = lcfirst($pipelineClassName);
|
||||
$pipelineDirectoryPath = $projectSourceDirectory . 'HandlingDomain/' . $pipelineNamespace . '/';
|
||||
$pipelineFilePath = $pipelineDirectoryPath . 'src/Pipeline/' . $pipelineName . '/' . $pipelineClassName . '.php';
|
||||
$pipelineFullNamespace = $projectNamespace . '\\Handling\\' . $pipelineNamespace . '\\Pipeline\\' . $pipelineName;
|
||||
$pipelineUsingNamespace = $pipelineFullNamespace . '\\' . $pipelineClassName;
|
||||
|
||||
# Payload
|
||||
$payloadClassName = $pipelineName . 'Payload';
|
||||
$payloadVariableName = lcfirst($payloadClassName);
|
||||
$payloadFilePath = $projectSourceDirectory . 'HandlingDomain/' . $pipelineNamespace . '/src/Pipeline/' . $pipelineName . '/' . $payloadClassName . '.php';
|
||||
$payloadFullNamespace = $projectNamespace . '\\Handling\\' . $pipelineNamespace . '\\Pipeline\\' . $pipelineName;
|
||||
$payloadUsingNamespace = $payloadFullNamespace . '\\' . $payloadClassName;
|
||||
|
||||
# Step
|
||||
$stepsFilePath = $projectSourceDirectory . 'HandlingDomain/' . $pipelineNamespace . '/src/Pipeline/' . $pipelineName . '/Step/';
|
||||
$stepsFullNamespace = $projectNamespace . '\\Handling\\' . $pipelineNamespace . '\\Pipeline\\' . $pipelineName . '\\Step';
|
||||
|
||||
$steps = [];
|
||||
foreach ($stepNames as $stepName) {
|
||||
$stepClassName = $stepName . 'Step';
|
||||
$steps[] = [
|
||||
'stepClassName' => $stepClassName,
|
||||
'stepVariableName' => lcfirst($stepClassName),
|
||||
'stepFilePath' => $stepsFilePath . $stepClassName . '.php',
|
||||
'stepUsingNamespace' => 'use ' . $payloadFullNamespace . '\\Step\\' . $stepClassName,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
########## WRITE FILES ###############
|
||||
function writeToFile($path, $content) {
|
||||
echo 'Writing contents to file ' . $path . PHP_EOL;
|
||||
|
||||
$directory = pathinfo($path, PATHINFO_DIRNAME);
|
||||
if (!is_dir($directory)) {
|
||||
mkdir($directory, 0755, true);
|
||||
}
|
||||
|
||||
file_put_contents($path, $content);
|
||||
}
|
||||
|
||||
$createNamespaceFiles = !file_exists($pipelineDirectoryPath);
|
||||
|
||||
$stepsUsingNamespaces = [];
|
||||
$stepsDeclarations = [];
|
||||
$stepsAutoWirings = [];
|
||||
$stepsReferences = [];
|
||||
|
||||
foreach ($steps as $step) {
|
||||
$stepClassName = $step['stepClassName'];
|
||||
$stepVariableName = $step['stepVariableName'];
|
||||
$stepFilePath = $step['stepFilePath'];
|
||||
$stepUsingNamespace = $step['stepUsingNamespace'];
|
||||
|
||||
$stepsUsingNamespaces[] = $stepUsingNamespace . ';';
|
||||
$stepsDeclarations[] = 'private readonly ' . $stepClassName . ' $' . $stepVariableName . ',';
|
||||
$stepsAutoWirings[] = $stepClassName . '::class => AutoWiringFactory::class,';
|
||||
$stepsReferences[] = '$this->' . $stepVariableName . ',';
|
||||
|
||||
$stepFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$stepsFullNamespace};
|
||||
|
||||
use {$payloadUsingNamespace};
|
||||
|
||||
use teewurst\\Pipeline\\PipelineInterface;
|
||||
use teewurst\\Pipeline\\TaskInterface;
|
||||
|
||||
class {$stepClassName} implements TaskInterface
|
||||
{
|
||||
public function __construct(
|
||||
#TODO
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(\$payload, PipelineInterface \$pipeline): void
|
||||
{
|
||||
/** @var {$payloadClassName} \${$payloadVariableName} */
|
||||
\${$payloadVariableName} = \$payload;
|
||||
|
||||
\$pipeline->next()(\$payload, \$pipeline);
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($stepFilePath, $stepFileContent);
|
||||
}
|
||||
|
||||
$stepsUsingNamespace = implode(PHP_EOL, $stepsUsingNamespaces);
|
||||
$stepsDeclaration = implode(PHP_EOL . ' ', $stepsDeclarations);
|
||||
$stepsAutoWiring = implode(PHP_EOL . ' ', $stepsAutoWirings);
|
||||
$stepsReference = implode(PHP_EOL . ' ', $stepsReferences);
|
||||
|
||||
|
||||
|
||||
$pipelineFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$pipelineFullNamespace};
|
||||
|
||||
{$stepsUsingNamespace}
|
||||
use teewurst\\Pipeline\\Pipeline;
|
||||
|
||||
class {$pipelineClassName} extends Pipeline
|
||||
{
|
||||
public function __construct(
|
||||
{$stepsDeclaration}
|
||||
) {
|
||||
parent::__construct([
|
||||
{$stepsReference}
|
||||
]);
|
||||
}
|
||||
}
|
||||
";
|
||||
writeToFile($pipelineFilePath, $pipelineFileContent);
|
||||
|
||||
$payloadFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {$payloadFullNamespace};
|
||||
|
||||
class {$payloadClassName}
|
||||
{
|
||||
#TODO
|
||||
}
|
||||
";
|
||||
writeToFile($payloadFilePath, $payloadFileContent);
|
||||
|
||||
|
||||
|
||||
if ($createNamespaceFiles) {
|
||||
$serviceManagerFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use {$pipelineUsingNamespace};
|
||||
{$stepsUsingNamespace}
|
||||
use Reinfi\\DependencyInjection\\Factory\\AutoWiringFactory;
|
||||
use Reinfi\\DependencyInjection\\Factory\\InjectionFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
/// Pipeline
|
||||
// {$pipelineName}
|
||||
{$pipelineClassName}::class => AutoWiringFactory::class,
|
||||
{$stepsAutoWiring}
|
||||
],
|
||||
];
|
||||
";
|
||||
$serviceManagerFilePath = $pipelineDirectoryPath . 'config/service_manager.php';
|
||||
writeToFile($serviceManagerFilePath, $serviceManagerFileContent);
|
||||
|
||||
$configProviderFileContent = "<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\\Handling\\{$pipelineNamespace};
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
";
|
||||
$configProviderFilePath = $pipelineDirectoryPath . 'src/ConfigProvider.php';
|
||||
writeToFile($configProviderFilePath, $configProviderFileContent);
|
||||
|
||||
}
|
||||
91
bin/doctrine-migrations-log.php
Normal file
91
bin/doctrine-migrations-log.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../config/autoload/defines.php';
|
||||
require APP_ROOT . '/vendor/autoload.php';
|
||||
|
||||
use MyTube\Data\Business\Manager\MyTubeEntityManager;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\DBAL\DriverManager;
|
||||
use Doctrine\Migrations\Configuration\Configuration;
|
||||
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
|
||||
use Doctrine\Migrations\Configuration\Migration\ExistingConfiguration;
|
||||
use Doctrine\Migrations\DependencyFactory;
|
||||
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
|
||||
use Doctrine\Migrations\Tools\Console\Command\DumpSchemaCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\GenerateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\LatestCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ListCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\RollupCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\StatusCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\SyncMetadataCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\VersionCommand;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
use Doctrine\ORM\Tools\Setup;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
$isDevMode = true;
|
||||
|
||||
$container = require APP_ROOT . '/config/container.php';
|
||||
$config = $container->get('config');
|
||||
$doctrineConfig = $config['doctrine'];
|
||||
$paths = $doctrineConfig['driver']['orm_log_annotation_driver']['paths'];
|
||||
|
||||
$dbParams = $doctrineConfig['connection']['orm_log']['params'];
|
||||
$migrationsConf = $doctrineConfig['migrations_configuration']['orm_log'];
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
$driver = new AnnotationDriver($reader, $paths);
|
||||
|
||||
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
|
||||
$config->setMetadataDriverImpl($driver);
|
||||
$entityManager = $container->get(MyTubeEntityManager::class);
|
||||
|
||||
try {
|
||||
$connection = DriverManager::getConnection($dbParams);
|
||||
} catch (\Doctrine\DBAL\Exception $e) {
|
||||
echo $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
|
||||
$configuration = new Configuration($connection);
|
||||
|
||||
$configuration->addMigrationsDirectory(
|
||||
$migrationsConf['namespace'],
|
||||
$migrationsConf['directory']
|
||||
);
|
||||
$configuration->setAllOrNothing(true);
|
||||
$configuration->setCheckDatabasePlatform(false);
|
||||
|
||||
$storageConfiguration = new TableMetadataStorageConfiguration();
|
||||
$storageConfiguration->setTableName($migrationsConf['table']);
|
||||
|
||||
$configuration->setMetadataStorageConfiguration($storageConfiguration);
|
||||
|
||||
$dependencyFactory = DependencyFactory::fromConnection(
|
||||
new ExistingConfiguration($configuration),
|
||||
new ExistingConnection($connection)
|
||||
);
|
||||
|
||||
$cli = new Application('Doctrine Migrations');
|
||||
$cli->setCatchExceptions(true);
|
||||
|
||||
$cli->addCommands([
|
||||
new DumpSchemaCommand($dependencyFactory),
|
||||
new ExecuteCommand($dependencyFactory),
|
||||
new GenerateCommand($dependencyFactory),
|
||||
new LatestCommand($dependencyFactory),
|
||||
new ListCommand($dependencyFactory),
|
||||
new MigrateCommand($dependencyFactory),
|
||||
new RollupCommand($dependencyFactory),
|
||||
new StatusCommand($dependencyFactory),
|
||||
new SyncMetadataCommand($dependencyFactory),
|
||||
new VersionCommand($dependencyFactory),
|
||||
]);
|
||||
|
||||
try {
|
||||
$cli->run();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
91
bin/doctrine-migrations.php
Normal file
91
bin/doctrine-migrations.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../config/autoload/defines.php';
|
||||
require APP_ROOT . '/vendor/autoload.php';
|
||||
|
||||
use MyTube\Data\Business\Manager\MyTubeEntityManager;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\DBAL\DriverManager;
|
||||
use Doctrine\Migrations\Configuration\Configuration;
|
||||
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
|
||||
use Doctrine\Migrations\Configuration\Migration\ExistingConfiguration;
|
||||
use Doctrine\Migrations\DependencyFactory;
|
||||
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
|
||||
use Doctrine\Migrations\Tools\Console\Command\DumpSchemaCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\GenerateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\LatestCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ListCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\RollupCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\StatusCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\SyncMetadataCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\VersionCommand;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
use Doctrine\ORM\Tools\Setup;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
$isDevMode = true;
|
||||
|
||||
$container = require APP_ROOT . '/config/container.php';
|
||||
$config = $container->get('config');
|
||||
$doctrineConfig = $config['doctrine'];
|
||||
$paths = $doctrineConfig['driver']['orm_myTube_annotation_driver']['paths'];
|
||||
|
||||
$dbParams = $doctrineConfig['connection']['orm_myTube']['params'];
|
||||
$migrationsConf = $doctrineConfig['migrations_configuration']['orm_myTube'];
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
$driver = new AnnotationDriver($reader, $paths);
|
||||
|
||||
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
|
||||
$config->setMetadataDriverImpl($driver);
|
||||
$entityManager = $container->get(MyTubeEntityManager::class);
|
||||
|
||||
try {
|
||||
$connection = DriverManager::getConnection($dbParams);
|
||||
} catch (\Doctrine\DBAL\Exception $e) {
|
||||
echo $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
|
||||
$configuration = new Configuration($connection);
|
||||
|
||||
$configuration->addMigrationsDirectory(
|
||||
$migrationsConf['namespace'],
|
||||
$migrationsConf['directory']
|
||||
);
|
||||
$configuration->setAllOrNothing(true);
|
||||
$configuration->setCheckDatabasePlatform(false);
|
||||
|
||||
$storageConfiguration = new TableMetadataStorageConfiguration();
|
||||
$storageConfiguration->setTableName($migrationsConf['table']);
|
||||
|
||||
$configuration->setMetadataStorageConfiguration($storageConfiguration);
|
||||
|
||||
$dependencyFactory = DependencyFactory::fromConnection(
|
||||
new ExistingConfiguration($configuration),
|
||||
new ExistingConnection($connection)
|
||||
);
|
||||
|
||||
$cli = new Application('Doctrine Migrations');
|
||||
$cli->setCatchExceptions(true);
|
||||
|
||||
$cli->addCommands([
|
||||
new DumpSchemaCommand($dependencyFactory),
|
||||
new ExecuteCommand($dependencyFactory),
|
||||
new GenerateCommand($dependencyFactory),
|
||||
new LatestCommand($dependencyFactory),
|
||||
new ListCommand($dependencyFactory),
|
||||
new MigrateCommand($dependencyFactory),
|
||||
new RollupCommand($dependencyFactory),
|
||||
new StatusCommand($dependencyFactory),
|
||||
new SyncMetadataCommand($dependencyFactory),
|
||||
new VersionCommand($dependencyFactory),
|
||||
]);
|
||||
|
||||
try {
|
||||
$cli->run();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
3
bin/script/build
Executable file
3
bin/script/build
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec build
|
||||
3
bin/script/down
Executable file
3
bin/script/down
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec down
|
||||
23
bin/script/exec
Executable file
23
bin/script/exec
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
COMMAND="$@"
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
#LOAD ENV VARIABLES FROM .ENV
|
||||
export $(grep -v '^#' "${SCRIPT_DIR}/../../.env" | xargs)
|
||||
|
||||
#MAC
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
docker compose -f "${SCRIPT_DIR}/../../docker/docker-compose-mac.yml" $COMMAND
|
||||
|
||||
#LINUX
|
||||
elif [[ "$OSTYPE" == "linux-gnu" ]]; then
|
||||
docker compose -f "${SCRIPT_DIR}/../../docker/docker-compose.yml" $COMMAND
|
||||
|
||||
else
|
||||
echo "Dieses Skript wird auf deinem Gerät nicht unterstützt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#UNSET ENV VARIABLES FROM .ENV
|
||||
unset $(grep -v '^#' "${SCRIPT_DIR}/../../.env" | sed -E 's/(.*)=.*/\1/' | xargs)
|
||||
32
bin/script/init
Executable file
32
bin/script/init
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
|
||||
ENV_DIR=$(realpath $PROJECT_DIR/../../)
|
||||
|
||||
# Check .env file
|
||||
if [ ! -f "$PROJECT_DIR/.env" ]
|
||||
then
|
||||
echo "Create .env file from example..."
|
||||
cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env"
|
||||
echo ".env file created, please change variables and call me again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build and start docker containers
|
||||
$SCRIPT_DIR/exec build
|
||||
$SCRIPT_DIR/exec up -d
|
||||
|
||||
# Source drun
|
||||
source $ENV_DIR/bin/script/drun
|
||||
|
||||
# Install PHP packages
|
||||
drun myTube-backend composer install
|
||||
|
||||
# Migrate databases to current version
|
||||
drun myTube-backend composer dmm
|
||||
drun myTube-backend composer dmlm
|
||||
|
||||
# Insert setup for project after this line
|
||||
drun myTube-backend composer console rbac:update
|
||||
drun myTube-backend composer console init:data
|
||||
3
bin/script/stop
Executable file
3
bin/script/stop
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec stop
|
||||
3
bin/script/up
Executable file
3
bin/script/up
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec up -d
|
||||
130
composer.development.json
Normal file
130
composer.development.json
Normal file
@ -0,0 +1,130 @@
|
||||
{
|
||||
"require": {
|
||||
"laminas\/laminas-servicemanager": "^3.21",
|
||||
"mezzio\/mezzio-laminasrouter": "^3.8",
|
||||
"reinfi\/zf-dependency-injection": "^5.4",
|
||||
"laminas\/laminas-config-aggregator": "^1.13",
|
||||
"doctrine\/doctrine-orm-module": "5.0.*",
|
||||
"doctrine\/migrations": "^3.5",
|
||||
"doctrine\/orm": "2.11.3",
|
||||
"doctrine\/persistence": "2.2.*",
|
||||
"ramsey\/uuid-doctrine": "^1.8",
|
||||
"roave\/psr-container-doctrine": "^3.1",
|
||||
"mezzio\/mezzio": "^3.17",
|
||||
"mezzio\/mezzio-helpers": "^5.15",
|
||||
"symfony\/cache": "5.4.8",
|
||||
"doctrine\/dbal": "^3.6",
|
||||
"teewurst\/psr4-advanced-wildcard-composer-plugin": "^3.0",
|
||||
"laminas\/laminas-crypt": "^3.10",
|
||||
"monolog\/monolog": "^3.4",
|
||||
"laminas\/laminas-mail": "^2.23",
|
||||
"teewurst\/pipeline": "^3.0",
|
||||
"guzzlehttp\/guzzle": "^7.8",
|
||||
"micilini\/video-stream": "^1.0",
|
||||
"nesbot\/carbon": "^3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyTube\\API\\Console\\": "src\/ApiDomain\/Console\/src",
|
||||
"MyTube\\API\\External\\Authentication\\": "src\/ApiDomain\/External\/Authentication\/src",
|
||||
"MyTube\\API\\External\\Health\\": "src\/ApiDomain\/External\/Health\/src",
|
||||
"MyTube\\API\\External\\Tag\\": "src\/ApiDomain\/External\/Tag\/src",
|
||||
"MyTube\\API\\External\\TagList\\": "src\/ApiDomain\/External\/TagList\/src",
|
||||
"MyTube\\API\\External\\User\\": "src\/ApiDomain\/External\/User\/src",
|
||||
"MyTube\\API\\External\\Video\\": "src\/ApiDomain\/External\/Video\/src",
|
||||
"MyTube\\API\\External\\VideoList\\": "src\/ApiDomain\/External\/VideoList\/src",
|
||||
"MyTube\\Data\\Business\\": "src\/DataDomain\/Business\/src",
|
||||
"MyTube\\Data\\Log\\": "src\/DataDomain\/Log\/src",
|
||||
"MyTube\\Handling\\Registration\\": "src\/HandlingDomain\/Registration\/src",
|
||||
"MyTube\\Handling\\Role\\": "src\/HandlingDomain\/Role\/src",
|
||||
"MyTube\\Handling\\Tag\\": "src\/HandlingDomain\/Tag\/src",
|
||||
"MyTube\\Handling\\TagList\\": "src\/HandlingDomain\/TagList\/src",
|
||||
"MyTube\\Handling\\User\\": "src\/HandlingDomain\/User\/src",
|
||||
"MyTube\\Handling\\UserSession\\": "src\/HandlingDomain\/UserSession\/src",
|
||||
"MyTube\\Handling\\Video\\": "src\/HandlingDomain\/Video\/src",
|
||||
"MyTube\\Handling\\VideoList\\": "src\/HandlingDomain\/VideoList\/src",
|
||||
"MyTube\\Infrastructure\\Database\\": "src\/Infrastructure\/Database\/src",
|
||||
"MyTube\\Infrastructure\\DependencyInjection\\": "src\/Infrastructure\/DependencyInjection\/src",
|
||||
"MyTube\\Infrastructure\\Encryption\\": "src\/Infrastructure\/Encryption\/src",
|
||||
"MyTube\\Infrastructure\\Exception\\": "src\/Infrastructure\/Exception\/src",
|
||||
"MyTube\\Infrastructure\\Logging\\": "src\/Infrastructure\/Logging\/src",
|
||||
"MyTube\\Infrastructure\\Rbac\\": "src\/Infrastructure\/Rbac\/src",
|
||||
"MyTube\\Infrastructure\\Request\\": "src\/Infrastructure\/Request\/src",
|
||||
"MyTube\\Infrastructure\\Response\\": "src\/Infrastructure\/Response\/src",
|
||||
"MyTube\\Infrastructure\\Session\\": "src\/Infrastructure\/Session\/src",
|
||||
"MyTube\\Infrastructure\\UuidGenerator\\": "src\/Infrastructure\/UuidGenerator\/src"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"teewurst\/psr4-advanced-wildcard-composer-plugin": {
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyTube\\API\\%s\\%s\\": "src\/ApiDomain\/{*}\/{*}\/src\/",
|
||||
"MyTube\\Data\\%s\\": "src\/DataDomain\/{*}\/src\/",
|
||||
"MyTube\\Handling\\%s\\": "src\/HandlingDomain\/{*}\/src\/",
|
||||
"MyTube\\Infrastructure\\%s\\": "src\/Infrastructure\/{*}\/src\/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"MyTube\\API\\%s\\%s\\": "src\/ApiDomain\/{*}\/{*}\/src\/",
|
||||
"MyTube\\Data\\%s\\": "src\/DataDomain\/{*}\/src\/",
|
||||
"MyTube\\Handling\\%s\\": "src\/HandlingDomain\/{*}\/src\/",
|
||||
"MyTube\\Infrastructure\\%s\\": "src\/Infrastructure\/{*}\/src\/"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dmg": "php bin\/doctrine-migrations.php migrations:generate",
|
||||
"dmm": "php bin\/doctrine-migrations.php migrations:migrate --no-interaction",
|
||||
"dmlg": "php bin\/doctrine-migrations-log.php migrations:generate",
|
||||
"dmlm": "php bin\/doctrine-migrations-log.php migrations:migrate --no-interaction",
|
||||
"console": "php bin\/console.php",
|
||||
"createApi": "php bin\/createApi.php",
|
||||
"createPipeline": "php bin\/createPipeline.php",
|
||||
"da": [
|
||||
"composer dump-autoload",
|
||||
"composer dump-autoload --dev"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"teewurst\/psr4-advanced-wildcard-composer-plugin": true
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony\/dotenv": "^6.3"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"MyTube\\API\\External\\Authentication\\": "src\/ApiDomain\/External\/Authentication\/src",
|
||||
"MyTube\\API\\External\\Health\\": "src\/ApiDomain\/External\/Health\/src",
|
||||
"MyTube\\API\\External\\Tag\\": "src\/ApiDomain\/External\/Tag\/src",
|
||||
"MyTube\\API\\External\\TagList\\": "src\/ApiDomain\/External\/TagList\/src",
|
||||
"MyTube\\API\\External\\User\\": "src\/ApiDomain\/External\/User\/src",
|
||||
"MyTube\\API\\External\\Video\\": "src\/ApiDomain\/External\/Video\/src",
|
||||
"MyTube\\API\\External\\VideoList\\": "src\/ApiDomain\/External\/VideoList\/src",
|
||||
"MyTube\\Data\\Business\\": "src\/DataDomain\/Business\/src",
|
||||
"MyTube\\Data\\Log\\": "src\/DataDomain\/Log\/src",
|
||||
"MyTube\\Handling\\Registration\\": "src\/HandlingDomain\/Registration\/src",
|
||||
"MyTube\\Handling\\Role\\": "src\/HandlingDomain\/Role\/src",
|
||||
"MyTube\\Handling\\Tag\\": "src\/HandlingDomain\/Tag\/src",
|
||||
"MyTube\\Handling\\TagList\\": "src\/HandlingDomain\/TagList\/src",
|
||||
"MyTube\\Handling\\User\\": "src\/HandlingDomain\/User\/src",
|
||||
"MyTube\\Handling\\UserSession\\": "src\/HandlingDomain\/UserSession\/src",
|
||||
"MyTube\\Handling\\Video\\": "src\/HandlingDomain\/Video\/src",
|
||||
"MyTube\\Handling\\VideoList\\": "src\/HandlingDomain\/VideoList\/src",
|
||||
"MyTube\\Infrastructure\\Database\\": "src\/Infrastructure\/Database\/src",
|
||||
"MyTube\\Infrastructure\\DependencyInjection\\": "src\/Infrastructure\/DependencyInjection\/src",
|
||||
"MyTube\\Infrastructure\\Encryption\\": "src\/Infrastructure\/Encryption\/src",
|
||||
"MyTube\\Infrastructure\\Exception\\": "src\/Infrastructure\/Exception\/src",
|
||||
"MyTube\\Infrastructure\\Logging\\": "src\/Infrastructure\/Logging\/src",
|
||||
"MyTube\\Infrastructure\\Rbac\\": "src\/Infrastructure\/Rbac\/src",
|
||||
"MyTube\\Infrastructure\\Request\\": "src\/Infrastructure\/Request\/src",
|
||||
"MyTube\\Infrastructure\\Response\\": "src\/Infrastructure\/Response\/src",
|
||||
"MyTube\\Infrastructure\\Session\\": "src\/Infrastructure\/Session\/src",
|
||||
"MyTube\\Infrastructure\\UuidGenerator\\": "src\/Infrastructure\/UuidGenerator\/src"
|
||||
}
|
||||
}
|
||||
}
|
||||
72
composer.json
Normal file
72
composer.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"require": {
|
||||
"laminas/laminas-servicemanager": "^3.21",
|
||||
"mezzio/mezzio-laminasrouter": "^3.8",
|
||||
"reinfi/zf-dependency-injection": "^5.4",
|
||||
"laminas/laminas-config-aggregator": "^1.13",
|
||||
"doctrine/doctrine-orm-module": "5.0.*",
|
||||
"doctrine/migrations": "^3.5",
|
||||
"doctrine/orm": "2.11.3",
|
||||
"doctrine/persistence": "2.2.*",
|
||||
"ramsey/uuid-doctrine": "^1.8",
|
||||
"roave/psr-container-doctrine": "^3.1",
|
||||
"mezzio/mezzio": "^3.17",
|
||||
"mezzio/mezzio-helpers": "^5.15",
|
||||
"symfony/cache": "5.4.8",
|
||||
"doctrine/dbal": "^3.6",
|
||||
"teewurst/psr4-advanced-wildcard-composer-plugin": "^3.0",
|
||||
"laminas/laminas-crypt": "^3.10",
|
||||
"monolog/monolog": "^3.4",
|
||||
"laminas/laminas-mail": "^2.23",
|
||||
"teewurst/pipeline": "^3.0",
|
||||
"guzzlehttp/guzzle": "^7.8",
|
||||
"micilini/video-stream": "^1.0",
|
||||
"nesbot/carbon": "^3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyTube\\API\\Console\\": "src/ApiDomain/Console/src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"teewurst/psr4-advanced-wildcard-composer-plugin": {
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyTube\\API\\%s\\%s\\": "src/ApiDomain/{*}/{*}/src/",
|
||||
"MyTube\\Data\\%s\\": "src/DataDomain/{*}/src/",
|
||||
"MyTube\\Handling\\%s\\": "src/HandlingDomain/{*}/src/",
|
||||
"MyTube\\Infrastructure\\%s\\": "src/Infrastructure/{*}/src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"MyTube\\API\\%s\\%s\\": "src/ApiDomain/{*}/{*}/src/",
|
||||
"MyTube\\Data\\%s\\": "src/DataDomain/{*}/src/",
|
||||
"MyTube\\Handling\\%s\\": "src/HandlingDomain/{*}/src/",
|
||||
"MyTube\\Infrastructure\\%s\\": "src/Infrastructure/{*}/src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dmg": "php bin/doctrine-migrations.php migrations:generate",
|
||||
"dmm": "php bin/doctrine-migrations.php migrations:migrate --no-interaction",
|
||||
"dmlg": "php bin/doctrine-migrations-log.php migrations:generate",
|
||||
"dmlm": "php bin/doctrine-migrations-log.php migrations:migrate --no-interaction",
|
||||
"console": "php bin/console.php",
|
||||
"createApi": "php bin/createApi.php",
|
||||
"createPipeline": "php bin/createPipeline.php",
|
||||
"da": [
|
||||
"composer dump-autoload",
|
||||
"composer dump-autoload --dev"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"teewurst/psr4-advanced-wildcard-composer-plugin": true
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dotenv": "^6.3"
|
||||
}
|
||||
}
|
||||
2
config/autoload/.gitignore
vendored
Normal file
2
config/autoload/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
local.php
|
||||
*.local.php
|
||||
29
config/autoload/api.global.php
Normal file
29
config/autoload/api.global.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'api' => [
|
||||
'keys' => [
|
||||
'myTube' => $_ENV['HOMEPAGE_API_KEY'],
|
||||
'notification' => $_ENV['NOTIFICATION_API_KEY'],
|
||||
],
|
||||
|
||||
'services' => [
|
||||
'myTube' => [
|
||||
'host' => 'myTube-backend-nginx',
|
||||
'apis' => [
|
||||
|
||||
]
|
||||
],
|
||||
'notification' => [
|
||||
'host' => 'notification-backend-nginx',
|
||||
'apis' => [
|
||||
'send-mail' => [
|
||||
'path' => '/api/mail/send',
|
||||
'method' => 'POST'
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
22
config/autoload/authorization.global.php
Normal file
22
config/autoload/authorization.global.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'myTube-rbac' => [
|
||||
'roles' => [
|
||||
'admin',
|
||||
'user',
|
||||
],
|
||||
'permissions' => [
|
||||
'user' => [
|
||||
'product.product-list',
|
||||
],
|
||||
'admin' => [
|
||||
'product.create-product',
|
||||
'product.delete-product',
|
||||
'product.product-list',
|
||||
'product.update-product',
|
||||
'user.create-user',
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
6
config/autoload/defines.php
Normal file
6
config/autoload/defines.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
|
||||
if (! defined('APP_ROOT')) {
|
||||
define('APP_ROOT', realpath(__DIR__ . '/../../'));
|
||||
}
|
||||
26
config/autoload/dependencies.global.php
Normal file
26
config/autoload/dependencies.global.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
// Provides application-wide services.
|
||||
// We recommend using fully-qualified class names whenever possible as
|
||||
// service names.
|
||||
'dependencies' => [
|
||||
// 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.
|
||||
'aliases' => [
|
||||
// Fully\Qualified\ClassOrInterfaceName::class => Fully\Qualified\ClassName::class,
|
||||
],
|
||||
// Use 'invokables' for constructor-less services, or services that do
|
||||
// not require arguments to the constructor. Map a service name to the
|
||||
// class name.
|
||||
'invokables' => [
|
||||
// Fully\Qualified\InterfaceName::class => Fully\Qualified\ClassName::class,
|
||||
],
|
||||
// Use 'factories' for services provided by callbacks/factory classes.
|
||||
'factories' => [
|
||||
// Fully\Qualified\ClassName::class => Fully\Qualified\FactoryName::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
14
config/autoload/doctrine.global.php
Normal file
14
config/autoload/doctrine.global.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\DBAL\Driver\PDO\MySQL\Driver;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
|
||||
use Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType;
|
||||
|
||||
return [
|
||||
'doctrine' => [
|
||||
'types' => [
|
||||
UuidBinaryOrderedTimeType::NAME => UuidBinaryOrderedTimeType::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
14
config/autoload/logger.global.php
Normal file
14
config/autoload/logger.global.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Monolog\Level;
|
||||
|
||||
return [
|
||||
'logger' => [
|
||||
'name' => 'myTube.backend',
|
||||
'path' => APP_ROOT . '/var/log/myTube.backend.log',
|
||||
'level' => Level::Debug,
|
||||
'pretty' => true,
|
||||
]
|
||||
];
|
||||
24
config/autoload/mezzio.global.php
Normal file
24
config/autoload/mezzio.global.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ConfigAggregator\ConfigAggregator;
|
||||
|
||||
return [
|
||||
// Toggle the configuration cache. Set this to boolean false, or remove the
|
||||
// directive, to disable configuration caching. Toggling development mode
|
||||
// will also disable it by default; clear the configuration cache using
|
||||
// `composer clear-config-cache`.
|
||||
ConfigAggregator::ENABLE_CACHE => false,
|
||||
|
||||
// Enable debugging; typically used to provide debugging information within myTubes.
|
||||
'debug' => false,
|
||||
'mezzio' => [
|
||||
// Provide myTubes for the error handling middleware to use when
|
||||
// generating responses.
|
||||
'error_handler' => [
|
||||
'myTube_404' => 'error::404',
|
||||
'myTube_error' => 'error::error',
|
||||
],
|
||||
],
|
||||
];
|
||||
97
config/config.php
Normal file
97
config/config.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ConfigAggregator\ArrayProvider;
|
||||
use Laminas\ConfigAggregator\ConfigAggregator;
|
||||
use Laminas\ConfigAggregator\PhpFileProvider;
|
||||
|
||||
// To enable or disable caching, set the `ConfigAggregator::ENABLE_CACHE` boolean in
|
||||
// `config/autoload/local.php`.
|
||||
$cacheConfig = [
|
||||
'config_cache_path' => 'data/cache/config-cache.php',
|
||||
];
|
||||
|
||||
$aggregator = new ConfigAggregator([
|
||||
// Include cache configuration
|
||||
new ArrayProvider($cacheConfig),
|
||||
\Mezzio\Helper\ConfigProvider::class,
|
||||
\Mezzio\ConfigProvider::class,
|
||||
\Mezzio\Router\ConfigProvider::class,
|
||||
\Mezzio\Router\LaminasRouter\ConfigProvider::class,
|
||||
|
||||
\Laminas\Diactoros\ConfigProvider::class,
|
||||
\Laminas\HttpHandlerRunner\ConfigProvider::class,
|
||||
\Laminas\Validator\ConfigProvider::class,
|
||||
\Laminas\Router\ConfigProvider::class,
|
||||
|
||||
\Reinfi\DependencyInjection\ConfigProvider::class,
|
||||
|
||||
\DoctrineORMModule\ConfigProvider::class,
|
||||
\DoctrineModule\ConfigProvider::class,
|
||||
|
||||
|
||||
// Swoole config to overwrite some services (if installed)
|
||||
class_exists(\Mezzio\Swoole\ConfigProvider::class)
|
||||
? \Mezzio\Swoole\ConfigProvider::class
|
||||
: function (): array {
|
||||
return [];
|
||||
},
|
||||
|
||||
|
||||
// Data
|
||||
\MyTube\Data\Business\ConfigProvider::class,
|
||||
\MyTube\Data\Log\ConfigProvider::class,
|
||||
|
||||
// Infrastructure
|
||||
\MyTube\Infrastructure\Database\ConfigProvider::class,
|
||||
\MyTube\Infrastructure\DependencyInjection\ConfigProvider::class,
|
||||
\MyTube\Infrastructure\Encryption\ConfigProvider::class,
|
||||
\MyTube\Infrastructure\Exception\ConfigProvider::class,
|
||||
\MyTube\Infrastructure\Logging\ConfigProvider::class,
|
||||
\MyTube\Infrastructure\Rbac\ConfigProvider::class,
|
||||
\MyTube\Infrastructure\Request\ConfigProvider::class,
|
||||
\MyTube\Infrastructure\Session\ConfigProvider::class,
|
||||
|
||||
// HandlingDomain
|
||||
\MyTube\Handling\User\ConfigProvider::class,
|
||||
\MyTube\Handling\UserSession\ConfigProvider::class,
|
||||
\MyTube\Handling\Registration\ConfigProvider::class,
|
||||
\MyTube\Handling\Video\ConfigProvider::class,
|
||||
\MyTube\Handling\VideoList\ConfigProvider::class,
|
||||
\MyTube\Handling\Tag\ConfigProvider::class,
|
||||
\MyTube\Handling\TagList\ConfigProvider::class,
|
||||
|
||||
// API
|
||||
/// Command
|
||||
\MyTube\API\Console\ConfigProvider::class,
|
||||
|
||||
/// External
|
||||
\MyTube\API\External\Health\ConfigProvider::class,
|
||||
\MyTube\API\External\User\ConfigProvider::class,
|
||||
\MyTube\API\External\Authentication\ConfigProvider::class,
|
||||
\MyTube\API\External\Video\ConfigProvider::class,
|
||||
\MyTube\API\External\VideoList\ConfigProvider::class,
|
||||
\MyTube\API\External\Tag\ConfigProvider::class,
|
||||
\MyTube\API\External\TagList\ConfigProvider::class,
|
||||
|
||||
/// Internal
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Load application config in a pre-defined order in such a way that local settings
|
||||
// overwrite global settings. (Loaded as first to last):
|
||||
// - `global.php`
|
||||
// - `*.global.php`
|
||||
// - `local.php`
|
||||
// - `*.local.php`
|
||||
new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'),
|
||||
|
||||
// Load development config if it exists
|
||||
new PhpFileProvider(realpath(__DIR__) . '/development.config.php'),
|
||||
], $cacheConfig['config_cache_path']);
|
||||
|
||||
return $aggregator->getMergedConfig();
|
||||
21
config/container.php
Normal file
21
config/container.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ServiceManager\ServiceManager;
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
|
||||
$dotenv = new Dotenv();
|
||||
|
||||
if (file_exists(__DIR__ . '/../.env')) {
|
||||
$dotenv->load(__DIR__ . '/../.env');
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
$config = require __DIR__ . '/config.php';
|
||||
|
||||
$dependencies = $config['dependencies'];
|
||||
$dependencies['services']['config'] = $config;
|
||||
|
||||
// Build container
|
||||
return new ServiceManager($dependencies);
|
||||
31
config/development.config.php
Normal file
31
config/development.config.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File required to allow enablement of development mode.
|
||||
*
|
||||
* For use with the laminas-development-mode tool.
|
||||
*
|
||||
* Usage:
|
||||
* $ composer development-disable
|
||||
* $ composer development-enable
|
||||
* $ composer development-status
|
||||
*
|
||||
* DO NOT MODIFY THIS FILE.
|
||||
*
|
||||
* Provide your own development-mode settings by editing the file
|
||||
* `config/autoload/development.local.php.dist`.
|
||||
*
|
||||
* Because this file is aggregated last, it simply ensures:
|
||||
*
|
||||
* - The `debug` flag is _enabled_.
|
||||
* - Configuration caching is _disabled_.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ConfigAggregator\ConfigAggregator;
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
ConfigAggregator::ENABLE_CACHE => false,
|
||||
];
|
||||
94
config/pipeline.php
Normal file
94
config/pipeline.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use MyTube\Infrastructure\Exception\Middleware\MyTubeExceptionHandlerMiddleware;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Stratigility\Middleware\ErrorHandler;
|
||||
use Mezzio\Application;
|
||||
use Mezzio\Handler\NotFoundHandler;
|
||||
use Mezzio\Helper\ServerUrlMiddleware;
|
||||
use Mezzio\Helper\UrlHelperMiddleware;
|
||||
use Mezzio\MiddlewareFactory;
|
||||
use Mezzio\Router\Middleware\DispatchMiddleware;
|
||||
use Mezzio\Router\Middleware\ImplicitHeadMiddleware;
|
||||
use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
|
||||
use Mezzio\Router\Middleware\MethodNotAllowedMiddleware;
|
||||
use Mezzio\Router\Middleware\RouteMiddleware;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// Pipe more middleware here that you want to execute on every request:
|
||||
// - bootstrapping
|
||||
// - pre-conditions
|
||||
// - 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.
|
||||
//
|
||||
// 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);
|
||||
|
||||
// Register the routing middleware in the middleware pipeline.
|
||||
// This middleware registers the Mezzio\Router\RouteResult request attribute.
|
||||
$app->pipe(RouteMiddleware::class);
|
||||
|
||||
// The following handle routing failures for common conditions:
|
||||
// - HEAD request but no routes answer that method
|
||||
// - OPTIONS request but no routes answer that method
|
||||
// - method not allowed
|
||||
// Order here matters; the MethodNotAllowedMiddleware should be placed
|
||||
// after the Implicit*Middleware.
|
||||
$app->pipe(ImplicitHeadMiddleware::class);
|
||||
$app->pipe(ImplicitOptionsMiddleware::class);
|
||||
$app->pipe(MethodNotAllowedMiddleware::class);
|
||||
|
||||
// Seed the UrlHelper with the routing results:
|
||||
$app->pipe(UrlHelperMiddleware::class);
|
||||
|
||||
|
||||
|
||||
|
||||
//// Pre MyTube Space
|
||||
$app->pipe(MyTubeExceptionHandlerMiddleware::class);
|
||||
$app->pipe(AnalyzeHeaderMiddleware::class);
|
||||
$app->pipe(AnalyzeBodyMiddleware::class);
|
||||
|
||||
//// MyTube Space
|
||||
$app->pipe(SessionMiddleware::class);
|
||||
|
||||
|
||||
|
||||
// Add more middleware here that needs to introspect the routing results; this
|
||||
// might include:
|
||||
//
|
||||
// - route-based authentication
|
||||
// - route-based validation
|
||||
// - etc.
|
||||
|
||||
// Register the dispatch middleware in the middleware pipeline
|
||||
$app->pipe(DispatchMiddleware::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);
|
||||
};
|
||||
52
config/routes.php
Normal file
52
config/routes.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Mezzio\Application;
|
||||
use Mezzio\MiddlewareFactory;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use MyTube\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
|
||||
/**
|
||||
* laminas-router route configuration
|
||||
*
|
||||
* @see https://docs.laminas.dev/laminas-router/
|
||||
*
|
||||
* Setup routes with a single request method:
|
||||
*
|
||||
* $app->get('/', App\Handler\HomePageHandler::class, 'home');
|
||||
* $app->post('/album', App\Handler\AlbumCreateHandler::class, 'album.create');
|
||||
* $app->put('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.put');
|
||||
* $app->patch('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.patch');
|
||||
* $app->delete('/album/:id', App\Handler\AlbumDeleteHandler::class, 'album.delete');
|
||||
*
|
||||
* Or with multiple request methods:
|
||||
*
|
||||
* $app->route('/contact', App\Handler\ContactHandler::class, ['GET', 'POST', ...], 'contact');
|
||||
*
|
||||
* Or handling all request methods:
|
||||
*
|
||||
* $app->route('/contact', App\Handler\ContactHandler::class)->setName('contact');
|
||||
*
|
||||
* or:
|
||||
*
|
||||
* $app->route(
|
||||
* '/contact',
|
||||
* App\Handler\ContactHandler::class,
|
||||
* Mezzio\Router\Route::HTTP_METHOD_ANY,
|
||||
* 'contact'
|
||||
* );
|
||||
*/
|
||||
|
||||
return static function (Application $app, MiddlewareFactory $factory, ContainerInterface $container): void {
|
||||
$config = $container->get('config');
|
||||
|
||||
foreach ($config['routes'] as $routeConfig) {
|
||||
$app->route(
|
||||
name: $routeConfig['name'],
|
||||
path: $routeConfig['path'],
|
||||
middleware: $routeConfig['middleware'],
|
||||
methods: $routeConfig['allowed_methods']
|
||||
);
|
||||
}
|
||||
};
|
||||
40
data/migrations/log/Version20230922150649.php
Normal file
40
data/migrations/log/Version20230922150649.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\Log;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922150649 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'log'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$query = 'CREATE TABLE log (
|
||||
id BINARY(16) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
context JSON DEFAULT NULL,
|
||||
level INT NOT NULL ,
|
||||
level_name VARCHAR(50) NOT NULL,
|
||||
extra JSON DEFAULT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
)';
|
||||
|
||||
$this->addSql($query);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE log');
|
||||
}
|
||||
}
|
||||
32
data/migrations/myTube/Version20230922085011.php
Normal file
32
data/migrations/myTube/Version20230922085011.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20230922085011 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'role'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE role (
|
||||
id binary(16) NOT NULL,
|
||||
identifier varchar(255) UNIQUE NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE role;");
|
||||
}
|
||||
}
|
||||
35
data/migrations/myTube/Version20230922092351.php
Normal file
35
data/migrations/myTube/Version20230922092351.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922092351 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'permission'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE permission (
|
||||
id binary(16) NOT NULL,
|
||||
identifier varchar(255) UNIQUE NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE permission;");
|
||||
}
|
||||
}
|
||||
36
data/migrations/myTube/Version20230922092754.php
Normal file
36
data/migrations/myTube/Version20230922092754.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922092754 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'role_permission'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE role_permission (
|
||||
id binary(16) NOT NULL DEFAULT (uuid_to_bin(uuid())),
|
||||
role_id binary(16) NOT NULL,
|
||||
permission_id binary(16) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE role_permission;");
|
||||
}
|
||||
}
|
||||
41
data/migrations/myTube/Version20230922101354.php
Normal file
41
data/migrations/myTube/Version20230922101354.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922101354 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'user'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE user (
|
||||
id binary(16) NOT NULL,
|
||||
role_id binary(16) NOT NULL,
|
||||
username varchar(255) UNIQUE NOT NULL,
|
||||
mail varchar(255) UNIQUE NOT NULL,
|
||||
password varchar(255) UNIQUE NOT NULL,
|
||||
last_login_at datetime DEFAULT NULL,
|
||||
updated_at datetime NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE user;");
|
||||
}
|
||||
}
|
||||
38
data/migrations/myTube/Version20230922101355.php
Normal file
38
data/migrations/myTube/Version20230922101355.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922101355 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'user_session'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE user_session (
|
||||
id binary(16) NOT NULL,
|
||||
user_id binary(16) DEFAULT NULL,
|
||||
csrf binary(16) DEFAULT NULL,
|
||||
updated_at datetime NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE role_permission;");
|
||||
}
|
||||
}
|
||||
37
data/migrations/myTube/Version20230924113403.php
Normal file
37
data/migrations/myTube/Version20230924113403.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230924113403 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'registration'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE registration (
|
||||
id binary(16) NOT NULL,
|
||||
mail varchar(255) NOT NULL,
|
||||
username varchar(255) NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE registration;");
|
||||
}
|
||||
}
|
||||
38
data/migrations/myTube/Version20240214194156.php
Normal file
38
data/migrations/myTube/Version20240214194156.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240214194156 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'video'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE video (
|
||||
id binary(16) NOT NULL,
|
||||
title varchar(255) NOT NULL,
|
||||
directory_path varchar(255) NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
updated_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE video;");
|
||||
}
|
||||
}
|
||||
37
data/migrations/myTube/Version20240223130626.php
Normal file
37
data/migrations/myTube/Version20240223130626.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240223130626 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'tag'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE tag (
|
||||
id binary(16) NOT NULL,
|
||||
description varchar(255) NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
updated_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE tag;");
|
||||
}
|
||||
}
|
||||
38
data/migrations/myTube/Version20240223130835.php
Normal file
38
data/migrations/myTube/Version20240223130835.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240223130835 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'tag_alias'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE tag_alias (
|
||||
id binary(16) NOT NULL,
|
||||
tag_id binary(16) NOT NULL,
|
||||
description varchar(255) NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
updated_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE tag_alias;");
|
||||
}
|
||||
}
|
||||
35
data/migrations/myTube/Version20240223142111.php
Normal file
35
data/migrations/myTube/Version20240223142111.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240223142111 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'video_tag'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE video_tag (
|
||||
video_id binary(16) NOT NULL,
|
||||
tag_id binary(16) NOT NULL,
|
||||
PRIMARY KEY (video_id, tag_id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE video_tag;");
|
||||
}
|
||||
}
|
||||
37
data/migrations/myTube/Version20240229205003.php
Normal file
37
data/migrations/myTube/Version20240229205003.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240229205003 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'video_event';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE video_event (
|
||||
id binary(16) NOT NULL,
|
||||
video_id binary(16) NOT NULL,
|
||||
datetime datetime NOT NULL,
|
||||
type varchar(255) NOT NULL,
|
||||
PRIMARY KEY (video_id, datetime, type)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE video_event;");
|
||||
}
|
||||
}
|
||||
35
data/migrations/myTube/Version20240323095155.php
Normal file
35
data/migrations/myTube/Version20240323095155.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\Migrations\MyTube;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240323095155 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'add duration to video';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "ALTER TABLE video
|
||||
ADD COLUMN duration int NULL after title
|
||||
;";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("ALTER TABLE video
|
||||
DROP COLUMN duration
|
||||
;");
|
||||
}
|
||||
}
|
||||
51
docker/docker-compose-mac.yml
Normal file
51
docker/docker-compose-mac.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: '3'
|
||||
networks:
|
||||
myTube:
|
||||
external: true
|
||||
|
||||
services:
|
||||
myTube-backend-mysql:
|
||||
image: myTube-backend-mysql
|
||||
networks:
|
||||
- myTube
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/mysql/dockerfile
|
||||
volumes:
|
||||
- /Users/flo/dev/backend/myTube/var/db:/var/lib/mysql:z
|
||||
environment:
|
||||
MYSQL_USER: ${DB_USER}
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||
ports:
|
||||
- 3306:3306
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
|
||||
myTube-backend-app:
|
||||
image: myTube-backend-app
|
||||
networks:
|
||||
- myTube
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/php/dockerfile
|
||||
volumes:
|
||||
- /Users/flo/dev/backend/myTube/:/var/www/html:z
|
||||
ports:
|
||||
- 9000:9000
|
||||
depends_on:
|
||||
myTube-backend-mysql:
|
||||
condition: service_healthy
|
||||
|
||||
myTube-backend-nginx:
|
||||
image: myTube-backend-nginx
|
||||
networks:
|
||||
- myTube
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/nginx/dockerfile
|
||||
ports:
|
||||
- 8080:80
|
||||
depends_on:
|
||||
- myTube-backend-app
|
||||
51
docker/docker-compose.yml
Normal file
51
docker/docker-compose.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: '3'
|
||||
networks:
|
||||
mytube:
|
||||
external: true
|
||||
|
||||
services:
|
||||
mytube-backend-mysql:
|
||||
image: mytube-backend-mysql
|
||||
networks:
|
||||
- mytube
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/mysql/dockerfile
|
||||
volumes:
|
||||
- ./../var/db:/var/lib/mysql:z
|
||||
environment:
|
||||
MYSQL_USER: ${DB_USER}
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||
ports:
|
||||
- 3306:3306
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
|
||||
mytube-backend-app:
|
||||
image: mytube-backend-app
|
||||
networks:
|
||||
- mytube
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/php/dockerfile
|
||||
volumes:
|
||||
- ./../:/var/www/html:z
|
||||
ports:
|
||||
- 9000:9000
|
||||
depends_on:
|
||||
mytube-backend-mysql:
|
||||
condition: service_healthy
|
||||
|
||||
mytube-backend-nginx:
|
||||
image: mytube-backend-nginx
|
||||
networks:
|
||||
- mytube
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/nginx/dockerfile
|
||||
ports:
|
||||
- 8080:80
|
||||
depends_on:
|
||||
- mytube-backend-app
|
||||
7
docker/mysql/dockerfile
Normal file
7
docker/mysql/dockerfile
Normal file
@ -0,0 +1,7 @@
|
||||
FROM mysql:latest
|
||||
|
||||
ENV MYSQL_RANDOM_ROOT_PASSWORD=1
|
||||
|
||||
COPY docker/mysql/scripts /docker-entrypoint-initdb.d/
|
||||
|
||||
CMD ["mysqld"]
|
||||
4
docker/mysql/scripts/initdb.sql
Normal file
4
docker/mysql/scripts/initdb.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE DATABASE IF NOT EXISTS `log`;
|
||||
CREATE DATABASE IF NOT EXISTS `myTube`;
|
||||
|
||||
GRANT ALL PRIVILEGES on *.* to 'myTube'@'%';
|
||||
17
docker/nginx/config/nginx.conf
Normal file
17
docker/nginx/config/nginx.conf
Normal file
@ -0,0 +1,17 @@
|
||||
upstream host-backend-app {
|
||||
server myTube-backend-app:9000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
client_max_body_size 10000M;
|
||||
|
||||
location / {
|
||||
fastcgi_pass host-backend-app;
|
||||
fastcgi_index index.php;
|
||||
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME /var/www/html/public/index.php;
|
||||
}
|
||||
}
|
||||
3
docker/nginx/config/upstream.conf
Normal file
3
docker/nginx/config/upstream.conf
Normal file
@ -0,0 +1,3 @@
|
||||
upstream backend-dev {
|
||||
server backend-app:9000;
|
||||
}
|
||||
5
docker/nginx/dockerfile
Normal file
5
docker/nginx/dockerfile
Normal file
@ -0,0 +1,5 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY docker/nginx/config/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
6
docker/php/config/uploads.ini
Normal file
6
docker/php/config/uploads.ini
Normal file
@ -0,0 +1,6 @@
|
||||
file_uploads = On
|
||||
max_file_uploads = 1000
|
||||
memory_limit = 10000M
|
||||
upload_max_filesize = 10000M
|
||||
post_max_size = 10000M
|
||||
max_execution_time = 1000
|
||||
18
docker/php/dockerfile
Normal file
18
docker/php/dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM php:8.1-fpm
|
||||
|
||||
RUN apt-get -y update
|
||||
RUN apt-get -y install git
|
||||
RUN apt-get install -y ffmpeg
|
||||
|
||||
RUN chown -R www-data:www-data /var/www/html
|
||||
WORKDIR /var/www/html
|
||||
|
||||
RUN docker-php-ext-install pdo pdo_mysql
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
|
||||
USER docker
|
||||
|
||||
COPY docker/php/config/uploads.ini /usr/local/etc/php/conf.d
|
||||
|
||||
CMD ["php-fpm"]
|
||||
26
phpunit.xml.dist
Normal file
26
phpunit.xml.dist
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
beStrictAboutCoversAnnotation="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
beStrictAboutTodoAnnotatedTests="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
convertDeprecationsToExceptions="true"
|
||||
executionOrder="depends,defects"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
verbose="true"
|
||||
colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="default">
|
||||
<directory suffix="Test.php">test</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
19
public/.htaccess
Normal file
19
public/.htaccess
Normal file
@ -0,0 +1,19 @@
|
||||
RewriteEngine On
|
||||
# The following rule allows authentication to work with fast-cgi
|
||||
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
# The following rule tells Apache that if the requested filename
|
||||
# exists, simply serve it.
|
||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -l [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [NC,L]
|
||||
|
||||
# The following rewrites all other queries to index.php. The
|
||||
# condition ensures that if you are using Apache aliases to do
|
||||
# mass virtual hosting, the base path will be prepended to
|
||||
# allow proper resolution of the index.php file; it will work
|
||||
# in non-aliased environments as well, providing a safe, one-size
|
||||
# fits all solution.
|
||||
RewriteCond $0::%{REQUEST_URI} ^([^:]*+(?::[^:]*+)*?)::(/.+?)\1$
|
||||
RewriteRule .+ - [E=BASE:%2]
|
||||
RewriteRule .* %{ENV:BASE}index.php [NC,L]
|
||||
48
public/index.php
Normal file
48
public/index.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Mezzio\Application;
|
||||
use Mezzio\MiddlewareFactory;
|
||||
|
||||
if (PHP_SAPI === 'cli-server' && $_SERVER['SCRIPT_FILENAME'] !== __FILE__) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require './../vendor/autoload.php';
|
||||
|
||||
require './../config/autoload/defines.php';
|
||||
|
||||
function throwableToMessageArray(Throwable $e): array {
|
||||
$messageArray = [];
|
||||
while($e !== null) {
|
||||
$messageArray[] = $e->getMessage();
|
||||
$e = $e->getPrevious();
|
||||
}
|
||||
return $messageArray;
|
||||
}
|
||||
|
||||
function throwableToMessageArrayString(Throwable $e): string {
|
||||
return implode( PHP_EOL, throwableToMessageArray($e) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Self-called anonymous function that creates its own scope and keeps the global namespace clean.
|
||||
*/
|
||||
(function () {
|
||||
|
||||
/** @var \Psr\Container\ContainerInterface $container */
|
||||
$container = require './../config/container.php';
|
||||
|
||||
/** @var Application $app */
|
||||
$app = $container->get(Application::class);
|
||||
$factory = $container->get(MiddlewareFactory::class);
|
||||
|
||||
// Execute programmatic/declarative middleware pipeline and routing
|
||||
// configuration statements
|
||||
(require './../config/pipeline.php')($app, $factory, $container);
|
||||
(require './../config/routes.php')($app, $factory, $container);
|
||||
|
||||
$app->run();
|
||||
|
||||
})();
|
||||
15
src/ApiDomain/Console/config/console.php
Normal file
15
src/ApiDomain/Console/config/console.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\Console\Command\AnalyzeVideoTitlesCommand;
|
||||
use MyTube\API\Console\Command\InitializeDataCommand;
|
||||
use MyTube\API\Console\Command\RbacUpdateCommand;
|
||||
use MyTube\API\Console\Command\ReadUntaggedVideosCommand;
|
||||
|
||||
return [
|
||||
'commands' => [
|
||||
InitializeDataCommand::class,
|
||||
RbacUpdateCommand::class,
|
||||
AnalyzeVideoTitlesCommand::class,
|
||||
ReadUntaggedVideosCommand::class,
|
||||
]
|
||||
];
|
||||
16
src/ApiDomain/Console/config/service_manager.php
Normal file
16
src/ApiDomain/Console/config/service_manager.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\Console\Command\AnalyzeVideoTitlesCommand;
|
||||
use MyTube\API\Console\Command\InitializeDataCommand;
|
||||
use MyTube\API\Console\Command\RbacUpdateCommand;
|
||||
use MyTube\API\Console\Command\ReadUntaggedVideosCommand;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
InitializeDataCommand::class => AutoWiringFactory::class,
|
||||
RbacUpdateCommand::class => AutoWiringFactory::class,
|
||||
AnalyzeVideoTitlesCommand::class => AutoWiringFactory::class,
|
||||
ReadUntaggedVideosCommand::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace MyTube\API\Console\Command;
|
||||
|
||||
use MyTube\Data\Business\Entity\Tag;
|
||||
use MyTube\Data\Business\Entity\Video;
|
||||
use MyTube\Data\Business\Manager\MyTubeEntityManager;
|
||||
use MyTube\Data\Business\Repository\VideoRepository;
|
||||
use MyTube\Handling\Video\Analyzer\VideoDurationAnalyzer;
|
||||
use MyTube\Handling\Video\Analyzer\VideoTitleAnalyzer;
|
||||
use MyTube\Infrastructure\Logging\Logger\Logger;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'analyze:video', description: 'Analyzes video titles and add tags')]
|
||||
class AnalyzeVideoTitlesCommand extends Command
|
||||
{
|
||||
private readonly VideoRepository $videoRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly MyTubeEntityManager $entityManager,
|
||||
private readonly VideoTitleAnalyzer $titleAnalyzer,
|
||||
private readonly VideoDurationAnalyzer $durationAnalyzer,
|
||||
private readonly Logger $logger,
|
||||
) {
|
||||
parent::__construct($this->getName());
|
||||
|
||||
$this->videoRepository = $this->entityManager->getRepository(Video::class);
|
||||
}
|
||||
|
||||
protected function execute(
|
||||
InputInterface $input,
|
||||
OutputInterface $output
|
||||
): int {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
$videos = $this->videoRepository->findAll();
|
||||
|
||||
/** @var Video $video */
|
||||
foreach ($videos as $video) {
|
||||
$io->info($video->getTitle());
|
||||
|
||||
$this->titleAnalyzer->analyze($video);
|
||||
$this->durationAnalyzer->analyze($video);
|
||||
|
||||
$this->entityManager->persist($video);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$io->success('OK!');
|
||||
} catch (\Throwable $e) {
|
||||
$io->error($e->getMessage());
|
||||
$io->error($e->getTraceAsString());
|
||||
$this->logger->error($e->getMessage(), ['exception' => $e]);
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
80
src/ApiDomain/Console/src/Command/InitializeDataCommand.php
Normal file
80
src/ApiDomain/Console/src/Command/InitializeDataCommand.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace MyTube\API\Console\Command;
|
||||
|
||||
use MyTube\Data\Business\Entity\Role;
|
||||
use MyTube\Data\Business\Entity\User;
|
||||
use MyTube\Data\Business\Repository\RoleRepository;
|
||||
use MyTube\Data\Business\Repository\UserRepository;
|
||||
use MyTube\Data\Business\Manager\MyTubeEntityManager;
|
||||
use MyTube\Infrastructure\Encryption\Client\EncryptionClient;
|
||||
use MyTube\Infrastructure\Logging\Logger\Logger;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'init:data', description: 'Initializes the applications data')]
|
||||
class InitializeDataCommand extends Command
|
||||
{
|
||||
private readonly RoleRepository $roleRepository;
|
||||
private readonly UserRepository $userRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly EncryptionClient $encryptionClient,
|
||||
private readonly MyTubeEntityManager $entityManager,
|
||||
private readonly Logger $logger,
|
||||
) {
|
||||
parent::__construct($this->getName());
|
||||
|
||||
$this->roleRepository = $this->entityManager->getRepository(Role::class);
|
||||
$this->userRepository = $this->entityManager->getRepository(User::class);
|
||||
}
|
||||
|
||||
protected function execute(
|
||||
InputInterface $input,
|
||||
OutputInterface $output
|
||||
): int {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
$admin = $this->roleRepository->findOneBy([
|
||||
'identifier' => 'admin'
|
||||
]) ?? null;
|
||||
if ($admin === null) {
|
||||
throw new \Exception('Admin role does not exist!');
|
||||
}
|
||||
|
||||
$adminUser = $this->userRepository->findOneBy([
|
||||
'roleId' => $admin->getId()
|
||||
]) ?? null;
|
||||
|
||||
if ($adminUser === null) {
|
||||
$io->info('Create admin');
|
||||
|
||||
$adminUser = new User();
|
||||
$adminUser->setRole($admin);
|
||||
$adminUser->setUsername($_ENV['INIT_USER_NAME']);
|
||||
$adminUser->setMail($_ENV['INIT_USER_MAIL']);
|
||||
$adminUser->setPassword(
|
||||
$this->encryptionClient->encrypt(
|
||||
$_ENV['INIT_USER_PASSWORD']
|
||||
)
|
||||
);
|
||||
|
||||
$this->entityManager->persist($adminUser);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$io->success('OK!');
|
||||
} catch (\Throwable $e) {
|
||||
$io->error($e->getMessage());
|
||||
$io->error($e->getTraceAsString());
|
||||
$this->logger->error($e->getMessage(), ['exception' => $e]);
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
98
src/ApiDomain/Console/src/Command/RbacUpdateCommand.php
Normal file
98
src/ApiDomain/Console/src/Command/RbacUpdateCommand.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace MyTube\API\Console\Command;
|
||||
|
||||
use MyTube\Data\Business\Entity\Permission;
|
||||
use MyTube\Data\Business\Entity\Role;
|
||||
use MyTube\Data\Business\Repository\PermissionRepository;
|
||||
use MyTube\Data\Business\Repository\RoleRepository;
|
||||
use MyTube\Data\Business\Manager\MyTubeEntityManager;
|
||||
use MyTube\Infrastructure\Logging\Logger\Logger;
|
||||
use Reinfi\DependencyInjection\Service\ConfigService;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'rbac:update', description: 'Updates RBAC entries in DB')]
|
||||
class RbacUpdateCommand extends Command
|
||||
{
|
||||
private array $rbacConfig;
|
||||
private RoleRepository $roleRepository;
|
||||
private PermissionRepository $permissionRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly ConfigService $configService,
|
||||
private readonly MyTubeEntityManager $entityManager,
|
||||
private readonly Logger $logger,
|
||||
) {
|
||||
parent::__construct($this->getName());
|
||||
|
||||
$this->roleRepository = $this->entityManager->getRepository(Role::class);
|
||||
$this->permissionRepository = $this->entityManager->getRepository(Permission::class);
|
||||
|
||||
$this->rbacConfig = $this->configService->resolve('myTube-rbac')->toArray();
|
||||
}
|
||||
|
||||
protected function execute(
|
||||
InputInterface $input,
|
||||
OutputInterface $output
|
||||
): int {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
|
||||
$roles = [];
|
||||
|
||||
foreach ($this->rbacConfig['roles'] as $roleIdentifier) {
|
||||
$role = $this->roleRepository->findOneBy([
|
||||
'identifier' => $roleIdentifier
|
||||
]) ?? null;
|
||||
|
||||
if ($role === null) {
|
||||
$role = new Role();
|
||||
$role->setIdentifier($roleIdentifier);
|
||||
|
||||
$this->entityManager->persist($role);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$roles[$roleIdentifier] = $role;
|
||||
}
|
||||
|
||||
foreach ($roles as $role) {
|
||||
$roleIdentifier = $role->getIdentifier();
|
||||
|
||||
foreach ($this->rbacConfig['permissions'][$roleIdentifier] as $permissionIdentifier) {
|
||||
$io->info($role->getIdentifier() . '.' . $permissionIdentifier);
|
||||
|
||||
$permission = $this->permissionRepository->findOneBy([
|
||||
'identifier' => $permissionIdentifier
|
||||
]) ?? null;
|
||||
|
||||
if ($permission === null) {
|
||||
$permission = new Permission();
|
||||
$permission->setIdentifier($permissionIdentifier);
|
||||
|
||||
$this->entityManager->persist($permission);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$role->addPermission($permission);
|
||||
$this->entityManager->persist($role);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
}
|
||||
|
||||
$io->success('OK!');
|
||||
} catch (\Throwable $e) {
|
||||
$io->error($e->getMessage());
|
||||
$io->error($e->getTraceAsString());
|
||||
$this->logger->error($e->getMessage(), ['exception' => $e]);
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace MyTube\API\Console\Command;
|
||||
|
||||
use MyTube\Data\Business\Entity\Tag;
|
||||
use MyTube\Data\Business\Entity\Video;
|
||||
use MyTube\Data\Business\Manager\MyTubeEntityManager;
|
||||
use MyTube\Data\Business\Repository\VideoRepository;
|
||||
use MyTube\Handling\Video\Analyzer\VideoTitleAnalyzer;
|
||||
use MyTube\Infrastructure\Logging\Logger\Logger;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'analyze:untagged', description: 'Returns the names of all untagged videos')]
|
||||
class ReadUntaggedVideosCommand extends Command
|
||||
{
|
||||
private readonly VideoRepository $videoRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly MyTubeEntityManager $entityManager,
|
||||
private readonly Logger $logger,
|
||||
) {
|
||||
parent::__construct($this->getName());
|
||||
|
||||
$this->videoRepository = $this->entityManager->getRepository(Video::class);
|
||||
}
|
||||
|
||||
protected function execute(
|
||||
InputInterface $input,
|
||||
OutputInterface $output
|
||||
): int {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
$qb = $this->videoRepository
|
||||
->createQueryBuilder('v')
|
||||
->leftJoin('v.tags', 't')
|
||||
->groupBy('v.id')
|
||||
->having('COUNT(t.id) = 0')
|
||||
->orderBy('v.title');
|
||||
|
||||
$videos = $qb->getQuery()->execute();
|
||||
|
||||
/** @var Video $video */
|
||||
foreach ($videos as $video) {
|
||||
echo $video->getTitle() . PHP_EOL;
|
||||
}
|
||||
|
||||
$io->info('total: ' . count($videos));
|
||||
|
||||
$io->success('OK!');
|
||||
} catch (\Throwable $e) {
|
||||
$io->error($e->getMessage());
|
||||
$io->error($e->getTraceAsString());
|
||||
$this->logger->error($e->getMessage(), ['exception' => $e]);
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
16
src/ApiDomain/Console/src/ConfigProvider.php
Normal file
16
src/ApiDomain/Console/src/ConfigProvider.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\Console;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'console' => require __DIR__ . '/./../config/console.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
43
src/ApiDomain/External/Authentication/config/routes.php
vendored
Normal file
43
src/ApiDomain/External/Authentication/config/routes.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\Authentication\Handler\ConfirmRegistrationHandler;
|
||||
use MyTube\API\External\Authentication\Handler\LoginUserHandler;
|
||||
use MyTube\API\External\Authentication\Handler\LogoutUserHandler;
|
||||
use MyTube\API\External\Authentication\Handler\RegisterUserHandler;
|
||||
use MyTube\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'auth.login-user',
|
||||
'path' => '/api/auth/login-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoginUserHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'auth.logout-user',
|
||||
'path' => '/api/auth/logout-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
LogoutUserHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'auth.confirm-registration',
|
||||
'path' => '/api/auth/confirm-registration',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
ConfirmRegistrationHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'auth.register-user',
|
||||
'path' => '/api/auth/register-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
RegisterUserHandler::class
|
||||
],
|
||||
],
|
||||
];
|
||||
17
src/ApiDomain/External/Authentication/config/service_manager.php
vendored
Normal file
17
src/ApiDomain/External/Authentication/config/service_manager.php
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\Authentication\Handler\ConfirmRegistrationHandler;
|
||||
use MyTube\API\External\Authentication\Handler\LoginUserHandler;
|
||||
use MyTube\API\External\Authentication\Handler\LogoutUserHandler;
|
||||
use MyTube\API\External\Authentication\Handler\RegisterUserHandler;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Handler
|
||||
LoginUserHandler::class => AutoWiringFactory::class,
|
||||
LogoutUserHandler::class => AutoWiringFactory::class,
|
||||
ConfirmRegistrationHandler::class => AutoWiringFactory::class,
|
||||
RegisterUserHandler::class => AutoWiringFactory::class
|
||||
],
|
||||
];
|
||||
16
src/ApiDomain/External/Authentication/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/Authentication/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Authentication;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
42
src/ApiDomain/External/Authentication/src/Handler/ConfirmRegistrationHandler.php
vendored
Normal file
42
src/ApiDomain/External/Authentication/src/Handler/ConfirmRegistrationHandler.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Authentication\Handler;
|
||||
|
||||
use MyTube\API\External\User\Formatter\UserFormatter;
|
||||
use MyTube\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandBuilder;
|
||||
use MyTube\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandHandler;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class ConfirmRegistrationHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ConfirmRegistrationCommandHandler $handler,
|
||||
private readonly ConfirmRegistrationCommandBuilder $builder,
|
||||
private readonly UserFormatter $userFormatter
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$query = $this->builder->build(
|
||||
Uuid::fromString($data['id']),
|
||||
$data['password'],
|
||||
$data['passwordConfirmation'],
|
||||
);
|
||||
|
||||
$result = $this->handler->execute($query);
|
||||
return new JsonResponse(
|
||||
$this->userFormatter->format($result)
|
||||
);
|
||||
}
|
||||
}
|
||||
40
src/ApiDomain/External/Authentication/src/Handler/LoginUserHandler.php
vendored
Normal file
40
src/ApiDomain/External/Authentication/src/Handler/LoginUserHandler.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Authentication\Handler;
|
||||
|
||||
use MyTube\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandBuilder;
|
||||
use MyTube\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandHandler;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class LoginUserHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LoginUserCommandHandler $handler,
|
||||
private readonly LoginUserCommandBuilder $builder
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$session,
|
||||
$data['identifier'],
|
||||
$data['password'],
|
||||
);
|
||||
|
||||
$result = $this->handler->execute($query);
|
||||
return new JsonResponse([
|
||||
'sessionId' => $result->getId()->toString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
35
src/ApiDomain/External/Authentication/src/Handler/LogoutUserHandler.php
vendored
Normal file
35
src/ApiDomain/External/Authentication/src/Handler/LogoutUserHandler.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Authentication\Handler;
|
||||
|
||||
use MyTube\Handling\UserSession\Handler\Command\LogoutUser\LogoutUserCommandBuilder;
|
||||
use MyTube\Handling\UserSession\Handler\Command\LogoutUser\LogoutUserCommandHandler;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class LogoutUserHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LogoutUserCommandHandler $handler,
|
||||
private readonly LogoutUserCommandBuilder $builder
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$session
|
||||
);
|
||||
$this->handler->execute($query);
|
||||
|
||||
return new JsonResponse('OK');
|
||||
}
|
||||
}
|
||||
43
src/ApiDomain/External/Authentication/src/Handler/RegisterUserHandler.php
vendored
Normal file
43
src/ApiDomain/External/Authentication/src/Handler/RegisterUserHandler.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Authentication\Handler;
|
||||
|
||||
use MyTube\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandBuilder;
|
||||
use MyTube\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandHandler;
|
||||
use MyTube\Infrastructure\Exception\Middleware\MyTubeExceptionHandlerMiddleware;
|
||||
use MyTube\Infrastructure\Logging\Logger\Logger;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
use MyTube\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class RegisterUserHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly RegisterUserCommandHandler $handler,
|
||||
private readonly RegisterUserCommandBuilder $builder,
|
||||
private readonly Logger $logger
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$host = $request->getAttribute(AnalyzeHeaderMiddleware::HOST_ATTRIBUTE);
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$data['username'],
|
||||
$data['mail'],
|
||||
$host
|
||||
);
|
||||
|
||||
$this->handler->execute($query);
|
||||
return new SuccessResponse();
|
||||
}
|
||||
}
|
||||
16
src/ApiDomain/External/Health/config/routes.php
vendored
Normal file
16
src/ApiDomain/External/Health/config/routes.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\Health\Handler\HealthHandler;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'health',
|
||||
'path' => '/api/health',
|
||||
'allowed_methods' => ['GET'],
|
||||
'middleware' => [
|
||||
HealthHandler::class
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
?>
|
||||
12
src/ApiDomain/External/Health/config/service_manager.php
vendored
Normal file
12
src/ApiDomain/External/Health/config/service_manager.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\Health\Handler\HealthHandler;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
HealthHandler::class => AutoWiringFactory::class
|
||||
],
|
||||
]
|
||||
|
||||
?>
|
||||
16
src/ApiDomain/External/Health/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/Health/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Health;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
23
src/ApiDomain/External/Health/src/Handler/HealthHandler.php
vendored
Normal file
23
src/ApiDomain/External/Health/src/Handler/HealthHandler.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Health\Handler;
|
||||
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class HealthHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
return new JsonResponse("I'm fine. :)");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
41
src/ApiDomain/External/Tag/config/routes.php
vendored
Normal file
41
src/ApiDomain/External/Tag/config/routes.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\Tag\Handler\AddAliasHandler;
|
||||
use MyTube\API\External\Tag\Handler\CreateHandler;
|
||||
use MyTube\API\External\Tag\Handler\ReadDetailsHandler;
|
||||
use MyTube\API\External\Tag\Handler\ReadVideoListHandler;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'tag.create',
|
||||
'path' => '/api/tag/create[/]',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
CreateHandler::class,
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'tag.add-alias',
|
||||
'path' => '/api/tag/add-alias[/]',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
AddAliasHandler::class,
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'tag.read-details',
|
||||
'path' => '/api/tag/read-details[/]',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
ReadDetailsHandler::class,
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'tag.read-video-list',
|
||||
'path' => '/api/tag/read-video-list[/]',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
ReadVideoListHandler::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
27
src/ApiDomain/External/Tag/config/service_manager.php
vendored
Normal file
27
src/ApiDomain/External/Tag/config/service_manager.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\Tag\Handler\AddAliasHandler;
|
||||
use MyTube\API\External\Tag\Handler\CreateHandler;
|
||||
use MyTube\API\External\Tag\Handler\ReadDetailsHandler;
|
||||
use MyTube\API\External\Tag\Handler\ReadVideoListHandler;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\AddAliasResponseFormatter;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\CreateResponseFormatter;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\ReadDetailsResponseFormatter;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\ReadVideoListResponseFormatter;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Handler
|
||||
AddAliasHandler::class => AutoWiringFactory::class,
|
||||
CreateHandler::class => AutoWiringFactory::class,
|
||||
ReadDetailsHandler::class => AutoWiringFactory::class,
|
||||
ReadVideoListHandler::class => AutoWiringFactory::class,
|
||||
|
||||
// Response Formatter
|
||||
AddAliasResponseFormatter::class => AutoWiringFactory::class,
|
||||
CreateResponseFormatter::class => AutoWiringFactory::class,
|
||||
ReadDetailsResponseFormatter::class => AutoWiringFactory::class,
|
||||
ReadVideoListResponseFormatter::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
16
src/ApiDomain/External/Tag/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/Tag/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
44
src/ApiDomain/External/Tag/src/Handler/AddAliasHandler.php
vendored
Normal file
44
src/ApiDomain/External/Tag/src/Handler/AddAliasHandler.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\Handler;
|
||||
|
||||
use MyTube\Handling\Tag\Exception\TagAliasAlreadyExistsException;
|
||||
use MyTube\Handling\Tag\Exception\TagNotFoundByIdException;
|
||||
use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandHandler;
|
||||
use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandBuilder;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\AddAliasResponseFormatter;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class AddAliasHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AddAliasCommandHandler $addAliasCommandHandler,
|
||||
private readonly AddAliasCommandBuilder $addAliasCommandBuilder,
|
||||
private readonly AddAliasResponseFormatter $responseFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TagNotFoundByIdException
|
||||
* @throws TagAliasAlreadyExistsException
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$addAliasCommand = $this->addAliasCommandBuilder->build(
|
||||
Uuid::fromString($data['tagId']),
|
||||
$data['description']
|
||||
);
|
||||
$result = $this->addAliasCommandHandler->execute($addAliasCommand);
|
||||
|
||||
return new SuccessResponse($this->responseFormatter->format($result));
|
||||
}
|
||||
}
|
||||
40
src/ApiDomain/External/Tag/src/Handler/CreateHandler.php
vendored
Normal file
40
src/ApiDomain/External/Tag/src/Handler/CreateHandler.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\Handler;
|
||||
|
||||
use MyTube\Handling\Tag\Exception\TagAlreadyExistsException;
|
||||
use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandHandler;
|
||||
use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandBuilder;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\CreateResponseFormatter;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
|
||||
class CreateHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CreateCommandHandler $createCommandHandler,
|
||||
private readonly CreateCommandBuilder $createCommandBuilder,
|
||||
private readonly CreateResponseFormatter $responseFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TagAlreadyExistsException
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$createCommand = $this->createCommandBuilder->build(
|
||||
$data['description']
|
||||
);
|
||||
$result = $this->createCommandHandler->execute($createCommand);
|
||||
|
||||
return new SuccessResponse($this->responseFormatter->format($result));
|
||||
}
|
||||
}
|
||||
41
src/ApiDomain/External/Tag/src/Handler/ReadDetailsHandler.php
vendored
Normal file
41
src/ApiDomain/External/Tag/src/Handler/ReadDetailsHandler.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\Handler;
|
||||
|
||||
use MyTube\Handling\Tag\Exception\TagNotFoundByIdException;
|
||||
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryHandler;
|
||||
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryBuilder;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\ReadDetailsResponseFormatter;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class ReadDetailsHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ReadDetailsQueryHandler $readDetailsQueryHandler,
|
||||
private readonly ReadDetailsQueryBuilder $readDetailsQueryBuilder,
|
||||
private readonly ReadDetailsResponseFormatter $responseFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TagNotFoundByIdException
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$readDetailsQuery = $this->readDetailsQueryBuilder->build(
|
||||
Uuid::fromString($data['tagId']),
|
||||
);
|
||||
$result = $this->readDetailsQueryHandler->execute($readDetailsQuery);
|
||||
|
||||
return new SuccessResponse($this->responseFormatter->format($result));
|
||||
}
|
||||
}
|
||||
40
src/ApiDomain/External/Tag/src/Handler/ReadVideoListHandler.php
vendored
Normal file
40
src/ApiDomain/External/Tag/src/Handler/ReadVideoListHandler.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\Handler;
|
||||
|
||||
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryHandler;
|
||||
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryBuilder;
|
||||
use MyTube\API\External\Tag\ResponseFormatter\ReadVideoListResponseFormatter;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class ReadVideoListHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ReadVideoListQueryHandler $readVideoListQueryHandler,
|
||||
private readonly ReadVideoListQueryBuilder $readVideoListQueryBuilder,
|
||||
private readonly ReadVideoListResponseFormatter $responseFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$readVideoListQuery = $this->readVideoListQueryBuilder->build(
|
||||
Uuid::fromString($data['tagId']),
|
||||
$data['query'] ?? null,
|
||||
$data['page'],
|
||||
$data['perPage'],
|
||||
);
|
||||
$result = $this->readVideoListQueryHandler->execute($readVideoListQuery);
|
||||
|
||||
return new SuccessResponse($this->responseFormatter->format($result));
|
||||
}
|
||||
}
|
||||
25
src/ApiDomain/External/Tag/src/ResponseFormatter/AddAliasResponseFormatter.php
vendored
Normal file
25
src/ApiDomain/External/Tag/src/ResponseFormatter/AddAliasResponseFormatter.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\ResponseFormatter;
|
||||
|
||||
use MyTube\Handling\Tag\Handler\Command\AddAlias\AddAliasCommandResult;
|
||||
|
||||
class AddAliasResponseFormatter
|
||||
{
|
||||
public function format(AddAliasCommandResult $addAliasCommandResult): array
|
||||
{
|
||||
$alias = $addAliasCommandResult->getAlias();
|
||||
$tag = $alias->getTag();
|
||||
|
||||
return [
|
||||
'id' => $alias->getId()->toString(),
|
||||
'description' => $alias->getDescription(),
|
||||
'tag' => [
|
||||
'id' => $tag->getId()->toString(),
|
||||
'description' => $tag->getDescription()
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
19
src/ApiDomain/External/Tag/src/ResponseFormatter/CreateResponseFormatter.php
vendored
Normal file
19
src/ApiDomain/External/Tag/src/ResponseFormatter/CreateResponseFormatter.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\ResponseFormatter;
|
||||
|
||||
use MyTube\Handling\Tag\Handler\Command\Create\CreateCommandResult;
|
||||
|
||||
class CreateResponseFormatter
|
||||
{
|
||||
public function format(CreateCommandResult $createCommandResult): array
|
||||
{
|
||||
$tag = $createCommandResult->getTag();
|
||||
return [
|
||||
'id' => $tag->getId()->toString(),
|
||||
'description' => $tag->getDescription(),
|
||||
];
|
||||
}
|
||||
}
|
||||
32
src/ApiDomain/External/Tag/src/ResponseFormatter/ReadDetailsResponseFormatter.php
vendored
Normal file
32
src/ApiDomain/External/Tag/src/ResponseFormatter/ReadDetailsResponseFormatter.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\ResponseFormatter;
|
||||
|
||||
use MyTube\Data\Business\Entity\TagAlias;
|
||||
use MyTube\Handling\Tag\Handler\Query\ReadDetails\ReadDetailsQueryResult;
|
||||
|
||||
class ReadDetailsResponseFormatter
|
||||
{
|
||||
public function format(ReadDetailsQueryResult $readDetailsQueryResult): array
|
||||
{
|
||||
$tag = $readDetailsQueryResult->getTag();
|
||||
|
||||
$aliases = [];
|
||||
|
||||
/** @var TagAlias $alias */
|
||||
foreach ($tag->getAliases() as $alias) {
|
||||
$aliases[] = [
|
||||
'id' => $alias->getId(),
|
||||
'description' => $alias->getDescription()
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $tag->getId()->toString(),
|
||||
'description' => $tag->getDescription(),
|
||||
'aliases' => $aliases
|
||||
];
|
||||
}
|
||||
}
|
||||
45
src/ApiDomain/External/Tag/src/ResponseFormatter/ReadVideoListResponseFormatter.php
vendored
Normal file
45
src/ApiDomain/External/Tag/src/ResponseFormatter/ReadVideoListResponseFormatter.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\Tag\ResponseFormatter;
|
||||
|
||||
use MyTube\Data\Business\Entity\Tag;
|
||||
use MyTube\Data\Business\Entity\Video;
|
||||
use MyTube\Handling\Tag\Handler\Query\ReadVideoList\ReadVideoListQueryResult;
|
||||
|
||||
class ReadVideoListResponseFormatter
|
||||
{
|
||||
public function format(ReadVideoListQueryResult $readVideoListQueryResult): array
|
||||
{
|
||||
$paginator = $readVideoListQueryResult->getPaginator();
|
||||
$videos = $paginator->getIterator();
|
||||
|
||||
$items = [];
|
||||
|
||||
/** @var Video $video */
|
||||
foreach ($videos as $video) {
|
||||
$tags = [];
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach ($video->getTags() as $tag) {
|
||||
$tags[] = [
|
||||
'id' => $tag->getId(),
|
||||
'description' => $tag->getDescription()
|
||||
];
|
||||
}
|
||||
|
||||
$items[] = [
|
||||
'title' => $video->getTitle(),
|
||||
'id' => $video->getId(),
|
||||
'duration' => $video->getDuration() === null ? 'n. def' : gmdate("H:i:s", $video->getDuration()),
|
||||
'tags' => $tags
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'total' => $paginator->count(),
|
||||
'items' => $items,
|
||||
];
|
||||
}
|
||||
}
|
||||
16
src/ApiDomain/External/TagList/config/routes.php
vendored
Normal file
16
src/ApiDomain/External/TagList/config/routes.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use MyTube\API\External\TagList\Handler\ReadListHandler;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'tag-list.read-list',
|
||||
'path' => '/api/tag-list/read-list[/]',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
ReadListHandler::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
17
src/ApiDomain/External/TagList/config/service_manager.php
vendored
Normal file
17
src/ApiDomain/External/TagList/config/service_manager.php
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use MyTube\API\External\TagList\Handler\ReadListHandler;
|
||||
use MyTube\API\External\TagList\ResponseFormatter\ReadListResponseFormatter;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Handler
|
||||
ReadListHandler::class => AutoWiringFactory::class,
|
||||
|
||||
// Response Formatter
|
||||
ReadListResponseFormatter::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
16
src/ApiDomain/External/TagList/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/TagList/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\TagList;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
36
src/ApiDomain/External/TagList/src/Handler/ReadListHandler.php
vendored
Normal file
36
src/ApiDomain/External/TagList/src/Handler/ReadListHandler.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\TagList\Handler;
|
||||
|
||||
use MyTube\Handling\TagList\Handler\Query\ReadList\ReadListQueryHandler;
|
||||
use MyTube\Handling\TagList\Handler\Query\ReadList\ReadListQueryBuilder;
|
||||
use MyTube\API\External\TagList\ResponseFormatter\ReadListResponseFormatter;
|
||||
use MyTube\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ReadListHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ReadListQueryHandler $readListQueryHandler,
|
||||
private readonly ReadListQueryBuilder $readListQueryBuilder,
|
||||
private readonly ReadListResponseFormatter $responseFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$readListQuery = $this->readListQueryBuilder->build(
|
||||
$data['query'] ?? null,
|
||||
);
|
||||
$result = $this->readListQueryHandler->execute($readListQuery);
|
||||
|
||||
return new SuccessResponse($this->responseFormatter->format($result));
|
||||
}
|
||||
}
|
||||
31
src/ApiDomain/External/TagList/src/ResponseFormatter/ReadListResponseFormatter.php
vendored
Normal file
31
src/ApiDomain/External/TagList/src/ResponseFormatter/ReadListResponseFormatter.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\TagList\ResponseFormatter;
|
||||
|
||||
use MyTube\Data\Business\Entity\Tag;
|
||||
use MyTube\Handling\TagList\Handler\Query\ReadList\ReadListQueryResult;
|
||||
|
||||
class ReadListResponseFormatter
|
||||
{
|
||||
public function format(ReadListQueryResult $readListQueryResult): array
|
||||
{
|
||||
$tags = $readListQueryResult->getItems();
|
||||
$items = [];
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
$items[] = [
|
||||
'id' => $tag->getId()->toString(),
|
||||
'description' => $tag->getDescription(),
|
||||
'videoCount' => $tag->getVideos()->count()
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'total' => count($items),
|
||||
'items' => $items,
|
||||
];
|
||||
}
|
||||
}
|
||||
48
src/ApiDomain/External/User/config/routes.php
vendored
Normal file
48
src/ApiDomain/External/User/config/routes.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\User\Handler\ChangePasswordHandler;
|
||||
use MyTube\API\External\User\Handler\ChangeUsernameHandler;
|
||||
use MyTube\API\External\User\Handler\CreateUserHandler;
|
||||
use MyTube\API\External\User\Handler\UserStateHandler;
|
||||
use MyTube\Infrastructure\Rbac\Middleware\EnsureAuthorizationMiddleware;
|
||||
use MyTube\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'user.create-user',
|
||||
'path' => '/api/user/create-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
EnsureAuthorizationMiddleware::class,
|
||||
CreateUserHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'user.change-password',
|
||||
'path' => '/api/user/change-password',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
ChangePasswordHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'user.change-username',
|
||||
'path' => '/api/user/change-username',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
ChangeUsernameHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'user.state',
|
||||
'path' => '/api/user/state',
|
||||
'allowed_methods' => ['GET'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
UserStateHandler::class
|
||||
],
|
||||
],
|
||||
];
|
||||
21
src/ApiDomain/External/User/config/service_manager.php
vendored
Normal file
21
src/ApiDomain/External/User/config/service_manager.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
use MyTube\API\External\User\Formatter\UserFormatter;
|
||||
use MyTube\API\External\User\Handler\ChangePasswordHandler;
|
||||
use MyTube\API\External\User\Handler\ChangeUsernameHandler;
|
||||
use MyTube\API\External\User\Handler\CreateUserHandler;
|
||||
use MyTube\API\External\User\Handler\UserStateHandler;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Formatter
|
||||
UserFormatter::class => AutoWiringFactory::class,
|
||||
|
||||
// Handler
|
||||
CreateUserHandler::class => AutoWiringFactory::class,
|
||||
UserStateHandler::class => AutoWiringFactory::class,
|
||||
ChangePasswordHandler::class => AutoWiringFactory::class,
|
||||
ChangeUsernameHandler::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
16
src/ApiDomain/External/User/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/User/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\User;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
27
src/ApiDomain/External/User/src/Formatter/UserFormatter.php
vendored
Normal file
27
src/ApiDomain/External/User/src/Formatter/UserFormatter.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace MyTube\API\External\User\Formatter;
|
||||
|
||||
use DateTime;
|
||||
use MyTube\Data\Business\Entity\User;
|
||||
|
||||
class UserFormatter {
|
||||
|
||||
public function format(User $user): array {
|
||||
$userArray = [
|
||||
'id' => $user->getId()->toString(),
|
||||
'username' => $user->getUsername(),
|
||||
'role' => $user->getRole()->getIdentifier(),
|
||||
'created' => $user->getCreatedAt()->format(DateTime::ATOM),
|
||||
'updated' => $user->getUpdatedAt()->format(DateTime::ATOM)
|
||||
];
|
||||
|
||||
$userArray['permissions'] = [];
|
||||
|
||||
foreach ($user->getRole()->getPermissions()->toArray() as $permission) {
|
||||
$userArray['permissions'][] = $permission->getIdentifier();
|
||||
}
|
||||
|
||||
return $userArray;
|
||||
}
|
||||
}
|
||||
40
src/ApiDomain/External/User/src/Handler/ChangePasswordHandler.php
vendored
Normal file
40
src/ApiDomain/External/User/src/Handler/ChangePasswordHandler.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MyTube\API\External\User\Handler;
|
||||
|
||||
use MyTube\Data\Business\Entity\User;
|
||||
use MyTube\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandBuilder;
|
||||
use MyTube\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandHandler;
|
||||
use MyTube\Infrastructure\Response\SuccessResponse;
|
||||
use MyTube\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ChangePasswordHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ChangePasswordCommandHandler $handler,
|
||||
private readonly ChangePasswordCommandBuilder $builder,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
|
||||
|
||||
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$user,
|
||||
$data['password'],
|
||||
$data['newPassword'],
|
||||
);
|
||||
$this->handler->execute($query);
|
||||
|
||||
return new SuccessResponse();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user