diff --git a/.env b/.env index afd9352..f728a72 100644 --- a/.env +++ b/.env @@ -1 +1,12 @@ APP_ENV=test +PHP=php +SYMFONY=symfony +COMPOSER=composer + +# use .env.local to override, example: + +# PHP with xdebug: +#PHP=php -dxdebug.start_with_request=yes -dxdebug.mode=debug + +# PHP using docker and xdebug: +#PHP=docker run -it --rm --user $$(id -u):$$(id -g) -v "$$PWD":/usr/src/myapp -w /usr/src/myapp php:8.4.0beta5-cli php -dxdebug.start_with_request=yes -dxdebug.mode=debug diff --git a/.gitignore b/.gitignore index fefb1ee..1d2e81a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ composer.lock -vendor/ +vendor .phpunit.cache tools .php-cs-fixer.cache var rector.log +.env.local diff --git a/Makefile b/Makefile index 4302d91..e2a8590 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,8 @@ +include .env +-include .env.local + +export APP_ENV + .PHONY: all all: test @@ -10,17 +15,17 @@ test: composer-dump composer-validate phpstan psalm phpunit .PHONY: phpstan phpstan: - vendor/bin/phpstan analyse + $(PHP) vendor/bin/phpstan analyse .PHONY: psalm psalm: - vendor/bin/psalm + $(PHP) vendor/bin/psalm .PHONY: phpunit phpunit: $(eval c ?=) rm -rf tests/var - vendor/bin/phpunit $(c) + $(PHP) vendor/bin/phpunit $(c) .PHONY: composer-dump composer-dump: @@ -32,7 +37,7 @@ composer-validate: .PHONY: php-cs-fixer php-cs-fixer: tools/php-cs-fixer - $< fix --config=.php-cs-fixer.dist.php --verbose --allow-risky=yes + $(PHP) $< fix --config=.php-cs-fixer.dist.php --verbose --allow-risky=yes .PHONY: tools/php-cs-fixer tools/php-cs-fixer: @@ -62,3 +67,11 @@ monorepo-release-%: git switch -c release/$* git add . git commit -m "release: $*" + +.PHONY: serve +serve: + $(PHP) tests/bin/console cache:clear + $(PHP) tests/bin/console importmap:install + $(PHP) tests/bin/console asset-map:compile + $(PHP) tests/bin/console asset:install tests/public/ + cd tests && sh -c "$(SYMFONY) server:start --document-root=public" diff --git a/composer.json b/composer.json index 6b5f4a6..b2956c2 100644 --- a/composer.json +++ b/composer.json @@ -22,14 +22,14 @@ "league/mime-type-detection": "^1.0.0", "maennchen/zipstream-php": "^3.1", "nyholm/psr7": "^1.8", - "oneup/uploader-bundle": "^4.0", + "oneup/uploader-bundle": "^5.0", "php": "^8.1", "php-http/discovery": "^1.15", "psr/container": "^2.0", "psr/http-factory-implementation": "^1.0", "psr/http-message": "^1.0 || ^2.0", "rekalogika/direct-property-access": "^1.1.2 || ^1.2", - "rekalogika/doctrine-collections-decorator": "^2.3", + "rekalogika/doctrine-collections-decorator": "^2.0", "rekalogika/reconstitutor": "^1.3.2 || ^1.4", "rekalogika/temporary-url-bundle": "^1.3", "symfony/config": "^6.2 || ^7.0", @@ -61,18 +61,25 @@ "psalm/plugin-mockery": "^1.1", "psalm/plugin-phpunit": "^0.19.0", "rector/rector": "^1.2", + "symfony/asset": "^6.2 || ^7.0", "symfony/asset-mapper": "^6.2 || ^7.0", "symfony/console": "^6.2 || ^7.0", "symfony/debug-bundle": "^6.2 || ^7.0", "symfony/dotenv": "^6.2 || ^7.0", "symfony/framework-bundle": "^6.2 || ^7.0", "symfony/http-client": "^6.2 || ^7.0", + "symfony/maker-bundle": "^1.55", + "symfony/monolog-bundle": "^3.0", "symfony/phpunit-bridge": "^6.3 || ^7.0", "symfony/property-info": "^6.2 || ^7.0", "symfony/routing": "^6.2 || ^7.0", "symfony/runtime": "^6.2 || ^7.0", + "symfony/twig-bundle": "^6.2 || ^7.0", + "symfony/ux-turbo": "^2.20", + "symfony/web-profiler-bundle": "^6.2 || ^7.0", "symfony/yaml": "^6.2 || ^7.0", "symplify/monorepo-builder": "^11.2.20 || ^11.3", + "twig/extra-bundle": "^2.12|^3.0", "vimeo/psalm": "^5.26" }, "replace": { diff --git a/packages/file-filepond/assets/package.json b/packages/file-filepond/assets/package.json index 6f3160c..ad6f220 100644 --- a/packages/file-filepond/assets/package.json +++ b/packages/file-filepond/assets/package.json @@ -14,7 +14,54 @@ } }, "importmap": { - "@hotwired/stimulus": "^3.0" + "@hotwired/stimulus": "^3.0", + "filepond": "^4.31.3", + "filepond/dist/filepond.min.css": "^4.31.3", + "filepond-plugin-file-encode": "^2.1.11", + "filepond-plugin-file-metadata": "^1.0.8", + "filepond-plugin-file-poster": "^2.5.1", + "filepond-plugin-file-poster/dist/filepond-plugin-file-poster.css": "^2.5.1", + "filepond-plugin-file-validate-size": "^2.2.8", + "filepond-plugin-file-validate-type": "^1.2.8", + "filepond-plugin-image-crop": "^2.0.6", + "filepond-plugin-image-edit": "^1.6.3", + "filepond-plugin-image-edit/dist/filepond-plugin-image-edit.css": "^1.6.3", + "filepond-plugin-image-exif-orientation": "^1.0.11", + "filepond-plugin-image-preview": "^4.6.11", + "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css": "^4.6.11", + "filepond-plugin-image-resize": "^2.0.10", + "filepond-plugin-image-transform": "^3.8.7", + "filepond-plugin-image-validate-size": "^1.2.7", + "filepond/locale/ar-ar.js": "^4.31.3", + "filepond/locale/cs-cz.js": "^4.31.3", + "filepond/locale/da-dk.js": "^4.31.3", + "filepond/locale/de-de.js": "^4.31.3", + "filepond/locale/el-el.js": "^4.31.3", + "filepond/locale/en-en.js": "^4.31.3", + "filepond/locale/es-es.js": "^4.31.3", + "filepond/locale/fa_ir.js": "^4.31.3", + "filepond/locale/fi-fi.js": "^4.31.3", + "filepond/locale/fr-fr.js": "^4.31.3", + "filepond/locale/he-he.js": "^4.31.3", + "filepond/locale/hr-hr.js": "^4.31.3", + "filepond/locale/hu-hu.js": "^4.31.3", + "filepond/locale/id-id.js": "^4.31.3", + "filepond/locale/it-it.js": "^4.31.3", + "filepond/locale/ja-ja.js": "^4.31.3", + "filepond/locale/lt-lt.js": "^4.31.3", + "filepond/locale/nl-nl.js": "^4.31.3", + "filepond/locale/no_nb.js": "^4.31.3", + "filepond/locale/pl-pl.js": "^4.31.3", + "filepond/locale/pt-br.js": "^4.31.3", + "filepond/locale/ro-ro.js": "^4.31.3", + "filepond/locale/ru-ru.js": "^4.31.3", + "filepond/locale/sk-sk.js": "^4.31.3", + "filepond/locale/sv_se.js": "^4.31.3", + "filepond/locale/tr-tr.js": "^4.31.3", + "filepond/locale/uk-ua.js": "^4.31.3", + "filepond/locale/vi-vi.js": "^4.31.3", + "filepond/locale/zh-cn.js": "^4.31.3", + "filepond/locale/zh-tw.js": "^4.31.3" } }, "scripts": { diff --git a/packages/file-oneup-uploader-bridge/composer.json b/packages/file-oneup-uploader-bridge/composer.json index 83259fe..aa54a3c 100644 --- a/packages/file-oneup-uploader-bridge/composer.json +++ b/packages/file-oneup-uploader-bridge/composer.json @@ -23,7 +23,7 @@ } }, "require": { - "oneup/uploader-bundle": "^4.0", + "oneup/uploader-bundle": "^5.0", "rekalogika/file-contracts": "^1.10.1", "rekalogika/file": "^1.10.1" }, diff --git a/tests/assets/app.js b/tests/assets/app.js new file mode 100644 index 0000000..8725cc5 --- /dev/null +++ b/tests/assets/app.js @@ -0,0 +1,10 @@ +import './bootstrap.js'; +/* + * Welcome to your app's main JavaScript file! + * + * This file will be included onto the page via the importmap() Twig function, + * which should already be in your base.html.twig. + */ +import './styles/app.css'; + +console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉'); diff --git a/tests/assets/bootstrap.js b/tests/assets/bootstrap.js new file mode 100644 index 0000000..d4e50c9 --- /dev/null +++ b/tests/assets/bootstrap.js @@ -0,0 +1,5 @@ +import { startStimulusApp } from '@symfony/stimulus-bundle'; + +const app = startStimulusApp(); +// register any custom, 3rd party controllers here +// app.register('some_controller_name', SomeImportedController); diff --git a/tests/assets/controllers.json b/tests/assets/controllers.json new file mode 100644 index 0000000..bde96a5 --- /dev/null +++ b/tests/assets/controllers.json @@ -0,0 +1,4 @@ +{ + "controllers": {}, + "entrypoints": [] +} diff --git a/tests/assets/controllers/hello_controller.js b/tests/assets/controllers/hello_controller.js new file mode 100644 index 0000000..e847027 --- /dev/null +++ b/tests/assets/controllers/hello_controller.js @@ -0,0 +1,16 @@ +import { Controller } from '@hotwired/stimulus'; + +/* + * This is an example Stimulus controller! + * + * Any element with a data-controller="hello" attribute will cause + * this controller to be executed. The name "hello" comes from the filename: + * hello_controller.js -> "hello" + * + * Delete this file or adapt it for your use! + */ +export default class extends Controller { + connect() { + this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js'; + } +} diff --git a/tests/assets/styles/app.css b/tests/assets/styles/app.css new file mode 100644 index 0000000..dd6181a --- /dev/null +++ b/tests/assets/styles/app.css @@ -0,0 +1,3 @@ +body { + background-color: skyblue; +} diff --git a/tests/config/packages/asset_mapper.yaml b/tests/config/packages/asset_mapper.yaml new file mode 100644 index 0000000..3de5105 --- /dev/null +++ b/tests/config/packages/asset_mapper.yaml @@ -0,0 +1,5 @@ +framework: + asset_mapper: + # The paths to make available to the asset mapper. + paths: + - assets/ \ No newline at end of file diff --git a/tests/config/packages/routing.yaml b/tests/config/packages/routing.yaml new file mode 100644 index 0000000..7e97762 --- /dev/null +++ b/tests/config/packages/routing.yaml @@ -0,0 +1,3 @@ +framework: + router: + utf8: true diff --git a/tests/config/packages/translation.yaml b/tests/config/packages/translation.yaml new file mode 100644 index 0000000..90270e5 --- /dev/null +++ b/tests/config/packages/translation.yaml @@ -0,0 +1,4 @@ +framework: + default_locale: en + translator: + default_path: '%kernel.project_dir%/translations' \ No newline at end of file diff --git a/tests/config/packages/twig.yaml b/tests/config/packages/twig.yaml new file mode 100644 index 0000000..5ad6061 --- /dev/null +++ b/tests/config/packages/twig.yaml @@ -0,0 +1,2 @@ +twig: + form_themes: ['bootstrap_5_horizontal_layout.html.twig'] diff --git a/tests/config/packages/web_profiler.yaml b/tests/config/packages/web_profiler.yaml new file mode 100644 index 0000000..6366b91 --- /dev/null +++ b/tests/config/packages/web_profiler.yaml @@ -0,0 +1,11 @@ +web_profiler: + toolbar: true + intercept_redirects: false + +framework: + profiler: + enabled: true + collect: true + only_exceptions: false + collect_serializer_data: true + only_main_requests: false diff --git a/tests/config/routes/test.yaml b/tests/config/routes/test.yaml new file mode 100644 index 0000000..214b772 --- /dev/null +++ b/tests/config/routes/test.yaml @@ -0,0 +1,5 @@ +test: + resource: + path: '../../src/App/Controller/' + namespace: 'Rekalogika\File\Tests\App\Controller' + type: attribute diff --git a/tests/config/routes/web_profiler.yaml b/tests/config/routes/web_profiler.yaml new file mode 100644 index 0000000..ce3155d --- /dev/null +++ b/tests/config/routes/web_profiler.yaml @@ -0,0 +1,7 @@ +web_profiler_wdt: + resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" + prefix: /_wdt + +web_profiler_profiler: + resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" + prefix: /_profiler diff --git a/tests/config/services.php b/tests/config/services.php new file mode 100644 index 0000000..1e292bd --- /dev/null +++ b/tests/config/services.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; + +return static function (ContainerConfigurator $containerConfigurator): void { + $services = $containerConfigurator->services(); + + $services->defaults() + ->autowire() + ->autoconfigure() + ->public(); + + $services + ->load('Rekalogika\\File\\Tests\\App\\', '../src/App/*'); + +}; diff --git a/tests/importmap.php b/tests/importmap.php new file mode 100644 index 0000000..5628bfa --- /dev/null +++ b/tests/importmap.php @@ -0,0 +1,173 @@ + [ + 'path' => './assets/app.js', + 'entrypoint' => true, + ], + '@symfony/stimulus-bundle' => [ + 'path' => '../vendor/symfony/stimulus-bundle/assets/dist/loader.js', + ], + '@hotwired/stimulus' => [ + 'version' => '3.2.2', + ], + '@hotwired/turbo' => [ + 'version' => '8.0.10', + ], + 'filepond' => [ + 'version' => '^4.31.3' + ], + 'filepond/dist/filepond.min.css' => [ + 'version' => '^4.31.3', + 'type' => 'css' + ], + 'filepond-plugin-file-encode' => [ + 'version' => '^2.1.11' + ], + 'filepond-plugin-file-metadata' => [ + 'version' => '^1.0.8' + ], + 'filepond-plugin-file-poster' => [ + 'version' => '^2.5.1' + ], + 'filepond-plugin-file-poster/dist/filepond-plugin-file-poster.css' => [ + 'version' => '^2.5.1', + 'type' => 'css' + ], + 'filepond-plugin-file-validate-size' => [ + 'version' => '^2.2.8' + ], + 'filepond-plugin-file-validate-type' => [ + 'version' => '^1.2.8' + ], + 'filepond-plugin-image-crop' => [ + 'version' => '^2.0.6' + ], + 'filepond-plugin-image-edit' => [ + 'version' => '^1.6.3' + ], + 'filepond-plugin-image-edit/dist/filepond-plugin-image-edit.css' => [ + 'version' => '^1.6.3', + 'type' => 'css' + ], + 'filepond-plugin-image-exif-orientation' => [ + 'version' => '^1.0.11' + ], + 'filepond-plugin-image-preview' => [ + 'version' => '^4.6.11' + ], + 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css' => [ + 'version' => '^4.6.11', + 'type' => 'css' + ], + 'filepond-plugin-image-resize' => [ + 'version' => '^2.0.10' + ], + 'filepond-plugin-image-transform' => [ + 'version' => '^3.8.7' + ], + 'filepond-plugin-image-validate-size' => [ + 'version' => '^1.2.7' + ], + 'filepond/locale/ar-ar.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/cs-cz.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/da-dk.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/de-de.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/el-el.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/en-en.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/es-es.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/fa_ir.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/fi-fi.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/fr-fr.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/he-he.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/hr-hr.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/hu-hu.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/id-id.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/it-it.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/ja-ja.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/lt-lt.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/nl-nl.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/no_nb.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/pl-pl.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/pt-br.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/ro-ro.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/ru-ru.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/sk-sk.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/sv_se.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/tr-tr.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/uk-ua.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/vi-vi.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/zh-cn.js' => [ + 'version' => '^4.31.3' + ], + 'filepond/locale/zh-tw.js' => [ + 'version' => '^4.31.3' + ] +]; diff --git a/tests/public/.htaccess b/tests/public/.htaccess new file mode 100644 index 0000000..1cd962f --- /dev/null +++ b/tests/public/.htaccess @@ -0,0 +1,22 @@ +DirectoryIndex index.php + + Options -MultiViews + + +RewriteEngine On + +RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$ +RewriteRule .* - [E=BASE:%1] + +# Sets the HTTP_AUTHORIZATION header removed by Apache +RewriteCond %{HTTP:Authorization} .+ +RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] + +# Removes the /index.php/ part from a URL, if present +RewriteCond %{ENV:REDIRECT_STATUS} ="" +RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L] + +# If the requested filename exists, simply serve it. +# Otherwise rewrite all other queries to the front controller. +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^ %{ENV:BASE}/index.php [L] diff --git a/tests/public/index.php b/tests/public/index.php new file mode 100644 index 0000000..e372ed1 --- /dev/null +++ b/tests/public/index.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +require_once __DIR__ . '/../../vendor/autoload_runtime.php'; + +return fn(array $context): TestKernel => new TestKernel(); diff --git a/tests/src/App/Controller/TestController.php b/tests/src/App/Controller/TestController.php new file mode 100644 index 0000000..04bd087 --- /dev/null +++ b/tests/src/App/Controller/TestController.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\File\Tests\App\Controller; + +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; + +class TestController extends AbstractController +{ + #[Route('/', name: 'index')] + public function index(): Response + { + return $this->render('index.html.twig'); + } + +} diff --git a/tests/src/TestKernel.php b/tests/src/TestKernel.php index aed5210..e825868 100644 --- a/tests/src/TestKernel.php +++ b/tests/src/TestKernel.php @@ -30,6 +30,7 @@ use Rekalogika\File\Association\PropertyReaderWriter\SymfonyPropertyAccessorBridge; use Rekalogika\File\Association\Reconstitutor\AttributeReconstitutor; use Rekalogika\File\Association\Reconstitutor\InterfaceReconstitutor; +use Rekalogika\File\Bridge\FilePond\RekalogikaFileFilePondBundle; use Rekalogika\File\Bundle\RekalogikaFileBundle; use Rekalogika\File\Image\ImageResizer; use Rekalogika\File\Zip\FileZip; @@ -41,10 +42,15 @@ use Symfony\Bundle\DebugBundle\DebugBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; +use Symfony\Bundle\MakerBundle\MakerBundle; +use Symfony\Bundle\TwigBundle\TwigBundle; +use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Kernel as HttpKernelKernel; +use Symfony\UX\StimulusBundle\StimulusBundle; +use Symfony\UX\Turbo\TurboBundle; +use Twig\Extra\TwigExtraBundle\TwigExtraBundle; class TestKernel extends HttpKernelKernel { @@ -74,9 +80,16 @@ public function registerBundles(): iterable yield new FrameworkBundle(); yield new DoctrineBundle(); yield new DebugBundle(); + yield new WebProfilerBundle(); + yield new TwigBundle(); + yield new MakerBundle(); + yield new StimulusBundle(); + yield new TurboBundle(); + yield new TwigExtraBundle(); yield new RekalogikaDirectPropertyAccessBundle(); yield new RekalogikaReconstitutorBundle(); yield new RekalogikaFileBundle(); + yield new RekalogikaFileFilePondBundle(); yield new RekalogikaTemporaryUrlBundle(); yield new RekalogikaPsr16SimpleCacheBundle(); } diff --git a/tests/templates/base.html.twig b/tests/templates/base.html.twig new file mode 100644 index 0000000..3cda30f --- /dev/null +++ b/tests/templates/base.html.twig @@ -0,0 +1,17 @@ + + + + + {% block title %}Welcome!{% endblock %} + + {% block stylesheets %} + {% endblock %} + + {% block javascripts %} + {% block importmap %}{{ importmap('app') }}{% endblock %} + {% endblock %} + + + {% block body %}{% endblock %} + + diff --git a/tests/templates/index.html.twig b/tests/templates/index.html.twig new file mode 100644 index 0000000..1503ec7 --- /dev/null +++ b/tests/templates/index.html.twig @@ -0,0 +1 @@ +{% extends 'base.html.twig' %}