diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..14eaf4c --- /dev/null +++ b/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + ["@babel/preset-env", { + "targets": { + "node": "6" + } + }] + ], + "plugins": [ + ["@babel/plugin-proposal-object-rest-spread", { + "useBuiltIns": true + }] + ] +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..81d9a54 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,32 @@ +**/*.log +**/*.md +**/*.php~ +**/._* +**/.dockerignore +**/.DS_Store +**/.git/ +**/.gitattributes +**/.github +**/.gitignore +**/.gitkeep +**/.gitmodules +**/.idea +**/Dockerfile +**/Thumbs.db +**/docker-compose*.yaml +**/docker-compose*.yml +.editorconfig +.php_cs.cache +.travis.yml +composer.phar +docker/mysql/data/ +etc/build/* +node_modules/ +var/* +vendor/ +public/assets/ +public/build/ +public/bundles/ +public/css/ +public/js/ +public/media/ diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8c5a7e8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,88 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +# Change these settings to your own preference +indent_style = space +indent_size = 4 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.feature] +indent_style = space +indent_size = 4 + +[*.js] +indent_style = space +indent_size = 2 + +[*.json] +indent_style = space +indent_size = 2 + +[*.md] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = false + +[*.neon] +indent_style = space +indent_size = 4 + +[*.php] +indent_style = space +indent_size = 4 + +[*.sh] +indent_style = space +indent_size = 4 + +[*.{yaml,yml}] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = false + +[docker-compose.{yaml,yml}] +indent_size = 2 + +[docker-compose.*.{yaml,yml}] +indent_size = 2 + +[.babelrc] +indent_style = space +indent_size = 2 + +[.gitmodules] +indent_style = tab +indent_size = 4 + +[.php_cs{,.dist}] +indent_style = space +indent_size = 4 + +[composer.json] +indent_style = space +indent_size = 4 + +[package.json] +indent_style = space +indent_size = 2 + +[phpspec.yml{,.dist}] +indent_style = space +indent_size = 4 + +[phpstan.neon] +indent_style = space +indent_size = 4 + +[phpunit.xml{,.dist}] +indent_style = space +indent_size = 4 diff --git a/.env b/.env new file mode 100644 index 0000000..0379e65 --- /dev/null +++ b/.env @@ -0,0 +1,36 @@ +# This file is a "template" of which env vars needs to be defined in your configuration or in an .env file +# Set variables here that may be different on each deployment target of the app, e.g. development, staging, production. +# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration + +###> symfony/framework-bundle ### +APP_ENV=dev +APP_DEBUG=1 +APP_SECRET=EDITME +###< symfony/framework-bundle ### + +###> doctrine/doctrine-bundle ### +# Choose one of the following DBMS, adjust the server version and charset if needed +DATABASE_URL=mysql://root@127.0.0.1/sylius_%kernel.environment%?serverVersion=8&charset=utf8mb4 +#DATABASE_URL=pgsql://postgres:postgres@127.0.0.1/sylius_%kernel.environment%?serverVersion=15&charset=utf8 +###< doctrine/doctrine-bundle ### + +###> symfony/messenger ### +# Choose one of the transports below +# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages +# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages +MESSENGER_TRANSPORT_DSN=doctrine://default +SYLIUS_MESSENGER_TRANSPORT_MAIN_DSN=doctrine://default +SYLIUS_MESSENGER_TRANSPORT_MAIN_FAILED_DSN=doctrine://default?queue_name=main_failed +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_DSN=doctrine://default?queue_name=catalog_promotion_removal +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_FAILED_DSN=doctrine://default?queue_name=catalog_promotion_removal_failed +###< symfony/messenger ### + +###> lexik/jwt-authentication-bundle ### +JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem +JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem +JWT_PASSPHRASE=e7c5fca1060bdf6ad23c33e4c236081f +###< lexik/jwt-authentication-bundle ### + +###> symfony/mailer ### +MAILER_DSN=null://null +###< symfony/mailer ### diff --git a/.env.prod b/.env.prod new file mode 100644 index 0000000..caab7ca --- /dev/null +++ b/.env.prod @@ -0,0 +1,3 @@ +APP_ENV=prod +APP_DEBUG=0 +APP_SECRET='s$cretf0rt3st' diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..ddc27a6 --- /dev/null +++ b/.env.test @@ -0,0 +1,18 @@ +APP_SECRET='s$cretf0rt3st' + +KERNEL_CLASS='App\Kernel' + +###> lexik/jwt-authentication-bundle ### +JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private-test.pem +JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public-test.pem +JWT_PASSPHRASE=ALL_THAT_IS_GOLD_DOES_NOT_GLITTER_NOT_ALL_THOSE_WHO_WANDER_ARE_LOST +###< lexik/jwt-authentication-bundle ### + +###> symfony/messenger ### +# Sync transport turned for testing env for the ease of testing +MESSENGER_TRANSPORT_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_MAIN_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_MAIN_FAILED_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_FAILED_DSN=sync:// +###< symfony/messenger ### diff --git a/.env.test_cached b/.env.test_cached new file mode 100644 index 0000000..ace50d7 --- /dev/null +++ b/.env.test_cached @@ -0,0 +1,19 @@ +APP_DEBUG=0 +APP_SECRET='s$cretf0rt3st' + +KERNEL_CLASS='App\Kernel' + +###> lexik/jwt-authentication-bundle ### +JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private-test.pem +JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public-test.pem +JWT_PASSPHRASE=ALL_THAT_IS_GOLD_DOES_NOT_GLITTER_NOT_ALL_THOSE_WHO_WANDER_ARE_LOST +###< lexik/jwt-authentication-bundle ### + +###> symfony/messenger ### +# Sync transport turned for testing env for the ease of testing +MESSENGER_TRANSPORT_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_MAIN_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_MAIN_FAILED_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_FAILED_DSN=sync:// +###< symfony/messenger ### diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..dfddb25 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,20 @@ +module.exports = { + extends: 'airbnb-base', + env: { + node: true, + }, + rules: { + 'object-shorthand': ['error', 'always', { + avoidQuotes: true, + avoidExplicitReturnArrows: true, + }], + 'function-paren-newline': ['error', 'consistent'], + 'max-len': ['warn', 120, 2, { + ignoreUrls: true, + ignoreComments: false, + ignoreRegExpLiterals: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + }], + }, +}; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..92faea2 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Sylius/core-team diff --git a/.github/autolabeler.yml b/.github/autolabeler.yml new file mode 100644 index 0000000..86c9218 --- /dev/null +++ b/.github/autolabeler.yml @@ -0,0 +1,2 @@ +Maintenance: ['etc/', '.github/', '*.md'] +Docker: ['docker/', '.docker/', 'Dockerfile', 'docker-compose.*'] diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e91abb6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,34 @@ +version: 2 +updates: +- package-ecosystem: composer + directory: "/" + schedule: + interval: daily + time: "10:00" + open-pull-requests-limit: 10 + ignore: + - dependency-name: stripe/stripe-php + versions: + - 7.69.0 + - 7.70.0 + - 7.72.0 + - 7.73.0 + - 7.74.0 + - 7.75.0 + - 7.76.0 + - dependency-name: sylius-labs/coding-standard + versions: + - 4.0.1 + - dependency-name: sylius/sylius + versions: + - 1.9.0 + - dependency-name: phpstan/phpstan + versions: + - 0.12.70 + - 0.12.71 + - 0.12.73 + - dependency-name: phpstan/phpstan-webmozart-assert + versions: + - 0.12.10 + - 0.12.11 + - 0.12.9 diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml new file mode 100644 index 0000000..e5fc0ec --- /dev/null +++ b/.github/workflows/auto-merge.yml @@ -0,0 +1,22 @@ +name: Auto-merge + +on: + pull_request: ~ + +jobs: + auto-merge: + runs-on: ubuntu-20.04 + steps: + - + name: Checkout repository + uses: actions/checkout@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - + name: Auto-merge minor dependencies upgrades + uses: ahmadnassri/action-dependabot-auto-merge@v2 + with: + target: minor + github-token: ${{ secrets.GITHUB_TOKEN }} + config: .github/dependabot.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..ca0b583 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,209 @@ +name: Build + +on: + push: + branches-ignore: + - "dependabot/**" + paths-ignore: + - "*.md" + pull_request: + paths-ignore: + - "*.md" + release: + types: [created] + schedule: + - + cron: "0 1 * * 6" # Run at 1am every Saturday + workflow_dispatch: ~ + +jobs: + tests: + runs-on: ubuntu-20.04 + + name: "PHP ${{ matrix.php }}, Symfony ${{ matrix.symfony }}, MySQL ${{ matrix.mysql }}, Node ${{ matrix.node }}" + + timeout-minutes: 50 + + strategy: + fail-fast: false + matrix: + php: ["8.0", "8.1"] + symfony: ["^5.4", "^6.0"] + node: ["16.x"] + mysql: ["5.7", "8.0"] + + env: + APP_ENV: test_cached + DATABASE_URL: "mysql://root:root@127.0.0.1/sylius?serverVersion=${{ matrix.mysql }}" + + steps: + - + uses: actions/checkout@v2 + + - + name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + extensions: intl, mbstring + tools: symfony + coverage: none + + - + name: Restrict Symfony version + if: matrix.symfony != '' + run: | + composer global config --no-plugins allow-plugins.symfony/flex true + composer global require --no-progress --no-scripts --no-plugins "symfony/flex:1.18.5" + composer config extra.symfony.require "${{ matrix.symfony }}" + + - + name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: "${{ matrix.node }}" + + - + name: Shutdown default MySQL + run: sudo service mysql stop + + - + name: Setup MySQL + uses: mirromutth/mysql-action@v1.1 + with: + mysql version: "${{ matrix.mysql }}" + mysql root password: "root" + + - + name: Output PHP version for Symfony CLI + run: php -v | head -n 1 | awk '{ print $2 }' > .php-version + + - + name: Install certificates + run: symfony server:ca:install + + - + name: Run Chrome Headless + run: google-chrome-stable --enable-automation --disable-background-networking --no-default-browser-check --no-first-run --disable-popup-blocking --disable-default-apps --allow-insecure-localhost --disable-translate --disable-extensions --no-sandbox --enable-features=Metal --headless --remote-debugging-port=9222 --window-size=2880,1800 --proxy-server='direct://' --proxy-bypass-list='*' http://127.0.0.1 > /dev/null 2>&1 & + + - + name: Run webserver + run: symfony server:start --port=8080 --dir=public --daemon + + - + name: Restrict Symfony version + if: matrix.symfony != '' + run: composer config extra.symfony.require "${{ matrix.symfony }}" + + - + name: Get Composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - + name: Cache Composer + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json **/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php-${{ matrix.php }}-composer- + + - + name: Install PHP dependencies + run: composer install --no-interaction + + - + name: Get Yarn cache directory + id: yarn-cache + run: echo "::set-output name=dir::$(yarn cache dir)" + + - + name: Cache Yarn + uses: actions/cache@v2 + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-node-${{ matrix.node }}-yarn-${{ hashFiles('**/package.json **/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node-${{ matrix.node }}-yarn- + + - + name: Install JS dependencies + run: yarn install + + - + name: Prepare test application database + run: | + APP_DEBUG=1 bin/console doctrine:database:create -vvv + bin/console doctrine:migrations:migrate -n -vvv + + - + name: Prepare test application assets + run: | + bin/console assets:install public -vvv + yarn encore production + + - + name: Prepare test application cache + run: bin/console cache:warmup -vvv + + - + name: Prepare Messenger transport (Doctrine) + run: bin/console messenger:setup-transports -vvv + + - + name: Load fixtures + run: bin/console sylius:fixtures:load -n + + - + name: Validate composer.json + run: composer validate --ansi --strict --no-check-publish + + - + name: Run security check + run: symfony security:check + + - + name: Check coding standard + run: vendor/bin/ecs check src + + - + name: Run PHPStan + run: vendor/bin/phpstan analyse -c phpstan.neon -l max src/ + + - + name: Validate database schema + run: bin/console doctrine:schema:validate + + - + name: Run PHPSpec + run: vendor/bin/phpspec run --ansi -f progress --no-interaction + + - + name: Run PHPUnit + run: vendor/bin/phpunit --colors=always + + - + name: Run managing catalog promotion scenarios + run: vendor/bin/behat --colors --strict --no-interaction -vvv -f progress --tags="~@javascript&&~@todo&&~@cli&&@managing_catalog_promotions" + + - + name: Run managing exchange rates scenarios + run: vendor/bin/behat --colors --strict --no-interaction -vvv -f progress --tags="~@javascript&&~@todo&&~@cli&&@managing_exchange_rates" + + - + name: Run non-JS Behat (without managing catalog promotion scenarios and exchange rates) + run: vendor/bin/behat --colors --strict --no-interaction -vvv -f progress --tags="~@javascript&&~@todo&&~@cli&&~@managing_catalog_promotions&&~@managing_exchange_rates" + + - + name: Run JS Behat + run: vendor/bin/behat --colors --strict --no-interaction -vvv -f progress --tags="@javascript&&~@todo&&~@cli" || vendor/bin/behat --colors --strict --no-interaction -vvv -f progress --tags="@javascript&&~@todo&&~@cli" --rerun || vendor/bin/behat --colors --strict --no-interaction -vvv -f progress --tags="@javascript&&~@todo&&~@cli" --rerun + + - + name: Upload Behat logs + uses: actions/upload-artifact@v2 + if: failure() + with: + name: "Behat logs (PHP ${{ matrix.php }}, Symfony ${{ matrix.symfony }}, MySQL ${{ matrix.mysql }})" + path: etc/build/ + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18f8948 --- /dev/null +++ b/.gitignore @@ -0,0 +1,49 @@ +/public/assets +/public/build +/public/css +/public/js +/public/media +!/public/media/image/.gitkeep + +/etc/build/* +!/etc/build/.gitignore + +/behat.yml +/phpspec.yml + +/docker-compose.override.yaml +/docker-compose.override.yml +/docker/mysql/data/ + +###> symfony/framework-bundle ### +/composer.lock +/.env.*.local +/.env.local +/.env.local.php +/public/bundles +/var/ +/vendor/ +###< symfony/framework-bundle ### + +###> friendsofphp/php-cs-fixer ### +/.php_cs +/.php_cs.cache +###< friendsofphp/php-cs-fixer ### + +###> phpunit/phpunit ### +/.phpunit.result.cache +/phpunit.xml +###< phpunit/phpunit ### + +###> lexik/jwt-authentication-bundle ### +/config/jwt/*.pem +!/config/jwt/*-test.pem +###< lexik/jwt-authentication-bundle ### + +###> symfony/webpack-encore-bundle ### +/node_modules/ +/public/build/ +/npm-debug.log +/yarn-error.log +/yarn.lock +###< symfony/webpack-encore-bundle ### diff --git a/CONFLICTS.md b/CONFLICTS.md new file mode 100644 index 0000000..dab299f --- /dev/null +++ b/CONFLICTS.md @@ -0,0 +1,9 @@ +# CONFLICTS + +This document explains why certain conflicts were added to `composer.json` and +references related issues. + +- `symfony/framework-bundle:6.2.8`: + + This version is missing the service alias `validator.expression` + which causes ValidatorException exception to be thrown when using `Expression` constraint. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..63b9f8d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,171 @@ +# the different stages of this Dockerfile are meant to be built into separate images +# https://docs.docker.com/compose/compose-file/#target + +ARG PHP_VERSION=8.1 +ARG NODE_VERSION=16 +ARG NGINX_VERSION=1.21 +ARG ALPINE_VERSION=3.15 +ARG COMPOSER_VERSION=2.4 +ARG PHP_EXTENSION_INSTALLER_VERSION=latest + +FROM composer:${COMPOSER_VERSION} AS composer + +FROM mlocati/php-extension-installer:${PHP_EXTENSION_INSTALLER_VERSION} AS php_extension_installer + +FROM php:${PHP_VERSION}-fpm-alpine${ALPINE_VERSION} AS base + +# persistent / runtime deps +RUN apk add --no-cache \ + acl \ + file \ + gettext \ + unzip \ + ; + +COPY --from=php_extension_installer /usr/bin/install-php-extensions /usr/local/bin/ + +# default PHP image extensions +# ctype curl date dom fileinfo filter ftp hash iconv json libxml mbstring mysqlnd openssl pcre PDO pdo_sqlite Phar +# posix readline Reflection session SimpleXML sodium SPL sqlite3 standard tokenizer xml xmlreader xmlwriter zlib +RUN install-php-extensions apcu exif gd intl pdo_mysql opcache zip + +COPY --from=composer /usr/bin/composer /usr/bin/composer +COPY docker/php/prod/php.ini $PHP_INI_DIR/php.ini +COPY docker/php/prod/opcache.ini $PHP_INI_DIR/conf.d/opcache.ini + +# copy file required by opcache preloading +COPY config/preload.php /srv/sylius/config/preload.php + +# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser +ENV COMPOSER_ALLOW_SUPERUSER=1 +RUN set -eux; \ + composer clear-cache +ENV PATH="${PATH}:/root/.composer/vendor/bin" + +WORKDIR /srv/sylius + +# build for production +ENV APP_ENV=prod + +# prevent the reinstallation of vendors at every changes in the source code +COPY composer.* symfony.lock ./ +RUN set -eux; \ + composer install --prefer-dist --no-autoloader --no-interaction --no-scripts --no-progress --no-dev; \ + composer clear-cache + +# copy only specifically what we need +COPY .env .env.prod ./ +COPY assets assets/ +COPY bin bin/ +COPY config config/ +COPY public public/ +COPY src src/ +COPY templates templates/ +COPY translations translations/ + +RUN set -eux; \ + mkdir -p var/cache var/log; \ + composer dump-autoload --classmap-authoritative; \ + APP_SECRET='' composer run-script post-install-cmd; \ + chmod +x bin/console; sync; \ + bin/console sylius:install:assets --no-interaction; \ + bin/console sylius:theme:assets:install public --no-interaction + +VOLUME /srv/sylius/var + +VOLUME /srv/sylius/public/media + +COPY docker/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint +RUN chmod +x /usr/local/bin/docker-entrypoint + +ENTRYPOINT ["docker-entrypoint"] +CMD ["php-fpm"] + +FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS sylius_node + +WORKDIR /srv/sylius + +RUN set -eux; \ + apk add --no-cache --virtual .build-deps \ + g++ \ + gcc \ + make \ + ; + +# prevent the reinstallation of vendors at every changes in the source code +COPY package.json yarn.* ./ +RUN set -eux; \ + yarn install; \ + yarn cache clean + +COPY --from=base /srv/sylius/vendor/sylius/sylius/src/Sylius/Bundle/UiBundle/Resources/private vendor/sylius/sylius/src/Sylius/Bundle/UiBundle/Resources/private/ +COPY --from=base /srv/sylius/vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle/Resources/private vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle/Resources/private/ +COPY --from=base /srv/sylius/vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle/Resources/private vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle/Resources/private/ +COPY --from=base /srv/sylius/assets ./assets + +COPY webpack.config.js ./ +RUN yarn build:prod + +COPY docker/node/docker-entrypoint.sh /usr/local/bin/docker-entrypoint +RUN chmod +x /usr/local/bin/docker-entrypoint + +ENTRYPOINT ["docker-entrypoint"] +CMD ["yarn", "build:prod"] + +FROM base AS sylius_php_prod + +COPY --from=sylius_node /srv/sylius/public/build public/build + +FROM nginx:${NGINX_VERSION}-alpine AS sylius_nginx + +COPY docker/nginx/conf.d/default.conf /etc/nginx/conf.d/ + +WORKDIR /srv/sylius + +COPY --from=base /srv/sylius/public public/ +COPY --from=sylius_node /srv/sylius/public public/ + +FROM sylius_php_prod AS sylius_php_dev + +COPY docker/php/dev/php.ini $PHP_INI_DIR/php.ini +COPY docker/php/dev/opcache.ini $PHP_INI_DIR/conf.d/opcache.ini + +WORKDIR /srv/sylius + +ENV APP_ENV=dev + +COPY .env.test .env.test_cached ./ + +RUN set -eux; \ + composer install --prefer-dist --no-autoloader --no-interaction --no-scripts --no-progress; \ + composer clear-cache + +FROM sylius_php_prod AS sylius_cron + +RUN set -eux; \ + apk add --no-cache --virtual .build-deps \ + apk-cron \ + ; + +COPY docker/cron/crontab /etc/crontabs/root +COPY docker/cron/docker-entrypoint.sh /usr/local/bin/docker-entrypoint +RUN chmod +x /usr/local/bin/docker-entrypoint + +ENTRYPOINT ["docker-entrypoint"] +CMD ["crond", "-f"] + +FROM sylius_php_prod AS sylius_migrations_prod + +COPY docker/migrations/docker-entrypoint.sh /usr/local/bin/docker-entrypoint +RUN chmod +x /usr/local/bin/docker-entrypoint + +ENTRYPOINT ["docker-entrypoint"] + +FROM sylius_php_dev AS sylius_migrations_dev + +COPY docker/migrations/docker-entrypoint.sh /usr/local/bin/docker-entrypoint +RUN chmod +x /usr/local/bin/docker-entrypoint + +RUN composer dump-autoload --classmap-authoritative + +ENTRYPOINT ["docker-entrypoint"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..92d58bf --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011-2020 Paweł Jędrzejewski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7151acb --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +

+ + + +

+ +

Sylius Standard Edition

+ +

This is Sylius Standard Edition repository for starting new projects.

+ +## About + +Sylius is the first decoupled eCommerce framework based on [**Symfony**](http://symfony.com) and [**Doctrine**](http://doctrine-project.org). +The highest quality of code, strong testing culture, built-in Agile (BDD) workflow and exceptional flexibility make it the best solution for application tailored to your business requirements. +Enjoy being an eCommerce Developer again! + +Powerful REST API allows for easy integrations and creating unique customer experience on any device. + +We're using full-stack Behavior-Driven-Development, with [phpspec](http://phpspec.net) and [Behat](http://behat.org) + +## Documentation + +Documentation is available at [docs.sylius.com](http://docs.sylius.com). + +## Installation + +### Traditional +```bash +$ wget http://getcomposer.org/composer.phar +$ php composer.phar create-project sylius/sylius-standard project +$ cd project +$ yarn install +$ yarn build +$ php bin/console sylius:install +$ symfony serve +$ open http://localhost:8000/ +``` + +For more detailed instruction please visit [installation chapter in our docs](https://docs.sylius.com/en/1.10/book/installation/installation.html). + +### Docker + +#### Development + +Make sure you have installed [Docker](https://docs.docker.com/get-docker/) on your local machine. +Execute `docker compose up -d` in your favorite terminal and wait some time until the services will be ready. You might want to see docker logs. +Then enter `localhost` in your browser or execute `open localhost` in your terminal. + +#### Production + +The simplest way to deploy your Sylius store via Docker is via `docker-compose.prod.yml` configuration file. +To do that you need to install [Docker](https://docs.docker.com/get-docker/) on your VPS and define `MYSQL_PASSWORD` environment. +Then execute `docker compose -f docker-compose.prod.yml up -d` command in your terminal. The `MYSQL_PASSWORD` env will be automatically +applied to the rest of the config. + +> When using a Virtual Private Server (VPS) we recommend having at least 2GB of RAM memory + +**Quick deploy:** +```bash +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +export MYSQL_PASSWORD=SLyPJLaye7 + +docker compose -f docker-compose.prod.yml up -d +docker compose -f docker-compose.prod.yml exec php bin/console sylius:fixtures:load --no-interaction +``` + +## Troubleshooting + +If something goes wrong, errors & exceptions are logged at the application level: + +```bash +$ tail -f var/log/prod.log +$ tail -f var/log/dev.log +``` + +## Contributing + +Would like to help us and build the most developer-friendly eCommerce framework? Start from reading our [Contribution Guide](https://docs.sylius.com/en/latest/contributing/)! + +## Stay Updated + +If you want to keep up with the updates, [follow the official Sylius account on Twitter](http://twitter.com/Sylius) and [like us on Facebook](https://www.facebook.com/SyliusEcommerce/). + +## Bug Tracking + +If you want to report a bug or suggest an idea, please use [GitHub issues](https://github.com/Sylius/Sylius/issues). + +## Community Support + +Get Sylius support on [Slack](https://sylius.com/slack), [Forum](https://forum.sylius.com/) or [Stack Overflow](https://stackoverflow.com/questions/tagged/sylius). + +## MIT License + +Sylius is completely free and released under the [MIT License](https://github.com/Sylius/Sylius/blob/master/LICENSE). + +## Authors + +Sylius was originally created by [Paweł Jędrzejewski](http://pjedrzejewski.com). +See the list of [contributors from our awesome community](https://github.com/Sylius/Sylius/contributors). diff --git a/assets/admin/entry.js b/assets/admin/entry.js new file mode 100644 index 0000000..8acf2c2 --- /dev/null +++ b/assets/admin/entry.js @@ -0,0 +1 @@ +// In this file you can import assets like images or stylesheets diff --git a/assets/shop/entry.js b/assets/shop/entry.js new file mode 100644 index 0000000..8acf2c2 --- /dev/null +++ b/assets/shop/entry.js @@ -0,0 +1 @@ +// In this file you can import assets like images or stylesheets diff --git a/behat.yml.dist b/behat.yml.dist new file mode 100644 index 0000000..49d5309 --- /dev/null +++ b/behat.yml.dist @@ -0,0 +1,66 @@ +imports: + - vendor/sylius/sylius/src/Sylius/Behat/Resources/config/suites.yml + +default: + formatters: + pretty: + verbose: true + paths: false + snippets: false + + extensions: + DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension: ~ + + FriendsOfBehat\MinkDebugExtension: + directory: etc/build + clean_start: false + screenshot: true + + Behat\MinkExtension: + files_path: "%paths.base%/vendor/sylius/sylius/src/Sylius/Behat/Resources/fixtures/" + base_url: "https://127.0.0.1:8080/" + default_session: symfony + javascript_session: chrome_headless + sessions: + symfony: + symfony: ~ + chrome_headless: + chrome: + api_url: http://127.0.0.1:9222 + validate_certificate: false + chrome_headless_second_session: + chrome: + api_url: http://127.0.0.1:9222 + validate_certificate: false + chrome: + selenium2: + browser: chrome + capabilities: + browserName: chrome + browser: chrome + version: "" + marionette: null # https://github.com/Behat/MinkExtension/pull/311 + chrome: + switches: + - "start-fullscreen" + - "start-maximized" + - "no-sandbox" + extra_capabilities: + unexpectedAlertBehaviour: accept + firefox: + selenium2: + browser: firefox + show_auto: false + + FriendsOfBehat\SymfonyExtension: ~ + + FriendsOfBehat\VariadicExtension: ~ + + FriendsOfBehat\SuiteSettingsExtension: + paths: + - "vendor/sylius/sylius/features" + - "features" + + gherkin: + filters: + tags: "~@todo&&~@cli" # CLI is excluded as it registers an error handler that mutes fatal errors diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..313dc90 --- /dev/null +++ b/bin/console @@ -0,0 +1,15 @@ +#!/usr/bin/env php +=1.2) +if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) { + $_SERVER += $env; + $_ENV += $env; +} elseif (!class_exists(Dotenv::class)) { + throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); +} elseif (method_exists(Dotenv::class, 'bootEnv')) { + (new Dotenv())->bootEnv(dirname(__DIR__) . '/.env'); + + return; +} else { + // load all the .env files + (new Dotenv(true))->loadEnv(dirname(__DIR__).'/.env'); +} + +$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; +$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; +$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/config/bundles.php b/config/bundles.php new file mode 100644 index 0000000..08f9762 --- /dev/null +++ b/config/bundles.php @@ -0,0 +1,63 @@ + ['all' => true], + Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + Sylius\Calendar\SyliusCalendarBundle::class => ['all' => true], + Sylius\Bundle\OrderBundle\SyliusOrderBundle::class => ['all' => true], + Sylius\Bundle\MoneyBundle\SyliusMoneyBundle::class => ['all' => true], + Sylius\Bundle\CurrencyBundle\SyliusCurrencyBundle::class => ['all' => true], + Sylius\Bundle\LocaleBundle\SyliusLocaleBundle::class => ['all' => true], + Sylius\Bundle\ProductBundle\SyliusProductBundle::class => ['all' => true], + Sylius\Bundle\ChannelBundle\SyliusChannelBundle::class => ['all' => true], + Sylius\Bundle\AttributeBundle\SyliusAttributeBundle::class => ['all' => true], + Sylius\Bundle\TaxationBundle\SyliusTaxationBundle::class => ['all' => true], + Sylius\Bundle\ShippingBundle\SyliusShippingBundle::class => ['all' => true], + Sylius\Bundle\PaymentBundle\SyliusPaymentBundle::class => ['all' => true], + Sylius\Bundle\MailerBundle\SyliusMailerBundle::class => ['all' => true], + Sylius\Bundle\PromotionBundle\SyliusPromotionBundle::class => ['all' => true], + Sylius\Bundle\AddressingBundle\SyliusAddressingBundle::class => ['all' => true], + Sylius\Bundle\InventoryBundle\SyliusInventoryBundle::class => ['all' => true], + Sylius\Bundle\TaxonomyBundle\SyliusTaxonomyBundle::class => ['all' => true], + Sylius\Bundle\UserBundle\SyliusUserBundle::class => ['all' => true], + Sylius\Bundle\CustomerBundle\SyliusCustomerBundle::class => ['all' => true], + Sylius\Bundle\UiBundle\SyliusUiBundle::class => ['all' => true], + Sylius\Bundle\ReviewBundle\SyliusReviewBundle::class => ['all' => true], + Sylius\Bundle\CoreBundle\SyliusCoreBundle::class => ['all' => true], + Sylius\Bundle\ResourceBundle\SyliusResourceBundle::class => ['all' => true], + Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true], + winzou\Bundle\StateMachineBundle\winzouStateMachineBundle::class => ['all' => true], + Sonata\BlockBundle\SonataBlockBundle::class => ['all' => true], + Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle::class => ['all' => true], + JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true], + FOS\RestBundle\FOSRestBundle::class => ['all' => true], + Knp\Bundle\GaufretteBundle\KnpGaufretteBundle::class => ['all' => true], + Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true], + Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true], + Payum\Bundle\PayumBundle\PayumBundle::class => ['all' => true], + Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true], + BabDev\PagerfantaBundle\BabDevPagerfantaBundle::class => ['all' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Sylius\Bundle\FixturesBundle\SyliusFixturesBundle::class => ['all' => true], + Sylius\Bundle\PayumBundle\SyliusPayumBundle::class => ['all' => true], + Sylius\Bundle\ThemeBundle\SyliusThemeBundle::class => ['all' => true], + Sylius\Bundle\AdminBundle\SyliusAdminBundle::class => ['all' => true], + Sylius\Bundle\ShopBundle\SyliusShopBundle::class => ['all' => true], + Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], + Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], + Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], + FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle::class => ['test' => true, 'test_cached' => true], + Sylius\Behat\Application\SyliusTestPlugin\SyliusTestPlugin::class => ['test' => true, 'test_cached' => true], + ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], + Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], + Sylius\Bundle\ApiBundle\SyliusApiBundle::class => ['all' => true], + SyliusLabs\DoctrineMigrationsExtraBundle\SyliusLabsDoctrineMigrationsExtraBundle::class => ['all' => true], + Sylius\PayPalPlugin\SyliusPayPalPlugin::class => ['all' => true], + SyliusLabs\Polyfill\Symfony\Security\Bundle\SyliusLabsPolyfillSymfonySecurityBundle::class => ['all' => true], + League\FlysystemBundle\FlysystemBundle::class => ['all' => true], + Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], +]; diff --git a/config/jwt/.gitkeep b/config/jwt/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/config/jwt/private-test.pem b/config/jwt/private-test.pem new file mode 100644 index 0000000..d2ff3d0 --- /dev/null +++ b/config/jwt/private-test.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIhNMtc+21vO0CAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECJ3pCz5BZ5wBBIIEyKx/OW6jYrrN +ZfcQn40CON3st4lO16QGaY3nwhtMfS3M0VBQWRXjGSTrUU72H3PEhqtM7v4av1ED +Vf1hkIm2gGPb/qxctapG33aw0Ean1AhHtqVtiEN0C3tK8Jpx6ARYbFees1xkHd4R +lIkl715D2K9eqZCWK5sljChGWPK97Jm2zTudLQImvzLDJLDDDd8T7HamG/GvDROc +lzZeNEg3oO2DzYwu3yI3oHYORM7pWxaJr0hSe+147U/hHwRq7n0vWP3JnsJlmxoy +gpN/ZG8qh+MdWaEdg9NmfjQSZK/N4ckIN3y/5ZeDXFxr5sQkLJk/V0ZU1j2qe6cj +TG4DX3pAkNwPw0PrMdas0V9FwL9wIH/65uQg9HdlXQ5FoaaNk4i+OULhpkcQ9znn ++tArQcnEyHY+/ZC8flnnOGRiZLyjVf+L2zHp4eiEd+ftiT5uv6UAGtUYVd/ulSZm +4do66tFRij6D5gkeS7KvSY952Ueq/3XqhCmJNbs3Hv9V9pCfdE420m9ntEbziZiM +5YU+jrLcLe0B5WYZyX3koIWLD09GXC+JB0735q+o0RMYbVGHNIMh0y9PSBPNZj6X +3ke2pHzigPhU4iuCUdt/KZHFN8UyiJH7EPYXRSTbGRTilvwe7ULEwiAZgqEng4qy +UCpKlokZynI7q0uhE537hn/zafpqcjHrdrfuO9jRyQOLmDq1ockP842+QBxhCtDU +N3A0hm03slIgGFikr4NsRki8osweDHSg0LaWyGBklQY0QHPh/e9XURfiqKI4LpkJ +REr7Lo4S2J+D4jgnADnrRc+R7a6jiN/562e6B4JiVCt28m5qJCeiiUpErp07J/ks +cpQ1i3TUpDoFFivmKkcJfneHKiaPaNjjcwUJf1szVp0I/rQ8zfe2zxqVW6ARUULp +fD65fgZZsigkPEbk4eqgvbcqu7hLFddHzdgi4TXcI0QSrYx8JHJ6L9aaiUyHmiih +W1gJ2jtn087ssN+yQ81bbs8tf3t+Efj7gge4kn7nye9r62adEpwrB3syT2uSt3yr +qf/j8ycf6R8lvD0AZPQ0aLQu1hOKloduk5OkuPTZToHNuvvYR9wpyMhCQFOBGD1P +trXGcAATIKDF4skG5A5ia36TcD07X+Nqb5obukQmbj3dMuPe3C4u1tFdykz5B4I9 +PJgiChRQ5J5Qg4xWXZdzmsuRC2YZT1SIIATnZ6PRnIlovhjBCtGKRVNjtljRqoIA +opzPolaxCX6Cuo15zVO8HgGB4fPht+VD6Muann8cRBx7RCvR8QZhym/HVJxnu9OL +mt+hYNUGgt+Kx5CKeDB98Vq7YOKjt9r0ocwnB/RzwgzwlXRoJ/m0Ra1VOmOJzAss +Ib78x/tTt9C3YMzfGXHxNHy9XWU28xOW8SjghOgJFlW8JWRzjRQ0TYNtLYnw+i3B +UpOhcdKiORmRew5gtjJd09Fu59U/YiDjAcCyauzTny8mNaseKgIWSUUviAexhbJL +FsIjqjEI1OxdD9/mKdyEA2nk3AmjrPtY3exvaWtx5QFsQM+RSWxD3oZ0Ht0Wg3J1 +q5IW5YvyyjgGIVW2gtThpzUjsn68G9dPQ8fVdC99HY5aNwmZtX/uWZKx+cmbJQbP +q3yyvW3b+6iYFIse6P/4Hg== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/config/jwt/public-test.pem b/config/jwt/public-test.pem new file mode 100644 index 0000000..0635bfb --- /dev/null +++ b/config/jwt/public-test.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApehy09MSecsyPhR8Ylkb +WCzXZxSup/1TfAeOJEpQCm/D1bcJVwoUZFFgrWcVvwFtXOngSXwIq0jhTdQqS0No +aeMR/lIvYK6ZBnz1+c3UU/rV2BvG4gSc07tVjyuaPuD1NBSBtIR5NY2gz2SatL9A +ZfKMJBZhaVb1yMVbDfwa4WgQQ9rd7F/D2fqblPIPARaBzGbkKuMSXbb6kWurW2GJ +1O8SyyHAv47Gr3PaB7MZxNMgsxJPBbIh8RZvpUBOvzvq0aAWlXTxNYp9iV5liPUA +/aXhx+p4CqtD87BLJ+Iim/Vu6xBVom/+Yahl8yZsSIebQy2Y0JlSjhgQ27E5Q4zQ +lwIDAQAB +-----END PUBLIC KEY----- diff --git a/config/packages/_sylius.yaml b/config/packages/_sylius.yaml new file mode 100644 index 0000000..ce751d0 --- /dev/null +++ b/config/packages/_sylius.yaml @@ -0,0 +1,254 @@ +imports: + - { resource: "@SyliusCoreBundle/Resources/config/app/config.yml" } + + - { resource: "@SyliusAdminBundle/Resources/config/app/config.yml" } + - { resource: "@SyliusApiBundle/Resources/config/app/config.yaml" } + + - { resource: "@SyliusShopBundle/Resources/config/app/config.yml" } + - { resource: "@SyliusPayPalPlugin/Resources/config/config.yaml" } + +parameters: + sylius_core.public_dir: '%kernel.project_dir%/public' + +when@dev: + sylius_api: + enabled: true + +sylius_addressing: + resources: + address: + classes: + model: App\Entity\Addressing\Address + country: + classes: + model: App\Entity\Addressing\Country + province: + classes: + model: App\Entity\Addressing\Province + zone: + classes: + model: App\Entity\Addressing\Zone + zone_member: + classes: + model: App\Entity\Addressing\ZoneMember + +sylius_attribute: + resources: + product: + attribute: + classes: + model: App\Entity\Product\ProductAttribute + translation: + classes: + model: App\Entity\Product\ProductAttributeTranslation + attribute_value: + classes: + model: App\Entity\Product\ProductAttributeValue + +sylius_channel: + resources: + channel: + classes: + model: App\Entity\Channel\Channel +sylius_core: + resources: + product_image: + classes: + model: App\Entity\Product\ProductImage + taxon_image: + classes: + model: App\Entity\Taxonomy\TaxonImage + product_taxon: + classes: + model: App\Entity\Product\ProductTaxon + channel_pricing: + classes: + model: App\Entity\Channel\ChannelPricing + +sylius_currency: + resources: + currency: + classes: + model: App\Entity\Currency\Currency + exchange_rate: + classes: + model: App\Entity\Currency\ExchangeRate + +sylius_customer: + resources: + customer: + classes: + model: App\Entity\Customer\Customer + customer_group: + classes: + model: App\Entity\Customer\CustomerGroup + +sylius_locale: + resources: + locale: + classes: + model: App\Entity\Locale\Locale + +sylius_order: + resources: + order: + classes: + model: App\Entity\Order\Order + order_item: + classes: + model: App\Entity\Order\OrderItem + order_item_unit: + classes: + model: App\Entity\Order\OrderItemUnit + adjustment: + classes: + model: App\Entity\Order\Adjustment + order_sequence: + classes: + model: App\Entity\Order\OrderSequence + +sylius_payment: + resources: + payment_method: + classes: + model: App\Entity\Payment\PaymentMethod + translation: + classes: + model: App\Entity\Payment\PaymentMethodTranslation + payment: + classes: + model: App\Entity\Payment\Payment + +sylius_payum: + resources: + payment_security_token: + classes: + model: App\Entity\Payment\PaymentSecurityToken + gateway_config: + classes: + model: App\Entity\Payment\GatewayConfig + +sylius_product: + resources: + product: + classes: + model: App\Entity\Product\Product + translation: + classes: + model: App\Entity\Product\ProductTranslation + product_variant: + classes: + model: App\Entity\Product\ProductVariant + translation: + classes: + model: App\Entity\Product\ProductVariantTranslation + product_option: + classes: + model: App\Entity\Product\ProductOption + translation: + classes: + model: App\Entity\Product\ProductOptionTranslation + product_option_value: + classes: + model: App\Entity\Product\ProductOptionValue + translation: + classes: + model: App\Entity\Product\ProductOptionValueTranslation + product_association: + classes: + model: App\Entity\Product\ProductAssociation + product_association_type: + classes: + model: App\Entity\Product\ProductAssociationType + translation: + classes: + model: App\Entity\Product\ProductAssociationTypeTranslation + +sylius_promotion: + resources: + catalog_promotion: + classes: + model: App\Entity\Promotion\CatalogPromotion + catalog_promotion_action: + classes: + model: App\Entity\Promotion\CatalogPromotionAction + catalog_promotion_scope: + classes: + model: App\Entity\Promotion\CatalogPromotionScope + promotion: + classes: + model: App\Entity\Promotion\Promotion + promotion_rule: + classes: + model: App\Entity\Promotion\PromotionRule + promotion_action: + classes: + model: App\Entity\Promotion\PromotionAction + promotion_coupon: + classes: + model: App\Entity\Promotion\PromotionCoupon + +sylius_review: + resources: + product: + review: + classes: + model: App\Entity\Product\ProductReview + +sylius_shipping: + resources: + shipment: + classes: + model: App\Entity\Shipping\Shipment + shipping_method: + classes: + model: App\Entity\Shipping\ShippingMethod + translation: + classes: + model: App\Entity\Shipping\ShippingMethodTranslation + shipping_category: + classes: + model: App\Entity\Shipping\ShippingCategory + +sylius_taxation: + resources: + tax_category: + classes: + model: App\Entity\Taxation\TaxCategory + tax_rate: + classes: + model: App\Entity\Taxation\TaxRate + +sylius_taxonomy: + resources: + taxon: + classes: + model: App\Entity\Taxonomy\Taxon + translation: + classes: + model: App\Entity\Taxonomy\TaxonTranslation +sylius_user: + resources: + admin: + user: + classes: + model: App\Entity\User\AdminUser + shop: + user: + classes: + model: App\Entity\User\ShopUser + oauth: + user: + classes: + model: App\Entity\User\UserOAuth + +sylius_shop: + product_grid: + include_all_descendants: true + +sylius_theme: + sources: + filesystem: + scan_depth: 1 + directories: + - "%kernel.project_dir%/themes" diff --git a/config/packages/api_platform.yaml b/config/packages/api_platform.yaml new file mode 100644 index 0000000..b0351e5 --- /dev/null +++ b/config/packages/api_platform.yaml @@ -0,0 +1,9 @@ +api_platform: + mapping: + paths: + - '%kernel.project_dir%/config/api_platform' + - '%kernel.project_dir%/src/Entity' + patch_formats: + json: ['application/merge-patch+json'] + swagger: + versions: [3] diff --git a/config/packages/assets.yaml b/config/packages/assets.yaml new file mode 100644 index 0000000..5382769 --- /dev/null +++ b/config/packages/assets.yaml @@ -0,0 +1,11 @@ +framework: + assets: + packages: + admin: + json_manifest_path: '%kernel.project_dir%/public/build/admin/manifest.json' + shop: + json_manifest_path: '%kernel.project_dir%/public/build/shop/manifest.json' + app.admin: + json_manifest_path: '%kernel.project_dir%/public/build/app/admin/manifest.json' + app.shop: + json_manifest_path: '%kernel.project_dir%/public/build/app/shop/manifest.json' diff --git a/config/packages/dev/jms_serializer.yaml b/config/packages/dev/jms_serializer.yaml new file mode 100644 index 0000000..2f32a9b --- /dev/null +++ b/config/packages/dev/jms_serializer.yaml @@ -0,0 +1,12 @@ +jms_serializer: + visitors: + json_serialization: + options: + - JSON_PRETTY_PRINT + - JSON_UNESCAPED_SLASHES + - JSON_PRESERVE_ZERO_FRACTION + json_deserialization: + options: + - JSON_PRETTY_PRINT + - JSON_UNESCAPED_SLASHES + - JSON_PRESERVE_ZERO_FRACTION diff --git a/config/packages/dev/monolog.yaml b/config/packages/dev/monolog.yaml new file mode 100644 index 0000000..da2b092 --- /dev/null +++ b/config/packages/dev/monolog.yaml @@ -0,0 +1,9 @@ +monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + firephp: + type: firephp + level: info diff --git a/config/packages/dev/nelmio_alice.yaml b/config/packages/dev/nelmio_alice.yaml new file mode 100644 index 0000000..e2ae069 --- /dev/null +++ b/config/packages/dev/nelmio_alice.yaml @@ -0,0 +1,3 @@ +nelmio_alice: + functions_blacklist: + - 'current' diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml new file mode 100644 index 0000000..bd8c393 --- /dev/null +++ b/config/packages/doctrine.yaml @@ -0,0 +1,23 @@ +parameters: + # Adds a fallback DATABASE_URL if the env var is not set. + # This allows you to run cache:warmup even if your + # environment variables are not available yet. + # You should not need to change this value. + env(DATABASE_URL): '' + +doctrine: + dbal: + url: '%env(resolve:DATABASE_URL)%' + + orm: + auto_generate_proxy_classes: '%kernel.debug%' + entity_managers: + default: + auto_mapping: true + mappings: + App: + is_bundle: false + type: annotation + dir: '%kernel.project_dir%/src/Entity' + prefix: 'App\Entity' + alias: App diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml new file mode 100644 index 0000000..765b5c5 --- /dev/null +++ b/config/packages/doctrine_migrations.yaml @@ -0,0 +1,6 @@ +doctrine_migrations: + storage: + table_storage: + table_name: sylius_migrations + migrations_paths: + 'App\Migrations': "%kernel.project_dir%/src/Migrations" diff --git a/config/packages/flysystem.yaml b/config/packages/flysystem.yaml new file mode 100644 index 0000000..2447c23 --- /dev/null +++ b/config/packages/flysystem.yaml @@ -0,0 +1,6 @@ +flysystem: + storages: + sylius.storage: + adapter: 'local' + options: + directory: '%sylius_core.images_dir%' diff --git a/config/packages/fos_rest.yaml b/config/packages/fos_rest.yaml new file mode 100644 index 0000000..eaebb27 --- /dev/null +++ b/config/packages/fos_rest.yaml @@ -0,0 +1,11 @@ +fos_rest: + exception: true + view: + formats: + json: true + xml: true + empty_content: 204 + format_listener: + rules: + - { path: '^/api/v1/.*', priorities: ['json', 'xml'], fallback_format: json, prefer_extension: true } + - { path: '^/', stop: true } diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml new file mode 100644 index 0000000..2904743 --- /dev/null +++ b/config/packages/framework.yaml @@ -0,0 +1,24 @@ +framework: + translator: { fallbacks: ["%locale%"] } + secret: '%env(APP_SECRET)%' + form: + enabled: true + legacy_error_messages: false + csrf_protection: true + session: + handler_id: ~ + serializer: + mapping: + paths: [ '%kernel.project_dir%/config/serialization' ] + +when@dev: + framework: + profiler: { only_exceptions: false } + +when@test: &framework_test + framework: + test: true + session: + storage_factory_id: session.storage.factory.mock_file + +when@test_cached: *framework_test diff --git a/config/packages/jms_serializer.yaml b/config/packages/jms_serializer.yaml new file mode 100644 index 0000000..ed7bc61 --- /dev/null +++ b/config/packages/jms_serializer.yaml @@ -0,0 +1,4 @@ +jms_serializer: + visitors: + xml_serialization: + format_output: '%kernel.debug%' diff --git a/config/packages/lexik_jwt_authentication.yaml b/config/packages/lexik_jwt_authentication.yaml new file mode 100644 index 0000000..edfb69d --- /dev/null +++ b/config/packages/lexik_jwt_authentication.yaml @@ -0,0 +1,4 @@ +lexik_jwt_authentication: + secret_key: '%env(resolve:JWT_SECRET_KEY)%' + public_key: '%env(resolve:JWT_PUBLIC_KEY)%' + pass_phrase: '%env(JWT_PASSPHRASE)%' diff --git a/config/packages/liip_imagine.yaml b/config/packages/liip_imagine.yaml new file mode 100644 index 0000000..bb2e7ce --- /dev/null +++ b/config/packages/liip_imagine.yaml @@ -0,0 +1,6 @@ +liip_imagine: + resolvers: + default: + web_path: + web_root: "%kernel.project_dir%/public" + cache_prefix: "media/cache" diff --git a/config/packages/mailer.yaml b/config/packages/mailer.yaml new file mode 100644 index 0000000..7acef57 --- /dev/null +++ b/config/packages/mailer.yaml @@ -0,0 +1,12 @@ +framework: + mailer: + dsn: '%env(MAILER_DSN)%' + +when@test: &mailer_test + framework: + cache: + pools: + test.mailer_pool: + adapter: cache.adapter.filesystem + +when@test_cached: *mailer_test diff --git a/config/packages/prod/doctrine.yaml b/config/packages/prod/doctrine.yaml new file mode 100644 index 0000000..55ea750 --- /dev/null +++ b/config/packages/prod/doctrine.yaml @@ -0,0 +1,35 @@ +doctrine: + orm: + entity_managers: + default: + metadata_cache_driver: + type: service + id: doctrine.system_cache_provider + query_cache_driver: + type: service + id: doctrine.system_cache_provider + result_cache_driver: + type: service + id: doctrine.result_cache_provider + +services: + doctrine.result_cache_provider: + class: Doctrine\Common\Cache\Psr6\DoctrineProvider + public: false + factory: ['Doctrine\Common\Cache\Psr6\DoctrineProvider', 'wrap'] + arguments: + - '@doctrine.result_cache_pool' + doctrine.system_cache_provider: + class: Doctrine\Common\Cache\Psr6\DoctrineProvider + public: false + factory: [ 'Doctrine\Common\Cache\Psr6\DoctrineProvider', 'wrap' ] + arguments: + - '@doctrine.system_cache_pool' + +framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/config/packages/prod/jms_serializer.yaml b/config/packages/prod/jms_serializer.yaml new file mode 100644 index 0000000..c288182 --- /dev/null +++ b/config/packages/prod/jms_serializer.yaml @@ -0,0 +1,10 @@ +jms_serializer: + visitors: + json_serialization: + options: + - JSON_UNESCAPED_SLASHES + - JSON_PRESERVE_ZERO_FRACTION + json_deserialization: + options: + - JSON_UNESCAPED_SLASHES + - JSON_PRESERVE_ZERO_FRACTION diff --git a/config/packages/prod/monolog.yaml b/config/packages/prod/monolog.yaml new file mode 100644 index 0000000..6461211 --- /dev/null +++ b/config/packages/prod/monolog.yaml @@ -0,0 +1,10 @@ +monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + nested: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug diff --git a/config/packages/routing.yaml b/config/packages/routing.yaml new file mode 100644 index 0000000..4116679 --- /dev/null +++ b/config/packages/routing.yaml @@ -0,0 +1,3 @@ +framework: + router: + strict_requirements: true diff --git a/config/packages/security.yaml b/config/packages/security.yaml new file mode 100644 index 0000000..ed1698c --- /dev/null +++ b/config/packages/security.yaml @@ -0,0 +1,121 @@ +security: + enable_authenticator_manager: true + providers: + sylius_admin_user_provider: + id: sylius.admin_user_provider.email_or_name_based + sylius_api_admin_user_provider: + id: sylius.admin_user_provider.email_or_name_based + sylius_shop_user_provider: + id: sylius.shop_user_provider.email_or_name_based + sylius_api_shop_user_provider: + id: sylius.shop_user_provider.email_or_name_based + password_hashers: + Sylius\Component\User\Model\UserInterface: argon2i + firewalls: + admin: + switch_user: true + context: admin + pattern: "%sylius.security.admin_regex%" + provider: sylius_admin_user_provider + form_login: + provider: sylius_admin_user_provider + login_path: sylius_admin_login + check_path: sylius_admin_login_check + failure_path: sylius_admin_login + default_target_path: sylius_admin_dashboard + use_forward: false + use_referer: true + enable_csrf: true + csrf_parameter: _csrf_admin_security_token + csrf_token_id: admin_authenticate + remember_me: + secret: "%env(APP_SECRET)%" + path: "/%sylius_admin.path_name%" + name: APP_ADMIN_REMEMBER_ME + lifetime: 31536000 + remember_me_parameter: _remember_me + logout: + path: sylius_admin_logout + target: sylius_admin_login + + new_api_admin_user: + pattern: "%sylius.security.new_api_admin_regex%/.*" + provider: sylius_api_admin_user_provider + stateless: true + entry_point: jwt + json_login: + check_path: "%sylius.security.new_api_admin_route%/authentication-token" + username_path: email + password_path: password + success_handler: lexik_jwt_authentication.handler.authentication_success + failure_handler: lexik_jwt_authentication.handler.authentication_failure + jwt: true + + new_api_shop_user: + pattern: "%sylius.security.new_api_shop_regex%/.*" + provider: sylius_api_shop_user_provider + stateless: true + entry_point: jwt + json_login: + check_path: "%sylius.security.new_api_shop_route%/authentication-token" + username_path: email + password_path: password + success_handler: lexik_jwt_authentication.handler.authentication_success + failure_handler: lexik_jwt_authentication.handler.authentication_failure + jwt: true + + shop: + switch_user: { role: ROLE_ALLOWED_TO_SWITCH } + context: shop + pattern: "%sylius.security.shop_regex%" + provider: sylius_shop_user_provider + form_login: + success_handler: sylius.authentication.success_handler + failure_handler: sylius.authentication.failure_handler + provider: sylius_shop_user_provider + login_path: sylius_shop_login + check_path: sylius_shop_login_check + failure_path: sylius_shop_login + default_target_path: sylius_shop_homepage + use_forward: false + use_referer: true + enable_csrf: true + csrf_parameter: _csrf_shop_security_token + csrf_token_id: shop_authenticate + remember_me: + secret: "%env(APP_SECRET)%" + name: APP_SHOP_REMEMBER_ME + lifetime: 31536000 + remember_me_parameter: _remember_me + logout: + path: sylius_shop_logout + target: sylius_shop_homepage + invalidate_session: false + + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + + access_control: + - { path: "%sylius.security.admin_regex%/_partial", role: PUBLIC_ACCESS, ips: [127.0.0.1, ::1] } + - { path: "%sylius.security.admin_regex%/_partial", role: ROLE_NO_ACCESS } + - { path: "%sylius.security.shop_regex%/_partial", role: PUBLIC_ACCESS, ips: [127.0.0.1, ::1] } + - { path: "%sylius.security.shop_regex%/_partial", role: ROLE_NO_ACCESS } + + - { path: "%sylius.security.admin_regex%/forgotten-password", role: PUBLIC_ACCESS } + + - { path: "%sylius.security.admin_regex%/login", role: PUBLIC_ACCESS } + - { path: "%sylius.security.shop_regex%/login", role: PUBLIC_ACCESS } + + - { path: "%sylius.security.shop_regex%/register", role: PUBLIC_ACCESS } + - { path: "%sylius.security.shop_regex%/verify", role: PUBLIC_ACCESS } + + - { path: "%sylius.security.admin_regex%", role: ROLE_ADMINISTRATION_ACCESS } + - { path: "%sylius.security.shop_regex%/account", role: ROLE_USER } + + - { path: "%sylius.security.new_api_admin_route%/reset-password-requests", role: PUBLIC_ACCESS } + - { path: "%sylius.security.new_api_admin_regex%/.*", role: ROLE_API_ACCESS } + - { path: "%sylius.security.new_api_admin_route%/authentication-token", role: PUBLIC_ACCESS } + - { path: "%sylius.security.new_api_user_account_regex%/.*", role: ROLE_USER } + - { path: "%sylius.security.new_api_shop_route%/authentication-token", role: PUBLIC_ACCESS } + - { path: "%sylius.security.new_api_shop_regex%/.*", role: PUBLIC_ACCESS } diff --git a/config/packages/stof_doctrine_extensions.yaml b/config/packages/stof_doctrine_extensions.yaml new file mode 100644 index 0000000..7770f74 --- /dev/null +++ b/config/packages/stof_doctrine_extensions.yaml @@ -0,0 +1,4 @@ +# Read the documentation: https://symfony.com/doc/current/bundles/StofDoctrineExtensionsBundle/index.html +# See the official DoctrineExtensions documentation for more details: https://github.com/Atlantic18/DoctrineExtensions/tree/master/doc/ +stof_doctrine_extensions: + default_locale: '%locale%' diff --git a/config/packages/sylius_labs_doctrine_migrations_extra.yaml b/config/packages/sylius_labs_doctrine_migrations_extra.yaml new file mode 100644 index 0000000..3150dd9 --- /dev/null +++ b/config/packages/sylius_labs_doctrine_migrations_extra.yaml @@ -0,0 +1,3 @@ +sylius_labs_doctrine_migrations_extra: + migrations: + 'App\Migrations': ~ diff --git a/config/packages/test/fidry_alice_data_fixtures.yaml b/config/packages/test/fidry_alice_data_fixtures.yaml new file mode 100644 index 0000000..ae4e694 --- /dev/null +++ b/config/packages/test/fidry_alice_data_fixtures.yaml @@ -0,0 +1,2 @@ +fidry_alice_data_fixtures: + default_purge_mode: no_purge diff --git a/config/packages/test/monolog.yaml b/config/packages/test/monolog.yaml new file mode 100644 index 0000000..7e2b9e3 --- /dev/null +++ b/config/packages/test/monolog.yaml @@ -0,0 +1,6 @@ +monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: error diff --git a/config/packages/test/nelmio_alice.yaml b/config/packages/test/nelmio_alice.yaml new file mode 100644 index 0000000..caec543 --- /dev/null +++ b/config/packages/test/nelmio_alice.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: ../dev/nelmio_alice.yaml } diff --git a/config/packages/test/security.yaml b/config/packages/test/security.yaml new file mode 100644 index 0000000..4071d31 --- /dev/null +++ b/config/packages/test/security.yaml @@ -0,0 +1,6 @@ +security: + password_hashers: + Sylius\Component\User\Model\UserInterface: + algorithm: argon2i + time_cost: 3 + memory_cost: 10 diff --git a/config/packages/test/sylius_theme.yaml b/config/packages/test/sylius_theme.yaml new file mode 100644 index 0000000..4d34199 --- /dev/null +++ b/config/packages/test/sylius_theme.yaml @@ -0,0 +1,3 @@ +sylius_theme: + sources: + test: ~ diff --git a/config/packages/test/sylius_uploader.yaml b/config/packages/test/sylius_uploader.yaml new file mode 100644 index 0000000..ab9d6ca --- /dev/null +++ b/config/packages/test/sylius_uploader.yaml @@ -0,0 +1,3 @@ +services: + Sylius\Component\Core\Generator\ImagePathGeneratorInterface: + class: Sylius\Behat\Service\Generator\UploadedImagePathGenerator diff --git a/config/packages/test_cached/doctrine.yaml b/config/packages/test_cached/doctrine.yaml new file mode 100644 index 0000000..55ea750 --- /dev/null +++ b/config/packages/test_cached/doctrine.yaml @@ -0,0 +1,35 @@ +doctrine: + orm: + entity_managers: + default: + metadata_cache_driver: + type: service + id: doctrine.system_cache_provider + query_cache_driver: + type: service + id: doctrine.system_cache_provider + result_cache_driver: + type: service + id: doctrine.result_cache_provider + +services: + doctrine.result_cache_provider: + class: Doctrine\Common\Cache\Psr6\DoctrineProvider + public: false + factory: ['Doctrine\Common\Cache\Psr6\DoctrineProvider', 'wrap'] + arguments: + - '@doctrine.result_cache_pool' + doctrine.system_cache_provider: + class: Doctrine\Common\Cache\Psr6\DoctrineProvider + public: false + factory: [ 'Doctrine\Common\Cache\Psr6\DoctrineProvider', 'wrap' ] + arguments: + - '@doctrine.system_cache_pool' + +framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/config/packages/test_cached/fidry_alice_data_fixtures.yaml b/config/packages/test_cached/fidry_alice_data_fixtures.yaml new file mode 100644 index 0000000..f5c8649 --- /dev/null +++ b/config/packages/test_cached/fidry_alice_data_fixtures.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: "../test/fidry_alice_data_fixtures.yaml" } diff --git a/config/packages/test_cached/fos_rest.yaml b/config/packages/test_cached/fos_rest.yaml new file mode 100644 index 0000000..2b4189d --- /dev/null +++ b/config/packages/test_cached/fos_rest.yaml @@ -0,0 +1,3 @@ +fos_rest: + exception: + debug: true diff --git a/config/packages/test_cached/monolog.yaml b/config/packages/test_cached/monolog.yaml new file mode 100644 index 0000000..71bef59 --- /dev/null +++ b/config/packages/test_cached/monolog.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: "../test/monolog.yaml" } diff --git a/config/packages/test_cached/security.yaml b/config/packages/test_cached/security.yaml new file mode 100644 index 0000000..f487c5a --- /dev/null +++ b/config/packages/test_cached/security.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: '../test/security.yaml' } diff --git a/config/packages/test_cached/sylius_channel.yaml b/config/packages/test_cached/sylius_channel.yaml new file mode 100644 index 0000000..bab83ef --- /dev/null +++ b/config/packages/test_cached/sylius_channel.yaml @@ -0,0 +1,2 @@ +sylius_channel: + debug: true diff --git a/config/packages/test_cached/sylius_theme.yaml b/config/packages/test_cached/sylius_theme.yaml new file mode 100644 index 0000000..9fb4c94 --- /dev/null +++ b/config/packages/test_cached/sylius_theme.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: "../test/sylius_theme.yaml" } diff --git a/config/packages/test_cached/sylius_uploader.yaml b/config/packages/test_cached/sylius_uploader.yaml new file mode 100644 index 0000000..cfa727e --- /dev/null +++ b/config/packages/test_cached/sylius_uploader.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: "../test/sylius_uploader.yaml" } diff --git a/config/packages/translation.yaml b/config/packages/translation.yaml new file mode 100644 index 0000000..1f4f966 --- /dev/null +++ b/config/packages/translation.yaml @@ -0,0 +1,8 @@ +framework: + default_locale: '%locale%' + translator: + paths: + - '%kernel.project_dir%/translations' + fallbacks: + - '%locale%' + - 'en' diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml new file mode 100644 index 0000000..18af2f4 --- /dev/null +++ b/config/packages/twig.yaml @@ -0,0 +1,16 @@ +twig: + paths: ['%kernel.project_dir%/templates'] + debug: '%kernel.debug%' + strict_variables: '%kernel.debug%' + +services: + _defaults: + public: false + autowire: true + autoconfigure: true + + Twig\Extra\Intl\IntlExtension: ~ + +when@test_cached: + twig: + strict_variables: true diff --git a/config/packages/validator.yaml b/config/packages/validator.yaml new file mode 100644 index 0000000..61807db --- /dev/null +++ b/config/packages/validator.yaml @@ -0,0 +1,3 @@ +framework: + validation: + enable_annotations: true diff --git a/config/packages/web_profiler.yaml b/config/packages/web_profiler.yaml new file mode 100644 index 0000000..7732441 --- /dev/null +++ b/config/packages/web_profiler.yaml @@ -0,0 +1,14 @@ +when@dev: + web_profiler: + toolbar: true + intercept_redirects: false + +when@test: &web_profiler_test + web_profiler: + toolbar: false + intercept_redirects: false + + framework: + profiler: { collect: false } + +when@test_cached: *web_profiler_test diff --git a/config/packages/webpack_encore.yaml b/config/packages/webpack_encore.yaml new file mode 100644 index 0000000..fe1b0b7 --- /dev/null +++ b/config/packages/webpack_encore.yaml @@ -0,0 +1,7 @@ +webpack_encore: + output_path: '%kernel.project_dir%/public/build/default' + builds: + admin: '%kernel.project_dir%/public/build/admin' + shop: '%kernel.project_dir%/public/build/shop' + app.admin: '%kernel.project_dir%/public/build/app/admin' + app.shop: '%kernel.project_dir%/public/build/app/shop' diff --git a/config/preload.php b/config/preload.php new file mode 100644 index 0000000..5ebcdb2 --- /dev/null +++ b/config/preload.php @@ -0,0 +1,5 @@ +get() won't work + public: false + + _instanceof: + Sylius\Bundle\ResourceBundle\Controller\ResourceController: + autowire: false + Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType: + autowire: false + + # Makes classes in src/ available to be used as services; + # this creates a service per class whose id is the fully-qualified class name + App\: + resource: '../src/*' + exclude: '../src/{Entity,Migrations,Tests,Kernel.php}' + + # Controllers are imported separately to make sure services can be injected + # as action arguments even if you don't extend any base controller class + App\Controller\: + resource: '../src/Controller' + tags: ['controller.service_arguments'] diff --git a/config/services_test.yaml b/config/services_test.yaml new file mode 100644 index 0000000..c02bef9 --- /dev/null +++ b/config/services_test.yaml @@ -0,0 +1,5 @@ +imports: + - { resource: "../vendor/sylius/sylius/src/Sylius/Behat/Resources/config/services.xml" } + +sylius_api: + enabled: true diff --git a/config/services_test_cached.yaml b/config/services_test_cached.yaml new file mode 100644 index 0000000..0de380e --- /dev/null +++ b/config/services_test_cached.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: "services_test.yaml" } diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..02d5b87 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,118 @@ +services: + php: + container_name: php + build: + context: . + target: sylius_php_prod + depends_on: + - migrations + environment: + APP_DEBUG: 0 + APP_ENV: prod + APP_SECRET: EDITME + DATABASE_URL: mysql://sylius:${MYSQL_PASSWORD}@mysql/sylius_prod + MAILER_URL: smtp://localhost + MESSENGER_TRANSPORT_DSN: doctrine://default + SYLIUS_MESSENGER_TRANSPORT_MAIN_DSN: doctrine://default + SYLIUS_MESSENGER_TRANSPORT_MAIN_FAILED_DSN: doctrine://default?queue_name=main_failed + SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_DSN: doctrine://default?queue_name=catalog_promotion_removal + SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_FAILED_DSN: doctrine://default?queue_name=catalog_promotion_removal_failed + PHP_DATE_TIMEZONE: ${PHP_DATE_TIMEZONE:-UTC} + volumes: + # use a bind-mounted host directory, as we want to keep the sessions + - ./var/sessions:/srv/sylius/var/sessions:rw + # use a bind-mounted host directory, as we want to keep the media + - ./public/media:/srv/sylius/public/media:rw + networks: + - sylius + + cron: + container_name: cron + build: + context: . + target: sylius_cron + depends_on: + - migrations + environment: + APP_ENV: prod + APP_DEBUG: 0 + APP_SECRET: EDITME + DATABASE_URL: mysql://sylius:${MYSQL_PASSWORD}@mysql/sylius_prod + PHP_DATE_TIMEZONE: ${PHP_DATE_TIMEZONE:-UTC} + networks: + - sylius + + worker: + container_name: worker + command: ["php", "bin/console", "messenger:consume", "main", "catalog_promotion_removal", "--limit=5", "--memory-limit=256M", "--time-limit=600"] + restart: always + build: + context: . + target: sylius_php_prod + depends_on: + - migrations + environment: + APP_ENV: prod + APP_DEBUG: 0 + APP_SECRET: EDITME + DATABASE_URL: mysql://sylius:${MYSQL_PASSWORD}@mysql/sylius_prod + MESSENGER_TRANSPORT_DSN: doctrine://default + SYLIUS_MESSENGER_TRANSPORT_MAIN_DSN: doctrine://default + SYLIUS_MESSENGER_TRANSPORT_MAIN_FAILED_DSN: doctrine://default?queue_name=main_failed + SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_DSN: doctrine://default?queue_name=catalog_promotion_removal + SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_FAILED_DSN: doctrine://default?queue_name=catalog_promotion_removal_failed + PHP_DATE_TIMEZONE: ${PHP_DATE_TIMEZONE:-UTC} + networks: + - sylius + + migrations: + container_name: migrations + build: + context: . + target: sylius_migrations_prod + depends_on: + - mysql + environment: + APP_ENV: prod + APP_DEBUG: 0 + APP_SECRET: EDITME + DATABASE_URL: mysql://sylius:${MYSQL_PASSWORD}@mysql/sylius_prod + LOAD_FIXTURES: ${LOAD_FIXTURES:-0} + PHP_DATE_TIMEZONE: ${PHP_DATE_TIMEZONE:-UTC} + networks: + - sylius + + mysql: + container_name: mysql + # in production, we may want to use a managed database service + image: mysql:5.7 # Sylius is fully working on mysql 8.0 version + environment: + MYSQL_RANDOM_ROOT_PASSWORD: true + MYSQL_DATABASE: sylius_prod + MYSQL_USER: sylius + MYSQL_PASSWORD: ${MYSQL_PASSWORD:?MYSQL_PASSWORD is not set or empty} + volumes: + # use a bind-mounted host directory, because we never want to lose our data! + - ./docker/mysql/data:/var/lib/mysql:rw,delegated + networks: + - sylius + + nginx: + container_name: nginx + # in production, we may want to use a static website hosting service + build: + context: . + target: sylius_nginx + depends_on: + - php + volumes: + # use a bind-mounted host directory, as we want to keep the media + - ./public/media:/srv/sylius/public/media:ro + networks: + - sylius + ports: + - 80:80 + +networks: + sylius: + driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ddcdec2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,104 @@ +services: + php: + container_name: php + build: + context: . + target: sylius_php_dev + depends_on: + - migrations + environment: + - APP_ENV=dev + - APP_DEBUG=1 + - APP_SECRET=EDITME + - DATABASE_URL=mysql://sylius:${MYSQL_PASSWORD:-nopassword}@mysql/sylius + - MAILER_DSN=smtp://mailhog:1025 + - PHP_DATE_TIMEZONE=${PHP_DATE_TIMEZONE:-UTC} + volumes: + - .:/srv/sylius:rw,cached + # if you develop on Linux, you may use a bind-mounted host directory instead + # - ./var:/srv/sylius/var:rw + - ./public:/srv/sylius/public:rw,delegated + # if you develop on Linux, you may use a bind-mounted host directory instead + # - ./public/media:/srv/sylius/public/media:rw + - public-media:/srv/sylius/public/media:rw + + migrations: + container_name: migrations + build: + context: . + target: sylius_migrations_dev + depends_on: + - mysql + environment: + - APP_ENV=dev + - APP_DEBUG=1 + - APP_SECRET=EDITME + - DATABASE_URL=mysql://sylius:${MYSQL_PASSWORD:-nopassword}@mysql/sylius + - LOAD_FIXTURES=1 + - PHP_DATE_TIMEZONE=${PHP_DATE_TIMEZONE:-UTC} + + mysql: + container_name: mysql + image: mysql:5.7 # Sylius is fully working on mysql 8.0 version + platform: linux/amd64 + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-nopassword} + - MYSQL_DATABASE=sylius + - MYSQL_USER=sylius + - MYSQL_PASSWORD=${MYSQL_PASSWORD:-nopassword} + volumes: + - mysql-data:/var/lib/mysql:rw + # you may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data! + # - ./docker/mysql/data:/var/lib/mysql:rw,delegated + ports: + - "${MYSQL_PORT:-3306}:3306" + cap_add: + - SYS_NICE # prevent "mbind: Operation not permitted" errors + + node: + container_name: node + build: + context: . + target: sylius_node + command: ["yarn", "watch"] + depends_on: + - php + environment: + - GULP_ENV=dev + - PHP_HOST=php + - PHP_PORT=9000 + volumes: + - .:/srv/sylius:rw,cached + - ./public:/srv/sylius/public:rw,delegated + ports: + - "${NODE_PORT:-35729}:35729" + + nginx: + container_name: nginx + build: + context: . + target: sylius_nginx + depends_on: + - php + - node # to ensure correct build order + volumes: + - ./public:/srv/sylius/public:ro + # if you develop on Linux, you may use a bind-mounted host directory instead + # - ./public/media:/srv/sylius/public/media:ro + - public-media:/srv/sylius/public/media:ro,nocopy + ports: + - "${HTTP_PORT:-80}:80" + + mailhog: + # do not use in production! + image: mailhog/mailhog:latest + environment: + - MH_STORAGE=maildir + # volumes: + # - ./docker/mailhog/maildir:/maildir:rw,delegated + ports: + - "${MAILHOG_PORT:-8025}:8025" + +volumes: + mysql-data: + public-media: diff --git a/docker/cron/crontab b/docker/cron/crontab new file mode 100644 index 0000000..c8fe77b --- /dev/null +++ b/docker/cron/crontab @@ -0,0 +1,2 @@ +* * * * * php /srv/sylius/bin/console sylius:remove-expired-carts +* * * * * php /srv/sylius/bin/console sylius:cancel-unpaid-orders diff --git a/docker/cron/docker-entrypoint.sh b/docker/cron/docker-entrypoint.sh new file mode 100755 index 0000000..360a4f9 --- /dev/null +++ b/docker/cron/docker-entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +while ping -c1 migrations >/dev/null 2>&1; +do + (>&2 echo "Waiting for Migrations container to finish") + sleep 1; +done; + +(>&2 echo "Migrations container finished. Starting Cron process.") + +exec docker-php-entrypoint "$@" diff --git a/docker/migrations/docker-entrypoint.sh b/docker/migrations/docker-entrypoint.sh new file mode 100755 index 0000000..6f3311c --- /dev/null +++ b/docker/migrations/docker-entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -e + +attempt_left=20 + +until php bin/console doctrine:query:sql "select 1" >/dev/null 2>&1; +do + attempt_left=$((attempt_left-1)) + + if [ "${attempt_left}" -eq "0" ]; then + + (>&2 echo "MySQL did not answer. Aborting migrations.") + exit 1 + else + (>&2 echo "Waiting for MySQL to be ready...") + fi + + sleep 1 +done + +php bin/console doctrine:migrations:migrate --no-interaction + +if [ "$LOAD_FIXTURES" = "1" ]; then + php bin/console sylius:fixtures:load --no-interaction +fi diff --git a/docker/nginx/conf.d/default.conf b/docker/nginx/conf.d/default.conf new file mode 100644 index 0000000..c2565c7 --- /dev/null +++ b/docker/nginx/conf.d/default.conf @@ -0,0 +1,43 @@ +server { + root /srv/sylius/public; + listen *:80; + + location / { + # try to serve file directly, fallback to index.php + try_files $uri /index.php$is_args$args; + } + + location ~ ^/index\.php(/|$) { + resolver 127.0.0.11 valid=10s ipv6=off; + set $backendfpm "php:9000"; + # Comment the next line and uncomment the next to enable dynamic resolution (incompatible with Kubernetes); + fastcgi_pass $backendfpm; + #resolver 127.0.0.11; + #set $upstream_host php; + #fastcgi_pass $upstream_host:9000; + + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + # When you are using symlinks to link the document root to the + # current version of your application, you should pass the real + # application path instead of the path to the symlink to PHP + # FPM. + # Otherwise, PHP's OPcache may not properly detect changes to + # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126 + # for more information). + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + # Prevents URIs that include the front controller. This will 404: + # http://domain.tld/index.php/some-path + # Remove the internal directive to allow URIs like this + internal; + } + + # return 404 for all other php files not matching the front controller + # this prevents access to other php files you don't want to be accessible. + location ~ \.php$ { + return 404; + } + + client_max_body_size 6m; +} diff --git a/docker/node/docker-entrypoint.sh b/docker/node/docker-entrypoint.sh new file mode 100755 index 0000000..ecd73af --- /dev/null +++ b/docker/node/docker-entrypoint.sh @@ -0,0 +1,18 @@ +#!/bin/sh +set -e + +# first arg is `-f` or `--some-option` +if [ "${1#-}" != "$1" ]; then + set -- node "$@" +fi + +if [ "$1" = 'node' ] || [ "$1" = 'yarn' ]; then + yarn install + + >&2 echo "Waiting for PHP to be ready..." + until nc -z "$PHP_HOST" "$PHP_PORT"; do + sleep 1 + done +fi + +exec "$@" diff --git a/docker/php/dev/opcache.ini b/docker/php/dev/opcache.ini new file mode 100644 index 0000000..b6a356a --- /dev/null +++ b/docker/php/dev/opcache.ini @@ -0,0 +1,10 @@ +[opcache] +opcache.enable=1 +opcache.enable_cli=1 +opcache.memory_consumption=256 +opcache.max_accelerated_files=20000 +opcache.validate_timestamps=1 +opcache.revalidate_freq=0 +opcache.jit=1255 +opcache.jit_buffer_size=128M +opcache.interned_strings_buffer=16 diff --git a/docker/php/dev/php.ini b/docker/php/dev/php.ini new file mode 100644 index 0000000..fc1acf9 --- /dev/null +++ b/docker/php/dev/php.ini @@ -0,0 +1,7 @@ +memory_limit=3G +post_max_size=6M +upload_max_filesize=5M +realpath_cache_size=4096K +realpath_cache_ttl=600 + +date.timezone=${PHP_DATE_TIMEZONE} diff --git a/docker/php/docker-entrypoint.sh b/docker/php/docker-entrypoint.sh new file mode 100755 index 0000000..54b400a --- /dev/null +++ b/docker/php/docker-entrypoint.sh @@ -0,0 +1,27 @@ +#!/bin/sh +set -e + +# first arg is `-f` or `--some-option` +if [ "${1#-}" != "$1" ]; then + set -- php-fpm "$@" +fi + +if [ "$1" = 'php-fpm' ] || [ "$1" = 'bin/console' ]; then + mkdir -p var/cache var/log var/sessions public/media + setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var public/media + setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var public/media + + if [ "$APP_ENV" != 'prod' ]; then + composer install --prefer-dist --no-progress --no-interaction + bin/console assets:install --no-interaction + bin/console sylius:theme:assets:install public --no-interaction + fi + + while ping -c1 migrations >/dev/null 2>&1; + do + (>&2 echo "Waiting for Migrations container to finish") + sleep 1; + done; +fi + +exec docker-php-entrypoint "$@" diff --git a/docker/php/prod/opcache.ini b/docker/php/prod/opcache.ini new file mode 100644 index 0000000..58be9e0 --- /dev/null +++ b/docker/php/prod/opcache.ini @@ -0,0 +1,9 @@ +[opcache] +opcache.enable=1 +opcache.enable_cli=1 +opcache.memory_consumption=256 +opcache.max_accelerated_files=20000 +opcache.validate_timestamps=0 +opcache.jit=1255 +opcache.jit_buffer_size=128M +opcache.interned_strings_buffer=16 diff --git a/docker/php/prod/php.ini b/docker/php/prod/php.ini new file mode 100644 index 0000000..31170a7 --- /dev/null +++ b/docker/php/prod/php.ini @@ -0,0 +1,7 @@ +memory_limit=256M +post_max_size=6M +upload_max_filesize=5M +realpath_cache_size=4096K +realpath_cache_ttl=600 + +date.timezone=${PHP_DATE_TIMEZONE} diff --git a/docker/test.sh b/docker/test.sh new file mode 100755 index 0000000..29dddcb --- /dev/null +++ b/docker/test.sh @@ -0,0 +1,24 @@ +#!/bin/sh +set -e + +readonly timeout=100 +readonly sleep_time=5 + +i=1 +time=$((timeout * sleep_time)) + +until curl -L --fail http://localhost:80 2>/dev/null +do + i=$((i+1)) + + if [ "${i}" -gt "${timeout}" ]; then + + echo "Sylius Store was never created, aborting due to ${time}s timeout!" + curl -L http://localhost:80 -H Accept:application/json + exit 1 + else + echo "Sylius Store did not response" + fi + + sleep $sleep_time +done diff --git a/ecs.php b/ecs.php new file mode 100644 index 0000000..8bf3677 --- /dev/null +++ b/ecs.php @@ -0,0 +1,18 @@ +import('vendor/sylius-labs/coding-standard/ecs.php'); + $config->paths(['src']); + + $config->skip([ + VisibilityRequiredFixer::class => ['*Spec.php'], + ]); + + $config->ruleWithConfiguration(BinaryOperatorSpacesFixer::class, []); + $config->ruleWithConfiguration(PhpdocSeparationFixer::class, ['groups' => [['ORM\\*']]]); +}; diff --git a/etc/build/.gitignore b/etc/build/.gitignore new file mode 100755 index 0000000..e69de29 diff --git a/features/.gitignore b/features/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/gulpfile.babel.js b/gulpfile.babel.js new file mode 100644 index 0000000..6a3c4e4 --- /dev/null +++ b/gulpfile.babel.js @@ -0,0 +1,63 @@ +import chug from 'gulp-chug'; +import gulp from 'gulp'; +import yargs from 'yargs'; + +const { argv } = yargs + .options({ + rootPath: { + description: ' path to web assets directory', + type: 'string', + requiresArg: true, + required: false, + }, + nodeModulesPath: { + description: ' path to node_modules directory', + type: 'string', + requiresArg: true, + required: false, + }, + }); + +const config = [ + '--rootPath', + argv.rootPath || '../../../../../../../public/assets', + '--nodeModulesPath', + argv.nodeModulesPath || '../../../../../../../node_modules', +]; + +export const buildAdmin = function buildAdmin() { + return gulp.src('vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle/gulpfile.babel.js', { read: false }) + .pipe(chug({ args: config, tasks: 'build' })); +}; +buildAdmin.description = 'Build admin assets.'; + +export const watchAdmin = function watchAdmin() { + return gulp.src('vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle/gulpfile.babel.js', { read: false }) + .pipe(chug({ args: config, tasks: 'watch' })); +}; +watchAdmin.description = 'Watch admin asset sources and rebuild on changes.'; + +export const buildShop = function buildShop() { + return gulp.src('vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle/gulpfile.babel.js', { read: false }) + .pipe(chug({ args: config, tasks: 'build' })); +}; +buildShop.description = 'Build shop assets.'; + +export const watchShop = function watchShop() { + return gulp.src('vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle/gulpfile.babel.js', { read: false }) + .pipe(chug({ args: config, tasks: 'watch' })); +}; +watchShop.description = 'Watch shop asset sources and rebuild on changes.'; + +export const build = gulp.parallel(buildAdmin, buildShop); +build.description = 'Build assets.'; + +export const watch = gulp.series(watchAdmin, watchShop); +watch.description = 'Watch asset sources and rebuild on changes.'; + +gulp.task('admin', buildAdmin); +gulp.task('admin-watch', watchAdmin); +gulp.task('shop', buildShop); +gulp.task('shop-watch', watchShop); + +export default build; diff --git a/package.json b/package.json new file mode 100644 index 0000000..dfe3258 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "license": "MIT", + "scripts": { + "build": "encore dev", + "build:prod": "encore production", + "postinstall": "semantic-ui-css-patch", + "lint": "yarn lint:js", + "watch": "encore dev --watch" + }, + "devDependencies": { + "@sylius-ui/frontend": "^1.0" + } +} diff --git a/phpspec.yaml.dist b/phpspec.yaml.dist new file mode 100644 index 0000000..8189080 --- /dev/null +++ b/phpspec.yaml.dist @@ -0,0 +1,6 @@ +suites: + app: + namespace: App + psr4_prefix: App + src_path: src/ + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..15423ce --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,3 @@ +parameters: + ignoreErrors: + - '/Generator expects value type Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface\, object given\./' diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..9d856d9 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,13 @@ + + + + + + tests + + + diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..6d02fc2 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,73 @@ +# Use the front controller as index file. It serves as a fallback solution when +# every other rewrite/redirect fails (e.g. in an aliased environment without +# mod_rewrite). Additionally, this reduces the matching process for the +# start page (path "/") because otherwise Apache will apply the rewriting rules +# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl). +DirectoryIndex index.php + +# By default, Apache does not evaluate symbolic links if you did not enable this +# feature in your server configuration. Uncomment the following line if you +# install assets as symlinks or if you experience problems related to symlinks +# when compiling LESS/Sass/CoffeScript assets. +# Options FollowSymlinks + +# Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve +# to the front controller "/index.php" but be rewritten to "/index.php/index". + + Options -MultiViews + + + + RewriteEngine On + + # Determine the RewriteBase automatically and set it as environment variable. + # If you are using Apache aliases to do mass virtual hosting or installed the + # project in a subdirectory, the base path will be prepended to allow proper + # resolution of the index.php file and to redirect to the correct URI. It will + # work in environments without path prefix as well, providing a safe, one-size + # fits all solution. But as you do not need it in this case, you can comment + # the following 2 lines to eliminate the overhead. + RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$ + RewriteRule ^(.*) - [E=BASE:%1] + + # Sets the HTTP_AUTHORIZATION header removed by Apache + RewriteCond %{HTTP:Authorization} . + RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Redirect to URI without front controller to prevent duplicate content + # (with and without `/index.php`). Only do this redirect on the initial + # rewrite by Apache and not on subsequent cycles. Otherwise we would get an + # endless redirect loop (request -> rewrite to front controller -> + # redirect -> request -> ...). + # So in case you get a "too many redirects" error or you always get redirected + # to the start page because your Apache does not expose the REDIRECT_STATUS + # environment variable, you have 2 choices: + # - disable this feature by commenting the following 2 lines or + # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the + # following RewriteCond (best solution) + RewriteCond %{ENV:REDIRECT_STATUS} ^$ + RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L] + + # If the requested filename exists, simply serve it. + # We only want to let Apache serve files and not directories. + RewriteCond %{REQUEST_FILENAME} -f + RewriteRule ^ - [L] + + # Rewrite all other queries to the front controller. + RewriteRule ^ %{ENV:BASE}/index.php [L] + + + + + # When mod_rewrite is not available, we instruct a temporary redirect of + # the start page to the front controller explicitly so that the website + # and the generated links can still be used. + RedirectMatch 307 ^/$ /index.php/ + # RedirectTemp cannot be used instead + + + + + # Prevent clickjacking + Header set X-Frame-Options SAMEORIGIN + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..592f7a8 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..9982c21 --- /dev/null +++ b/public/index.php @@ -0,0 +1,9 @@ +importNames(); + $rectorConfig->import(__DIR__ . '/vendor/sylius/sylius-rector/config/config.php'); + $rectorConfig->paths([ + __DIR__ . '/src' + ]); +}; diff --git a/src/Controller/.gitignore b/src/Controller/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/Entity/.gitignore b/src/Entity/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/Entity/Addressing/Address.php b/src/Entity/Addressing/Address.php new file mode 100644 index 0000000..c78e862 --- /dev/null +++ b/src/Entity/Addressing/Address.php @@ -0,0 +1,18 @@ +getProjectDir() . '/var/cache/' . $this->environment; + } + + public function getLogDir(): string + { + return $this->getProjectDir() . '/var/log'; + } + + public function registerBundles(): iterable + { + $contents = require $this->getProjectDir() . '/config/bundles.php'; + foreach ($contents as $class => $envs) { + if (isset($envs['all']) || isset($envs[$this->environment])) { + yield new $class(); + } + } + } + + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void + { + $container->addResource(new FileResource($this->getProjectDir() . '/config/bundles.php')); + $container->setParameter('container.dumper.inline_class_loader', true); + $confDir = $this->getProjectDir() . '/config'; + + $loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{packages}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{services}' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{services}_' . $this->environment . self::CONFIG_EXTS, 'glob'); + } + + protected function getContainerBaseClass(): string + { + if ($this->isTestEnvironment() && class_exists(MockerContainer::class)) { + return MockerContainer::class; + } + + return parent::getContainerBaseClass(); + } + + private function isTestEnvironment(): bool + { + return 0 === strpos($this->getEnvironment(), 'test'); + } +} diff --git a/src/Migrations/.gitignore b/src/Migrations/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/symfony.lock b/symfony.lock new file mode 100644 index 0000000..38466de --- /dev/null +++ b/symfony.lock @@ -0,0 +1,882 @@ +{ + "aeon-php/calendar": { + "version": "0.16.4" + }, + "alcohol/iso4217": { + "version": "4.0.0" + }, + "api-platform/core": { + "version": "2.5", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "2.5", + "ref": "a93061567140e386f107be75340ac2aee3f86cbf" + }, + "files": [ + "config/packages/api_platform.yaml", + "config/routes/api_platform.yaml", + "src/Entity/.gitignore" + ] + }, + "babdev/pagerfanta-bundle": { + "version": "v2.8.0" + }, + "behat/behat": { + "version": "v3.5.0" + }, + "behat/gherkin": { + "version": "v4.5.1" + }, + "behat/mink-selenium2-driver": { + "version": "v1.3.1" + }, + "behat/transliterator": { + "version": "v1.2.0" + }, + "clue/stream-filter": { + "version": "v1.4.0" + }, + "coduo/php-matcher": { + "version": "3.1.0" + }, + "coduo/php-to-string": { + "version": "2.0.1" + }, + "dealerdirect/phpcodesniffer-composer-installer": { + "version": "v0.7.1" + }, + "dmore/behat-chrome-extension": { + "version": "1.3.0" + }, + "dmore/chrome-mink-driver": { + "version": "2.7.0" + }, + "doctrine/annotations": { + "version": "1.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.0", + "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672" + } + }, + "doctrine/cache": { + "version": "v1.8.0" + }, + "doctrine/collections": { + "version": "v1.5.0" + }, + "doctrine/common": { + "version": "v2.9.0" + }, + "doctrine/data-fixtures": { + "version": "v1.3.1" + }, + "doctrine/dbal": { + "version": "v2.8.0" + }, + "doctrine/deprecations": { + "version": "v0.5.3" + }, + "doctrine/doctrine-bundle": { + "version": "1.6", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.6", + "ref": "ae205d5114e719deb64d2110f56ef910787d1e04" + } + }, + "doctrine/doctrine-migrations-bundle": { + "version": "1.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.2", + "ref": "c1431086fec31f17fbcfe6d6d7e92059458facc1" + } + }, + "doctrine/event-manager": { + "version": "v1.0.0" + }, + "doctrine/inflector": { + "version": "v1.3.0" + }, + "doctrine/instantiator": { + "version": "1.1.0" + }, + "doctrine/lexer": { + "version": "v1.0.1" + }, + "doctrine/migrations": { + "version": "v1.8.1" + }, + "doctrine/orm": { + "version": "v2.6.2" + }, + "doctrine/persistence": { + "version": "v1.0.0" + }, + "doctrine/sql-formatter": { + "version": "1.1.1" + }, + "egulias/email-validator": { + "version": "2.1.5" + }, + "enshrined/svg-sanitize": { + "version": "0.15.4" + }, + "fakerphp/faker": { + "version": "v1.12.0" + }, + "fig/link-util": { + "version": "1.1.1" + }, + "friends-of-behat/mink": { + "version": "v1.8.0" + }, + "friends-of-behat/mink-browserkit-driver": { + "version": "v1.4.0" + }, + "friends-of-behat/mink-debug-extension": { + "version": "v2.0.1" + }, + "friends-of-behat/mink-extension": { + "version": "v2.5.0" + }, + "friends-of-behat/page-object-extension": { + "version": "0.1" + }, + "friends-of-behat/suite-settings-extension": { + "version": "v1.0.1" + }, + "friends-of-behat/symfony-extension": { + "version": "v1.2.2" + }, + "friends-of-behat/variadic-extension": { + "version": "v1.1.0" + }, + "friendsofphp/proxy-manager-lts": { + "version": "v1.0.3" + }, + "friendsofsymfony/rest-bundle": { + "version": "2.2", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "2.2", + "ref": "258300d52be6ad59b32a888d5ddafbf9638540ff" + } + }, + "gedmo/doctrine-extensions": { + "version": "v2.4.36" + }, + "guzzlehttp/guzzle": { + "version": "6.3.3" + }, + "guzzlehttp/promises": { + "version": "v1.3.1" + }, + "guzzlehttp/psr7": { + "version": "1.4.2" + }, + "hamcrest/hamcrest-php": { + "version": "v2.0.0" + }, + "imagine/imagine": { + "version": "v0.7.1" + }, + "instaclick/php-webdriver": { + "version": "1.4.5" + }, + "jms/metadata": { + "version": "1.6.0" + }, + "jms/serializer": { + "version": "1.13.0" + }, + "jms/serializer-bundle": { + "version": "2.0", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "2.0", + "ref": "fe60ce509ef04a3f40da96e3979bc8d9b13b2372" + } + }, + "knplabs/gaufrette": { + "version": "v0.6.0" + }, + "knplabs/knp-gaufrette-bundle": { + "version": "v0.5.3" + }, + "knplabs/knp-menu": { + "version": "2.3.0" + }, + "knplabs/knp-menu-bundle": { + "version": "v2.2.1" + }, + "laminas/laminas-code": { + "version": "3.4.1" + }, + "laminas/laminas-stdlib": { + "version": "3.3.1" + }, + "lchrusciel/api-test-case": { + "version": "v3.1.3" + }, + "lcobucci/clock": { + "version": "2.0.0" + }, + "lcobucci/jwt": { + "version": "3.3.2" + }, + "league/flysystem-bundle": { + "version": "2.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "913dc3d7a5a1af0d2b044c5ac3a16e2f851d7380" + }, + "files": [ + "config/packages/flysystem.yaml", + "var/storage/.gitignore" + ] + }, + "league/uri": { + "version": "5.3.0" + }, + "league/uri-components": { + "version": "1.8.1" + }, + "league/uri-interfaces": { + "version": "1.1.0" + }, + "lexik/jwt-authentication-bundle": { + "version": "2.5", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "2.5", + "ref": "5b2157bcd5778166a5696e42f552ad36529a07a6" + }, + "files": [ + "config/packages/lexik_jwt_authentication.yaml" + ] + }, + "liip/imagine-bundle": { + "version": "1.8", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "1.8", + "ref": "7f6676627c1ceeeee204553d24a0545d5f918b7b" + } + }, + "marcj/topsort": { + "version": "1.1.0" + }, + "mockery/mockery": { + "version": "1.1.0" + }, + "monolog/monolog": { + "version": "1.23.0" + }, + "myclabs/deep-copy": { + "version": "1.8.1" + }, + "namshi/jose": { + "version": "7.2.3" + }, + "nelmio/alice": { + "version": "3.2", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "3.2", + "ref": "5ef2976310e8f9621c1a722a73bfbe115c1559a3" + } + }, + "openlss/lib-array2xml": { + "version": "0.0.10" + }, + "pagerfanta/pagerfanta": { + "version": "v2.0.1" + }, + "payum/iso4217": { + "version": "1.0.1" + }, + "payum/payum": { + "version": "1.5.0" + }, + "payum/payum-bundle": { + "version": "2.3.1" + }, + "phar-io/manifest": { + "version": "1.0.1" + }, + "phar-io/version": { + "version": "1.0.1" + }, + "php-http/guzzle6-adapter": { + "version": "v1.1.1" + }, + "php-http/httplug": { + "version": "v1.1.0" + }, + "php-http/message": { + "version": "1.7.0" + }, + "php-http/message-factory": { + "version": "v1.0.2" + }, + "php-http/promise": { + "version": "v1.0.0" + }, + "phpdocumentor/reflection-common": { + "version": "1.0.1" + }, + "phpdocumentor/reflection-docblock": { + "version": "4.3.0" + }, + "phpdocumentor/type-resolver": { + "version": "0.4.0" + }, + "phpseclib/phpseclib": { + "version": "2.0.30" + }, + "phpspec/php-diff": { + "version": "v1.1.0" + }, + "phpspec/phpspec": { + "version": "4.3.1" + }, + "phpspec/prophecy": { + "version": "1.8.0" + }, + "phpstan/extension-installer": { + "version": "1.0.1" + }, + "phpstan/phpdoc-parser": { + "version": "0.3" + }, + "phpstan/phpstan": { + "version": "0.12.3" + }, + "phpstan/phpstan-doctrine": { + "version": "0.11.5" + }, + "phpstan/phpstan-webmozart-assert": { + "version": "0.12.8" + }, + "phpunit/php-code-coverage": { + "version": "5.3.2" + }, + "phpunit/php-file-iterator": { + "version": "1.4.5" + }, + "phpunit/php-text-template": { + "version": "1.2.1" + }, + "phpunit/php-timer": { + "version": "1.0.9" + }, + "phpunit/php-token-stream": { + "version": "2.0.2" + }, + "phpunit/phpunit": { + "version": "4.7", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.7", + "ref": "c276fa48d4713de91eb410289b3b1834acb7e403" + } + }, + "polishsymfonycommunity/symfony-mocker-container": { + "version": "v1.0.2" + }, + "psr/cache": { + "version": "1.0.1" + }, + "psr/container": { + "version": "1.0.0" + }, + "psr/event-dispatcher": { + "version": "1.0.0" + }, + "psr/http-client": { + "version": "1.0.0" + }, + "psr/http-message": { + "version": "1.0.1" + }, + "psr/link": { + "version": "1.0.0" + }, + "psr/log": { + "version": "1.0.2" + }, + "ralouphie/getallheaders": { + "version": "2.0.5" + }, + "ramsey/uuid": { + "version": "3.8.0" + }, + "sebastian/code-unit-reverse-lookup": { + "version": "1.0.1" + }, + "sebastian/comparator": { + "version": "2.1.3" + }, + "sebastian/diff": { + "version": "2.0.1" + }, + "sebastian/environment": { + "version": "3.1.0" + }, + "sebastian/exporter": { + "version": "3.1.0" + }, + "sebastian/global-state": { + "version": "2.0.0" + }, + "sebastian/object-enumerator": { + "version": "3.0.3" + }, + "sebastian/object-reflector": { + "version": "1.1.1" + }, + "sebastian/recursion-context": { + "version": "3.0.0" + }, + "sebastian/resource-operations": { + "version": "1.0.0" + }, + "sebastian/type": { + "version": "1.1.3" + }, + "sebastian/version": { + "version": "2.0.1" + }, + "slevomat/coding-standard": { + "version": "6.4.1" + }, + "sonata-project/block-bundle": { + "version": "3.12.1" + }, + "sonata-project/cache": { + "version": "2.0.1" + }, + "sonata-project/doctrine-extensions": { + "version": "1.1.0" + }, + "sonata-project/form-extensions": { + "version": "1.0.0" + }, + "sonata-project/twig-extensions": { + "version": "1.1.1" + }, + "squizlabs/php_codesniffer": { + "version": "3.3.1" + }, + "stella-maris/clock": { + "version": "0.1.4" + }, + "stof/doctrine-extensions-bundle": { + "version": "1.2", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "1.2", + "ref": "6c1ceb662f8997085f739cd089bfbef67f245983" + } + }, + "stripe/stripe-php": { + "version": "v6.28.1" + }, + "sylius-labs/association-hydrator": { + "version": "v1.1.0" + }, + "sylius-labs/coding-standard": { + "version": "v2.0.0" + }, + "sylius-labs/doctrine-migrations-extra-bundle": { + "version": "v0.1.3" + }, + "sylius-labs/polyfill-symfony-event-dispatcher": { + "version": "v1.0.0" + }, + "sylius-labs/polyfill-symfony-framework-bundle": { + "version": "v1.0.0" + }, + "sylius-labs/polyfill-symfony-security": { + "version": "v1.0.0" + }, + "sylius/calendar": { + "version": "v0.3.0" + }, + "sylius/fixtures-bundle": { + "version": "v1.4.1" + }, + "sylius/grid-bundle": { + "version": "v1.5.1" + }, + "sylius/mailer-bundle": { + "version": "v1.4.4" + }, + "sylius/paypal-plugin": { + "version": "v1.0.1" + }, + "sylius/registry": { + "version": "v1.4.1" + }, + "sylius/resource-bundle": { + "version": "v1.4.4" + }, + "sylius/sylius": { + "version": "v1.3.6" + }, + "sylius/theme-bundle": { + "version": "v1.4.6" + }, + "symfony/amqp-messenger": { + "version": "v5.2.1" + }, + "symfony/asset": { + "version": "v4.1.3" + }, + "symfony/browser-kit": { + "version": "v4.1.3" + }, + "symfony/cache": { + "version": "v4.1.3" + }, + "symfony/cache-contracts": { + "version": "v1.1.5" + }, + "symfony/config": { + "version": "v4.1.3" + }, + "symfony/console": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "e3868d2f4a5104f19f844fe551099a00c6562527" + } + }, + "symfony/css-selector": { + "version": "v4.1.3" + }, + "symfony/debug-bundle": { + "version": "4.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.1", + "ref": "f8863cbad2f2e58c4b65fa1eac892ab189971bea" + } + }, + "symfony/dependency-injection": { + "version": "v4.1.3" + }, + "symfony/deprecation-contracts": { + "version": "v2.2.0" + }, + "symfony/doctrine-bridge": { + "version": "v4.1.3" + }, + "symfony/doctrine-messenger": { + "version": "v5.2.1" + }, + "symfony/dom-crawler": { + "version": "v4.1.3" + }, + "symfony/dotenv": { + "version": "v4.1.3" + }, + "symfony/error-handler": { + "version": "v4.4.18" + }, + "symfony/event-dispatcher": { + "version": "v4.1.3" + }, + "symfony/event-dispatcher-contracts": { + "version": "v1.1.5" + }, + "symfony/expression-language": { + "version": "v4.1.3" + }, + "symfony/filesystem": { + "version": "v4.1.3" + }, + "symfony/finder": { + "version": "v4.1.3" + }, + "symfony/flex": { + "version": "1.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.0", + "ref": "e921bdbfe20cdefa3b82f379d1cd36df1bc8d115" + } + }, + "symfony/form": { + "version": "v4.1.3" + }, + "symfony/framework-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "87c585d24de9f43bca80ebcfd5cf5cb39445d95f" + } + }, + "symfony/http-foundation": { + "version": "v4.1.3" + }, + "symfony/http-kernel": { + "version": "v4.1.3" + }, + "symfony/intl": { + "version": "v4.1.3" + }, + "symfony/mailer": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "4.3", + "ref": "97a61eabb351d7f6cb7702039bcfe07fe9d7e03c" + }, + "files": [ + "config/packages/mailer.yaml" + ] + }, + "symfony/messenger": { + "version": "4.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.3", + "ref": "8a2675c061737658bed85102e9241c752620e575" + }, + "files": [ + "config/packages/messenger.yaml" + ] + }, + "symfony/mime": { + "version": "v4.3.1" + }, + "symfony/monolog-bridge": { + "version": "v4.1.3" + }, + "symfony/monolog-bundle": { + "version": "3.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.1", + "ref": "18ebf5a940573a20de06f9c4060101eeb438cf3d" + } + }, + "symfony/options-resolver": { + "version": "v4.1.3" + }, + "symfony/password-hasher": { + "version": "v5.3.2" + }, + "symfony/polyfill-mbstring": { + "version": "v1.9.0" + }, + "symfony/polyfill-php81": { + "version": "v1.23.0" + }, + "symfony/process": { + "version": "v4.1.3" + }, + "symfony/property-access": { + "version": "v4.1.3" + }, + "symfony/property-info": { + "version": "v5.1.2" + }, + "symfony/proxy-manager-bridge": { + "version": "v4.1.3" + }, + "symfony/redis-messenger": { + "version": "v5.2.1" + }, + "symfony/routing": { + "version": "4.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.0", + "ref": "cda8b550123383d25827705d05a42acf6819fe4e" + } + }, + "symfony/security-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527" + } + }, + "symfony/security-core": { + "version": "v4.4.18" + }, + "symfony/security-csrf": { + "version": "v5.2.1" + }, + "symfony/security-guard": { + "version": "v4.4.18" + }, + "symfony/security-http": { + "version": "v4.4.18" + }, + "symfony/serializer": { + "version": "v5.1.2" + }, + "symfony/service-contracts": { + "version": "v1.1.6" + }, + "symfony/stopwatch": { + "version": "v4.1.3" + }, + "symfony/string": { + "version": "v5.2.1" + }, + "symfony/templating": { + "version": "v4.1.3" + }, + "symfony/thanks": { + "version": "v1.0.8" + }, + "symfony/translation": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "6bcd6c570c017ea6ae5a7a6a027c929fd3542cd8" + } + }, + "symfony/translation-contracts": { + "version": "v1.1.6" + }, + "symfony/twig-bridge": { + "version": "v4.1.3" + }, + "symfony/twig-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "f75ac166398e107796ca94cc57fa1edaa06ec47f" + } + }, + "symfony/validator": { + "version": "4.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.1", + "ref": "0cdc982334f45d554957a6167e030482795bf9d7" + } + }, + "symfony/var-dumper": { + "version": "v4.1.3" + }, + "symfony/var-exporter": { + "version": "v4.2.1" + }, + "symfony/web-link": { + "version": "v5.1.2" + }, + "symfony/web-profiler-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6" + } + }, + "symfony/webpack-encore-bundle": { + "version": "1.15", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.10", + "ref": "51fec8b86251b9bfc126ebc1827c9a02fa81ee81" + }, + "files": [ + "assets/app.js", + "assets/bootstrap.js", + "assets/controllers.json", + "assets/controllers/hello_controller.js", + "assets/styles/app.css", + "config/packages/webpack_encore.yaml", + "package.json", + "webpack.config.js" + ] + }, + "symfony/yaml": { + "version": "v4.1.3" + }, + "symplify/easy-coding-standard": { + "version": "v4.6.1" + }, + "textalk/websocket": { + "version": "1.3.1" + }, + "theofidry/alice-data-fixtures": { + "version": "1.0", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "1.0", + "ref": "fe5a50faf580eb58f08ada2abe8afbd2d4941e05" + } + }, + "theseer/tokenizer": { + "version": "1.1.0" + }, + "twig/intl-extra": { + "version": "v2.12.5" + }, + "twig/twig": { + "version": "v2.5.0" + }, + "webmozart/assert": { + "version": "1.3.0" + }, + "willdurand/hateoas": { + "version": "2.12.0" + }, + "willdurand/hateoas-bundle": { + "version": "1.4.0" + }, + "willdurand/jsonp-callback-validator": { + "version": "v1.1.0" + }, + "willdurand/negotiation": { + "version": "v2.3.1" + }, + "winzou/state-machine": { + "version": "0.3.3" + }, + "winzou/state-machine-bundle": { + "version": "v0.3.1" + } +} diff --git a/templates/.gitignore b/templates/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/templates/bundles/SyliusAdminBundle/Order/Show/_payment.html.twig b/templates/bundles/SyliusAdminBundle/Order/Show/_payment.html.twig new file mode 100644 index 0000000..39165ed --- /dev/null +++ b/templates/bundles/SyliusAdminBundle/Order/Show/_payment.html.twig @@ -0,0 +1,46 @@ +{% import "@SyliusAdmin/Common/Macro/money.html.twig" as money %} +{% import '@SyliusUi/Macro/labels.html.twig' as label %} + +
+
+ {% include '@SyliusAdmin/Common/Label/paymentState.html.twig' with {'data': payment.state} %} +
+ +
+
+ {{ payment.method }} +
+
+ {{ money.format(payment.amount, payment.order.currencyCode) }} +
+
+ {% if sm_can(payment, 'complete', 'sylius_payment') %} +
+
+ + + +
+
+ {% endif %} + {% if sm_can(payment, 'refund', 'sylius_payment') %} +
+
+ + + +
+
+ {% endif %} + {% if + payment.method.gatewayConfig.factoryName == 'sylius.pay_pal' and + payment.state == 'refunded' + %} +
+ +
+

{{ 'sylius.pay_pal.tender_type'|trans }}

+
+
+ {% endif %} +
diff --git a/templates/bundles/SyliusAdminBundle/PaymentMethod/Gateways/paymentGateways.html.twig b/templates/bundles/SyliusAdminBundle/PaymentMethod/Gateways/paymentGateways.html.twig new file mode 100644 index 0000000..ea0e1d4 --- /dev/null +++ b/templates/bundles/SyliusAdminBundle/PaymentMethod/Gateways/paymentGateways.html.twig @@ -0,0 +1,5 @@ +{% for name, gateway in gatewayFactories %} + + {{ gateway|trans }} + +{% endfor %} diff --git a/templates/bundles/SyliusAdminBundle/_scripts.html.twig b/templates/bundles/SyliusAdminBundle/_scripts.html.twig new file mode 100644 index 0000000..033a791 --- /dev/null +++ b/templates/bundles/SyliusAdminBundle/_scripts.html.twig @@ -0,0 +1,2 @@ +{{ encore_entry_script_tags('admin-entry', null, 'admin') }} +{{ encore_entry_script_tags('app-admin-entry', null, 'app.admin') }} diff --git a/templates/bundles/SyliusAdminBundle/_styles.html.twig b/templates/bundles/SyliusAdminBundle/_styles.html.twig new file mode 100644 index 0000000..663dced --- /dev/null +++ b/templates/bundles/SyliusAdminBundle/_styles.html.twig @@ -0,0 +1,2 @@ +{{ encore_entry_link_tags('admin-entry', null, 'admin') }} +{{ encore_entry_link_tags('app-admin-entry', null, 'app.admin') }} diff --git a/templates/bundles/SyliusShopBundle/Checkout/SelectPayment/_choice.html.twig b/templates/bundles/SyliusShopBundle/Checkout/SelectPayment/_choice.html.twig new file mode 100644 index 0000000..2c84123 --- /dev/null +++ b/templates/bundles/SyliusShopBundle/Checkout/SelectPayment/_choice.html.twig @@ -0,0 +1,18 @@ +
+
+
+ {{ form_widget(form, sylius_test_form_attribute('payment-method-select')) }} +
+
+
+ {{ form_label(form, null, {'label_attr': {'data-test-payment-method-label': ''}}) }} + {% if method.description is not null %} +
+

{{ method.description }}

+
+ {% endif %} + {% if method.gatewayConfig.factoryName == 'sylius.pay_pal' %} + {{ render(controller('Sylius\\PayPalPlugin\\Controller\\PayPalButtonsController::renderPaymentPageButtonsAction', {'orderId': order.id})) }} + {% endif %} +
+
diff --git a/templates/bundles/SyliusShopBundle/Common/Order/_addresses.html.twig b/templates/bundles/SyliusShopBundle/Common/Order/_addresses.html.twig new file mode 100644 index 0000000..6d7ee9f --- /dev/null +++ b/templates/bundles/SyliusShopBundle/Common/Order/_addresses.html.twig @@ -0,0 +1,23 @@ +
+
+
+
{{ 'sylius.ui.billing_address'|trans }}
+ {% include '@SyliusShop/Common/_address.html.twig' with {'address': order.billingAddress} %} +
+ {% if order.isShippingRequired() %} +
+
{{ 'sylius.ui.shipping_address'|trans }}
+ {% include '@SyliusShop/Common/_address.html.twig' with {'address': order.shippingAddress} %} +
+ {% endif %} +
+
+{% if sylius_is_billing_address_missing(order) %} +
+ +
+
{{ 'sylius.pay_pal.missing_billing_address_header'|trans }}
+

{{ 'sylius.pay_pal.missing_billing_address_content'|trans }}

+
+
+{% endif %} diff --git a/templates/bundles/SyliusShopBundle/Common/Order/_payments.html.twig b/templates/bundles/SyliusShopBundle/Common/Order/_payments.html.twig new file mode 100644 index 0000000..1591a7d --- /dev/null +++ b/templates/bundles/SyliusShopBundle/Common/Order/_payments.html.twig @@ -0,0 +1,29 @@ +{% import "@SyliusShop/Common/Macro/money.html.twig" as money %} + +{% set state = order.paymentState %} + +{% if state != 'cart' %} + {% include "@SyliusShop/Common/Order/Label/PaymentState/orderPaymentState.html.twig" %} +{% endif %} + +{% for payment in order.payments %} + {% set state = payment.state %} + +
+ +
+
+ {{ payment.method }} +
+

{{ money.format(payment.amount, payment.currencyCode) }}

+ {% if payment.amount != payment.order.total and state == 'processing' %} + {{ 'sylius.pay_pal.different_amount'|trans }} + {% endif %} + {% if state != 'cart' %} +

+ {% include "@SyliusShop/Common/Order/Label/PaymentState/singlePaymentState.html.twig" with { 'state': state } %} +

+ {% endif %} +
+
+{% endfor %} diff --git a/templates/bundles/SyliusShopBundle/Order/thankYou.html.twig b/templates/bundles/SyliusShopBundle/Order/thankYou.html.twig new file mode 100644 index 0000000..3c29c3a --- /dev/null +++ b/templates/bundles/SyliusShopBundle/Order/thankYou.html.twig @@ -0,0 +1,40 @@ +{% extends '@SyliusShop/layout.html.twig' %} + +{% block content %} + +
+
+

+ {% set lastPayment = order.payments.last() %} + +
+ {{ 'sylius.ui.thank_you'|trans }} +
{{ 'sylius.ui.placed_an_order'|trans }}
+
+

+ + {{ sylius_template_event('sylius.shop.order.thank_you.after_message', {'order': order}) }} + + {% if lastPayment != false %} + {% if lastPayment.method.instructions is not null %} +
+ {{ lastPayment.method.instructions }} +
+ {% endif %} + + {% endif %} + + {% if order.customer.user is not null %} + {{ 'sylius.ui.view_order'|trans }} + {% else %} + {% if lastPayment.state != 'completed' %} + {{ 'sylius.ui.change_payment_method'|trans }} + {% endif %} + + + {{ 'sylius.ui.create_an_account'|trans }} + + {% endif %} +
+
+{% endblock %} diff --git a/templates/bundles/SyliusShopBundle/_scripts.html.twig b/templates/bundles/SyliusShopBundle/_scripts.html.twig new file mode 100644 index 0000000..67f721b --- /dev/null +++ b/templates/bundles/SyliusShopBundle/_scripts.html.twig @@ -0,0 +1,2 @@ +{{ encore_entry_script_tags('shop-entry', null, 'shop') }} +{{ encore_entry_script_tags('app-shop-entry', null, 'app.shop') }} diff --git a/templates/bundles/SyliusShopBundle/_styles.html.twig b/templates/bundles/SyliusShopBundle/_styles.html.twig new file mode 100644 index 0000000..783ef09 --- /dev/null +++ b/templates/bundles/SyliusShopBundle/_styles.html.twig @@ -0,0 +1,2 @@ +{{ encore_entry_link_tags('shop-entry', null, 'shop') }} +{{ encore_entry_link_tags('app-shop-entry', null, 'app.shop') }} diff --git a/templates/bundles/TwigBundle/Exception/error.html.twig b/templates/bundles/TwigBundle/Exception/error.html.twig new file mode 100644 index 0000000..f1ee1a4 --- /dev/null +++ b/templates/bundles/TwigBundle/Exception/error.html.twig @@ -0,0 +1 @@ +{% include '@SyliusShop/error.html.twig' %} diff --git a/templates/bundles/TwigBundle/Exception/error404.html.twig b/templates/bundles/TwigBundle/Exception/error404.html.twig new file mode 100644 index 0000000..adcff81 --- /dev/null +++ b/templates/bundles/TwigBundle/Exception/error404.html.twig @@ -0,0 +1 @@ +{% include '@SyliusShop/error404.html.twig' %} diff --git a/templates/bundles/TwigBundle/Exception/error500.html.twig b/templates/bundles/TwigBundle/Exception/error500.html.twig new file mode 100644 index 0000000..c7c1d66 --- /dev/null +++ b/templates/bundles/TwigBundle/Exception/error500.html.twig @@ -0,0 +1 @@ +{% include '@SyliusShop/error500.html.twig' %} diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/themes/.gitignore b/themes/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/translations/.gitignore b/translations/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..e1a473d --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,89 @@ +const path = require('path'); +const Encore = require('@symfony/webpack-encore'); + +const syliusBundles = path.resolve(__dirname, 'vendor/sylius/sylius/src/Sylius/Bundle/'); +const uiBundleScripts = path.resolve(syliusBundles, 'UiBundle/Resources/private/js/'); +const uiBundleResources = path.resolve(syliusBundles, 'UiBundle/Resources/private/'); + +// Shop config +Encore + .setOutputPath('public/build/shop/') + .setPublicPath('/build/shop') + .addEntry('shop-entry', './vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle/Resources/private/entry.js') + .disableSingleRuntimeChunk() + .cleanupOutputBeforeBuild() + .enableSourceMaps(!Encore.isProduction()) + .enableVersioning(Encore.isProduction()) + .enableSassLoader(); + +const shopConfig = Encore.getWebpackConfig(); + +shopConfig.resolve.alias['sylius/ui'] = uiBundleScripts; +shopConfig.resolve.alias['sylius/ui-resources'] = uiBundleResources; +shopConfig.resolve.alias['sylius/bundle'] = syliusBundles; +shopConfig.name = 'shop'; + +Encore.reset(); + +// Admin config +Encore + .setOutputPath('public/build/admin/') + .setPublicPath('/build/admin') + .addEntry('admin-entry', './vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle/Resources/private/entry.js') + .disableSingleRuntimeChunk() + .cleanupOutputBeforeBuild() + .enableSourceMaps(!Encore.isProduction()) + .enableVersioning(Encore.isProduction()) + .enableSassLoader(); + +const adminConfig = Encore.getWebpackConfig(); + +adminConfig.resolve.alias['sylius/ui'] = uiBundleScripts; +adminConfig.resolve.alias['sylius/ui-resources'] = uiBundleResources; +adminConfig.resolve.alias['sylius/bundle'] = syliusBundles; +adminConfig.externals = Object.assign({}, adminConfig.externals, { window: 'window', document: 'document' }); +adminConfig.name = 'admin'; + +Encore.reset(); + +// App shop config +Encore + .setOutputPath('public/build/app/shop') + .setPublicPath('/build/app/shop') + .addEntry('app-shop-entry', './assets/shop/entry.js') + .disableSingleRuntimeChunk() + .cleanupOutputBeforeBuild() + .enableSourceMaps(!Encore.isProduction()) + .enableVersioning(Encore.isProduction()) + .enableSassLoader(); + +const appShopConfig = Encore.getWebpackConfig(); + +appShopConfig.resolve.alias['sylius/ui'] = uiBundleScripts; +appShopConfig.resolve.alias['sylius/ui-resources'] = uiBundleResources; +appShopConfig.resolve.alias['sylius/bundle'] = syliusBundles; +appShopConfig.externals = Object.assign({}, appShopConfig.externals, { window: 'window', document: 'document' }); +appShopConfig.name = 'app.shop'; + +Encore.reset(); + +// App admin config +Encore + .setOutputPath('public/build/app/admin') + .setPublicPath('/build/app/admin') + .addEntry('app-admin-entry', './assets/admin/entry.js') + .disableSingleRuntimeChunk() + .cleanupOutputBeforeBuild() + .enableSourceMaps(!Encore.isProduction()) + .enableVersioning(Encore.isProduction()) + .enableSassLoader(); + +const appAdminConfig = Encore.getWebpackConfig(); + +appAdminConfig.resolve.alias['sylius/ui'] = uiBundleScripts; +appAdminConfig.resolve.alias['sylius/ui-resources'] = uiBundleResources; +appAdminConfig.resolve.alias['sylius/bundle'] = syliusBundles; +appAdminConfig.externals = Object.assign({}, appAdminConfig.externals, { window: 'window', document: 'document' }); +appAdminConfig.name = 'app.admin'; + +module.exports = [shopConfig, adminConfig, appShopConfig, appAdminConfig];