diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..1a51090 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,55 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/docker-in-docker +{ + "name": "Sylius Robots Txt Plugin", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/base:bullseye", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "latest", + "enableNonRootDocker": "true", + "moby": "false" + }, + "ghcr.io/devcontainers/features/github-cli:1": { + "installDirectlyFromGitHubRelease": true, + "version": "latest" + }, + "ghcr.io/devcontainers/features/node:1": { + "nodeGypDependencies": true, + "version": "14", + "nvmVersion": "latest" + }, + "ghcr.io/shyim/devcontainers-features/php:0": { + "installComposer": true, + "version": "8.2" + }, + "ghcr.io/shyim/devcontainers-features/symfony-cli:0": {} + }, + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [ + 8000 + ], + "portsAttributes": { + "8000": { + "label": "Sylius Test Application" + } + }, + // Use 'postCreateCommand' to run commands after the container is created. + "onCreateCommand": "make dependencies application codespace.hostname docker.pull install stop", + "postStartCommand": "make up", + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.makefile-tools", + "TheNouillet.symfony-vscode", + "xdebug.php-debug", + "eamodio.gitlens" + ] + } + } + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} + diff --git a/.github/workflows/recipe.yaml b/.github/workflows/recipe.yaml new file mode 100644 index 0000000..cb4466f --- /dev/null +++ b/.github/workflows/recipe.yaml @@ -0,0 +1,82 @@ +name: Flex Recipe + +on: + push: + branches: [ master ] + pull_request: + +jobs: + + recipe: + + name: Flex recipe (PHP ${{ matrix.php }}, Sylius ${{ matrix.sylius }}) + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php: ['8.2'] + sylius: ["~1.12.0"] + + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, intl, json + ini-values: date.timezone=UTC + tools: symfony-cli + + - name: Set project php-version + run: | + echo ${{ matrix.php }} > .php-version + + - uses: actions/checkout@v3 + with: + path: plugin + + - name: Determine composer cache directory + id: composer-cache-directory + working-directory: plugin + run: echo "directory=$(composer config cache-dir)" >> $GITHUB_OUTPUT + + - name: Cache dependencies installed with composer + uses: actions/cache@v3 + id: cache-composer + with: + path: ${{ steps.composer-cache-directory.outputs.directory }} + key: composer2-php:${{ matrix.php }}-sylius:${{ matrix.sylius }}-${{ hashFiles('**/composer.json') }} + restore-keys: composer2-php:${{ matrix.php }}-sylius:${{ matrix.sylius }}- + + - name: Ensure that composer cache directory exists + run: mkdir -p ${{ steps.composer-cache-directory.outputs.directory }} + + - name: Composer Github Auth + run: composer config -g github-oauth.github.com ${{ github.token }} + + - name: Create Sylius-Standard project without install + run: | + composer create-project --prefer-dist --no-scripts --no-progress --no-install sylius/sylius-standard sylius "${{ matrix.sylius }}" + + # Because the sylius-standard has a soft constraint + - name: Make sure to install the required version of Sylius + working-directory: ./sylius + run: | + composer require --no-install --no-scripts --no-progress sylius/sylius="${{ matrix.sylius }}" + + - name: Setup some requirements + working-directory: ./sylius + run: | + composer config --no-plugins allow-plugins true + composer config --no-plugins extra.symfony.allow-contrib true + composer config --no-plugins secure-http false + composer config --no-plugins --unset platform.php + composer config --no-plugins extra.symfony.docker false + composer config --no-plugins --json extra.symfony.endpoint '["https://api.github.com/repos/monsieurbiz/symfony-recipes/contents/index.json?ref=flex/master","flex://defaults"]' + composer config repositories.plugin '{"type": "path", "url": "../plugin/"}' + + - name: Require plugin & install all dependencies + working-directory: ./sylius + run: | + composer require monsieurbiz/sylius-robots-txt-plugin="*@dev" diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml new file mode 100644 index 0000000..8167db5 --- /dev/null +++ b/.github/workflows/security.yaml @@ -0,0 +1,55 @@ +name: Security + +on: + push: + pull_request: + +jobs: + + security: + + name: Security check (PHP ${{ matrix.php }}) + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php: ['8.2'] + + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, intl, json + ini-values: date.timezone=UTC + + - name: Set project php-version + run: | + echo ${{ matrix.php }} > .php-version + + - name: Determine composer cache directory + id: composer-cache-directory + run: echo "directory=$(composer config cache-dir)" >> $GITHUB_OUTPUT + + - name: Cache dependencies installed with composer + uses: actions/cache@v3 + id: cache-composer + with: + path: ${{ steps.composer-cache-directory.outputs.directory }} + key: composer2-php:${{ matrix.php }}-${{ hashFiles('**/composer.json') }} + restore-keys: composer2-php:${{ matrix.php }}- + - name: Ensure that composer cache directory exists + run: mkdir -p ${{ steps.composer-cache-directory.outputs.directory }} + + - name: Composer Github Auth + run: composer config -g github-oauth.github.com ${{ github.token }} + + - name: Install PHP dependencies + run: composer update --prefer-dist + + - uses: symfonycorp/security-checker-action@v4 + diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..501ea6c --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,78 @@ +name: Tests + +on: + push: + branches: [ master ] + pull_request: + +jobs: + + php: + + name: Quality tests (PHP ${{ matrix.php }}) + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php: ['8.2'] + + env: + COMPOSER_ARGS: --prefer-dist + DOCKER_INTERACTIVE_ARGS: -t + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: '16' + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, intl, json + ini-values: date.timezone=UTC + tools: symfony-cli + + - name: Set project php-version + run: | + echo ${{ matrix.php }} > .php-version + + - name: Determine composer cache directory + id: composer-cache-directory + run: echo "directory=$(composer config cache-dir)" >> $GITHUB_OUTPUT + + - name: Cache dependencies installed with composer + uses: actions/cache@v3 + id: cache-composer + with: + path: ${{ steps.composer-cache-directory.outputs.directory }} + key: composer2-php:${{ matrix.php }}-${{ hashFiles('**/composer.json') }} + restore-keys: composer2-php:${{ matrix.php }}- + + - name: Ensure that composer cache directory exists + run: mkdir -p ${{ steps.composer-cache-directory.outputs.directory }} + + - name: Composer Github Auth + run: composer config -g github-oauth.github.com ${{ github.token }} + + - run: make install + + - run: make test.composer + + - run: make test.phpcs + + - run: make test.phpstan + + - run: make test.phpmd + + - run: make test.yaml + + - run: make test.twig + + - run: make test.schema + + - run: make test.container diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7332111 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +/vendor/ +/composer.lock + +/etc/build/* +!/etc/build/.gitignore + +/tests/Application + +/behat.yml +/phpspec.yml + +/package-lock.json + +/var +/public +/bin +/.php-version +/php.ini +/.phpunit.result.cache +/node_modules +/yarn.lock +/.php-cs-fixer.cache diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..d7b447c --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,266 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +$header = <<<'HEADER' +This file is part of Monsieur Biz's Sylius Robots Txt Plugin for Sylius. +(c) Monsieur Biz +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +HEADER; + +$finder = PhpCsFixer\Finder::create() + ->in(__DIR__) + ->exclude( + [ + 'tests/Application', + ] + ) +; + +$config = new PhpCsFixer\Config(); +$config + ->setRiskyAllowed(true) + ->setRules([ + '@DoctrineAnnotation' => true, + '@PHP71Migration' => true, + '@PHP71Migration:risky' => true, + '@PHPUnit60Migration:risky' => true, + '@Symfony' => true, + '@Symfony:risky' => true, + 'align_multiline_comment' => [ + 'comment_type' => 'phpdocs_like', + ], + 'array_indentation' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'binary_operator_spaces' => true, + 'blank_line_after_opening_tag' => true, + 'blank_line_after_namespace' => true, + 'blank_lines_before_namespace' => true, + 'blank_line_before_statement' => true, + 'cast_spaces' => true, + 'class_attributes_separation' => true, + 'class_definition' => [ + 'single_item_single_line' => true, + 'multi_line_extends_each_single_line' => true, + ], + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'comment_to_phpdoc' => true, + 'compact_nullable_type_declaration' => true, + 'concat_space' => [ + 'spacing' => 'one', + ], + 'constant_case' => [ + 'case' => 'lower', + ], + 'declare_equal_normalize' => true, + 'dir_constant' => true, + 'declare_strict_types' => true, + 'doctrine_annotation_array_assignment' => [ + 'operator' => '=', + ], + 'doctrine_annotation_spaces' => [ + 'after_array_assignments_equals' => false, + 'before_array_assignments_equals' => false, + ], + 'elseif' => true, + 'encoding' => true, + 'ereg_to_preg' => true, + 'error_suppression' => true, + 'explicit_indirect_variable' => true, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => true, + 'function_declaration' => true, + 'function_to_constant' => true, + 'general_phpdoc_tag_rename' => true, + 'global_namespace_import' => [ + 'import_classes' => true, + 'import_constants' => false, + 'import_functions' => false, + ], + 'header_comment' => [ + 'header' => $header, + 'location' => 'after_open', + ], + 'include' => true, + 'increment_style' => [ + 'style' => 'pre', + ], + 'indentation_type' => true, + 'is_null' => true, + 'line_ending' => true, + 'list_syntax' => [ + 'syntax' => 'short', + ], + 'logical_operators' => true, + 'lowercase_cast' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'magic_constant_casing' => true, + 'method_argument_space' => true, + 'modernize_strpos' => false, + 'modernize_types_casting' => true, + 'multiline_comment_opening_closing' => true, + 'multiline_whitespace_before_semicolons' => [ + 'strategy' => 'new_line_for_chained_calls', + ], + 'native_constant_invocation' => true, + 'native_function_casing' => true, + 'new_with_parentheses' => true, + 'no_alias_functions' => true, + 'no_alternative_syntax' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => [ + 'tokens' => [ + 'break', + 'case', + 'continue', + 'curly_brace_block', + 'default', + 'extra', + 'parenthesis_brace_block', + 'return', + 'square_brace_block', + 'switch', + 'throw', + 'use', + ], + ], + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => [ + 'use' => 'echo', + ], + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_short_bool_cast' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_around_offset' => true, + 'spaces_inside_parentheses' => true, + 'no_superfluous_elseif' => true, + 'no_superfluous_phpdoc_tags' => [ + 'allow_mixed' => true, + ], + 'no_unset_cast' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unneeded_braces' => true, + 'no_unneeded_final_method' => true, + 'no_unset_on_property' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_trailing_comma_in_singleline' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'non_printable_character' => true, + 'normalize_index_brace' => true, + 'nullable_type_declaration_for_default_null_value' => false, + 'object_operator_without_whitespace' => true, + 'ordered_imports' => [ + 'imports_order' => [ + 'class', + 'function', + 'const', + ], + 'sort_algorithm' => 'alpha', + ], + 'php_unit_dedicate_assert' => true, + 'php_unit_fqcn_annotation' => true, + 'php_unit_method_casing' => [ + 'case' => 'camel_case', + ], + 'php_unit_set_up_tear_down_visibility' => true, + 'php_unit_test_annotation' => [ + 'style' => 'prefix', + ], + 'phpdoc_align' => [ + 'align' => 'left', + ], + 'phpdoc_add_missing_param_annotation' => [ + 'only_untyped' => true, + ], + 'phpdoc_indent' => true, + 'phpdoc_inline_tag_normalizer' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_alias_tag' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_no_useless_inheritdoc' => true, + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => ['groups' => [ + ['ORM\\*'], ['Assert\\*'], + ]], + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_tag_type' => true, + 'phpdoc_to_comment' => false, + 'phpdoc_trim' => true, + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => true, + 'phpdoc_types_order' => [ + 'null_adjustment' => 'always_last', + 'sort_algorithm' => 'none', + ], + 'phpdoc_var_annotation_correct_order' => true, + 'phpdoc_var_without_name' => true, + 'pow_to_exponentiation' => true, + 'protected_to_private' => true, + 'return_assignment' => true, + 'return_type_declaration' => true, + 'self_accessor' => true, + 'short_scalar_cast' => true, + 'single_blank_line_at_eof' => true, + 'single_class_element_per_statement' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_line_comment_style' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'standardize_not_equals' => true, + 'strict_param' => true, + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'ternary_operator_spaces' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline' => [ + 'elements' => ['arrays'], + ], + 'trim_array_spaces' => true, + 'type_declaration_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => [ + 'elements' => [ + 'const', + 'property', + 'method', + ], + ], + 'void_return' => true, + 'whitespace_after_comma_in_array' => true, // alerady in symfony set + ]) + ->setFinder($finder) +; + +return $config; diff --git a/.php-version.dist b/.php-version.dist new file mode 100644 index 0000000..2983cad --- /dev/null +++ b/.php-version.dist @@ -0,0 +1 @@ +8.2 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f977cd1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Monsieur Biz + +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. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dd7acef --- /dev/null +++ b/Makefile @@ -0,0 +1,239 @@ +.DEFAULT_GOAL := help +SHELL=/bin/bash +APP_DIR=tests/Application +SYLIUS_VERSION=1.12.0 +SYMFONY=cd ${APP_DIR} && symfony +COMPOSER=symfony composer +CONSOLE=${SYMFONY} console +export COMPOSE_PROJECT_NAME=sylius_robots_txt_plugin +PLUGIN_NAME=sylius-robots-txt-plugin +COMPOSE=docker-compose +YARN=yarn +DOCTRINE_MIGRATIONS_NAMESPACE=MonsieurBiz\SyliusRobotsTxtPlugin\Migrations + + +### +### DEVELOPMENT +### ¯¯¯¯¯¯¯¯¯¯¯ + +install: application platform sylius ## Install the plugin +.PHONY: install + +up: docker.up server.start ## Up the project (start docker, start symfony server) +stop: server.stop docker.stop ## Stop the project (stop docker, stop symfony server) +down: server.stop docker.down ## Down the project (removes docker containers, stop symfony server) + +reset: ## Stop docker and remove dependencies + ${MAKE} docker.down || true + rm -rf ${APP_DIR}/node_modules ${APP_DIR}/yarn.lock + rm -rf ${APP_DIR} + rm -rf vendor composer.lock +.PHONY: reset + +dependencies: composer.lock node_modules ## Setup the dependencies +.PHONY: dependencies + +.php-version: .php-version.dist + rm -f .php-version + ln -s .php-version.dist .php-version + +php.ini: php.ini.dist + rm -f php.ini + ln -s php.ini.dist php.ini + +composer.lock: composer.json + ${COMPOSER} install --no-scripts --no-plugins + +yarn.install: ${APP_DIR}/yarn.lock + +${APP_DIR}/yarn.lock: + ln -sf ${APP_DIR}/node_modules node_modules + cd ${APP_DIR} && ${YARN} install && ${YARN} build +# No CSS and JS on this plugin yet +# ${YARN} install +# ${YARN} encore prod + +node_modules: ${APP_DIR}/node_modules ## Install the Node dependencies using yarn + +${APP_DIR}/node_modules: yarn.install + +### +### TEST APPLICATION +### ¯¯¯¯¯ + +application: .php-version php.ini ${APP_DIR} setup_application ${APP_DIR}/docker-compose.yaml + +${APP_DIR}: + (${COMPOSER} create-project --no-interaction --prefer-dist --no-scripts --no-progress --no-install sylius/sylius-standard="~${SYLIUS_VERSION}" ${APP_DIR}) + +setup_application: + rm -f ${APP_DIR}/yarn.lock + (cd ${APP_DIR} && ${COMPOSER} config repositories.plugin '{"type": "path", "url": "../../"}') + (cd ${APP_DIR} && ${COMPOSER} config extra.symfony.allow-contrib true) + (cd ${APP_DIR} && ${COMPOSER} config minimum-stability dev) + (cd ${APP_DIR} && ${COMPOSER} config --no-plugins allow-plugins true) + (cd ${APP_DIR} && ${COMPOSER} config --no-plugins --json extra.symfony.endpoint '["https://api.github.com/repos/monsieurbiz/symfony-recipes/contents/index.json?ref=flex/master","flex://defaults"]') + (cd ${APP_DIR} && ${COMPOSER} require --no-install --no-scripts --no-progress sylius/sylius="~${SYLIUS_VERSION}") # Make sure to install the required version of sylius because the sylius-standard has a soft constraint + $(MAKE) ${APP_DIR}/.php-version + $(MAKE) ${APP_DIR}/php.ini + (cd ${APP_DIR} && ${COMPOSER} install --no-interaction) + $(MAKE) apply_dist + (cd ${APP_DIR} && ${COMPOSER} require --no-progress monsieurbiz/${PLUGIN_NAME}="*@dev") + rm -rf ${APP_DIR}/var/cache + + +${APP_DIR}/docker-compose.yaml: + rm -f ${APP_DIR}/docker-compose.yml + rm -f ${APP_DIR}/docker-compose.yaml + ln -s ../../docker-compose.yaml.dist ${APP_DIR}/docker-compose.yaml +.PHONY: ${APP_DIR}/docker-compose.yaml + +${APP_DIR}/.php-version: .php-version + (cd ${APP_DIR} && ln -sf ../../.php-version) + +${APP_DIR}/php.ini: php.ini + (cd ${APP_DIR} && ln -sf ../../php.ini) + +apply_dist: + ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))); \ + for i in `cd dist && find . -type f`; do \ + FILE_PATH=`echo $$i | sed 's|./||'`; \ + FOLDER_PATH=`dirname $$FILE_PATH`; \ + echo $$FILE_PATH; \ + (cd ${APP_DIR} && rm -f $$FILE_PATH); \ + (cd ${APP_DIR} && mkdir -p $$FOLDER_PATH); \ + (cd ${APP_DIR} && ln -s $$ROOT_DIR/dist/$$FILE_PATH $$FILE_PATH); \ + done + +### +### TESTS +### ¯¯¯¯¯ + +test.all: test.composer test.phpstan test.phpmd test.phpcs test.yaml test.schema test.twig test.container ## Run all tests in once + +test.composer: ## Validate composer.json + ${COMPOSER} validate --strict + +test.phpstan: ## Run PHPStan + ${COMPOSER} phpstan + +test.phpmd: ## Run PHPMD + ${COMPOSER} phpmd + +test.phpcs: ## Run PHP CS Fixer in dry-run + ${COMPOSER} run -- phpcs --dry-run -v + +test.phpcs.fix: ## Run PHP CS Fixer and fix issues if possible + ${COMPOSER} run -- phpcs -v + +test.container: ## Lint the symfony container + ${CONSOLE} lint:container + +test.yaml: ## Lint the symfony Yaml files + ${CONSOLE} lint:yaml ../../recipes ../../src/Resources/config + +test.schema: ## Validate MySQL Schema + ${CONSOLE} doctrine:schema:validate + +test.twig: ## Validate Twig templates + ${CONSOLE} lint:twig --no-debug templates/ ../../src/Resources/views/ + +### +### MIGRATIONS +### ¯¯¯¯¯¯¯¯¯¯ + +app.doctrine.migration.diff: ## Create a diff migration file for the Test Application + ${CONSOLE} doctrine:migrations:diff --namespace="App\Migrations" +.PHONY: app.doctrine.migration.diff + +doctrine.migration.diff: ## Create a diff migration file for the Plugin itself + ${CONSOLE} doctrine:migrations:diff --namespace="${DOCTRINE_MIGRATIONS_NAMESPACE}" +.PHONY: doctrine.migration.diff + +doctrine.migration.migrate: ## Run migrations + ${CONSOLE} doctrine:migration:migrate -n +.PHONY: doctrine.migration.migrate + +### +### SYLIUS +### ¯¯¯¯¯¯ + +sylius: dependencies sylius.database sylius.fixtures sylius.assets messenger.setup ## Install Sylius +.PHONY: sylius + +sylius.database: ## Setup the database + ${CONSOLE} doctrine:database:drop --if-exists --force + ${CONSOLE} doctrine:database:create --if-not-exists + ${CONSOLE} doctrine:migration:migrate -n + +sylius.fixtures: ## Run the fixtures + ${CONSOLE} sylius:fixtures:load -n default + +sylius.assets: ## Install all assets with symlinks + ${CONSOLE} assets:install --symlink + ${CONSOLE} sylius:install:assets + ${CONSOLE} sylius:theme:assets:install --symlink + +messenger.setup: ## Setup Messenger transports + ${CONSOLE} messenger:setup-transports + +### +### PLATFORM +### ¯¯¯¯¯¯¯¯ + +platform: .php-version up ## Setup the platform tools +.PHONY: platform + +docker.pull: ## Pull the docker images + cd ${APP_DIR} && ${COMPOSE} pull + +docker.up: ## Start the docker containers + cd ${APP_DIR} && ${COMPOSE} up -d +.PHONY: docker.up + +docker.stop: ## Stop the docker containers + cd ${APP_DIR} && ${COMPOSE} stop +.PHONY: docker.stop + +docker.down: ## Stop and remove the docker containers + cd ${APP_DIR} && ${COMPOSE} down +.PHONY: docker.down + +docker.logs: ## Logs the docker containers + cd ${APP_DIR} && ${COMPOSE} logs -f +.PHONY: docker.logs + +docker.dc: ARGS=ps +docker.dc: ## Run docker-compose command. Use ARGS="" to pass parameters to docker-compose. + cd ${APP_DIR} && ${COMPOSE} ${ARGS} +.PHONY: docker.dc + +server.start: ## Run the local webserver using Symfony + ${SYMFONY} local:server:start -d + +server.stop: ## Stop the local webserver + ${SYMFONY} local:server:stop + +### +### GITHUB CODESPACES +### ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + +codespace.hostname: ${APP_DIR}/.env.local ## Init the SYLIUS_FIXTURES_HOSTNAME variable in .env.local +ifdef CODESPACES + echo SYLIUS_FIXTURES_HOSTNAME=${CODESPACE_NAME}-8000.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN} >> ${APP_DIR}/.env.local +endif + +${APP_DIR}/.env.local: + touch ${APP_DIR}/.env.local + +### +### HELP +### ¯¯¯¯ + +help: SHELL=/bin/bash +help: ## Dislay this help + @IFS=$$'\n'; for line in `grep -h -E '^[a-zA-Z_#-]+:?.*?##.*$$' $(MAKEFILE_LIST)`; do if [ "$${line:0:2}" = "##" ]; then \ + echo $$line | awk 'BEGIN {FS = "## "}; {printf "\033[33m %s\033[0m\n", $$2}'; else \ + echo $$line | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m%s\n", $$1, $$2}'; fi; \ + done; unset IFS; +.PHONY: help diff --git a/README.md b/README.md new file mode 100644 index 0000000..58c97ed --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# Sylius Robots Txt Plugin + +Manage your robot.txt from your Sylius admin pannel + +## Installation + +TBD + +## License + +This plugin is under the MIT license. +Please see the [LICENSE](LICENSE) file for more information. diff --git a/behat.yml.dist b/behat.yml.dist new file mode 100644 index 0000000..ea37647 --- /dev/null +++ b/behat.yml.dist @@ -0,0 +1,8 @@ +default: + suites: + default: + contexts: + - App\Tests\Behat\DemoContext + + extensions: + FriendsOfBehat\SymfonyExtension: null diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..6309a7c --- /dev/null +++ b/composer.json @@ -0,0 +1,84 @@ +{ + "name": "monsieurbiz/sylius-robots-txt-plugin", + "type": "sylius-plugin", + "keywords": ["sylius", "sylius-plugin"], + "description": "Manage your robot.txt from your Sylius admin pannel", + "license": "MIT", + "require": { + "php": "^8.2", + "sylius/sylius": ">=1.12 <1.13" + }, + "require-dev": { + "behat/behat": "^3.6.1", + "behat/mink-selenium2-driver": "^1.4", + "dmore/behat-chrome-extension": "^1.3", + "dmore/chrome-mink-driver": "^2.7", + "friendsofphp/php-cs-fixer": "^3.51", + "friends-of-behat/mink": "^1.8", + "friends-of-behat/mink-browserkit-driver": "^1.4", + "friends-of-behat/mink-debug-extension": "^2.0.0", + "friends-of-behat/mink-extension": "^2.4", + "friends-of-behat/page-object-extension": "^0.3", + "friends-of-behat/suite-settings-extension": "^1.0", + "friends-of-behat/symfony-extension": "^2.1", + "friends-of-behat/variadic-extension": "^1.3", + "phpmd/phpmd": "^2.15", + "phpspec/phpspec": "^7.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.8.1", + "phpstan/phpstan-doctrine": "1.3.40", + "phpstan/phpstan-strict-rules": "^1.3.0", + "phpstan/phpstan-webmozart-assert": "^1.2.0", + "phpunit/phpunit": "^9.5", + "polishsymfonycommunity/symfony-mocker-container": "^1.0", + "sylius-labs/coding-standard": "^4.2", + "symfony/browser-kit": "^5.4 || ^6.0", + "symfony/debug-bundle": "^5.4 || ^6.0", + "symfony/dotenv": "^5.4 || ^6.0", + "symfony/flex": "^2.2.2", + "symfony/intl": "^5.4 || ^6.0", + "symfony/web-profiler-bundle": "^5.4 || ^6.0", + "vimeo/psalm": "5.12.0", + "phpmd/phpmd": "^2.13", + "friendsofphp/php-cs-fixer": "^3.16" + }, + "prefer-stable": true, + "autoload": { + "psr-4": { + "MonsieurBiz\\SyliusRobotsTxtPlugin\\": "src/" + } + }, + "scripts": { + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + }, + "phpcs": "php-cs-fixer fix --using-cache=no", + "phpstan": "phpstan analyse -c phpstan.neon src/", + "phpmd": "phpmd --exclude Migrations/* src/ ansi phpmd.xml", + "phpunit": "phpunit", + "phpspec": "phpspec run" + }, + "extra": { + "symfony": { + "docker": false, + "endpoint": [ + "https://api.github.com/repos/monsieurbiz/symfony-recipes/contents/index.json?ref=flex/master", + "flex://defaults" + ] + }, + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "symfony/thanks": true, + "ergebnis/composer-normalize": true, + "symfony/flex": true, + "php-http/discovery": false, + "phpstan/extension-installer": true + } + } +} diff --git a/dist/config/packages/monsieurbiz_sylius_robots_txt_plugin.yaml b/dist/config/packages/monsieurbiz_sylius_robots_txt_plugin.yaml new file mode 100644 index 0000000..c007128 --- /dev/null +++ b/dist/config/packages/monsieurbiz_sylius_robots_txt_plugin.yaml @@ -0,0 +1,2 @@ +imports: + resource: '@MonsieurBizSyliusRobotsTxtPlugin/Resources/config/config.yaml' diff --git a/dist/config/routes/monsieurbiz_sylius_robots_txt_plugin.yaml b/dist/config/routes/monsieurbiz_sylius_robots_txt_plugin.yaml new file mode 100644 index 0000000..9142615 --- /dev/null +++ b/dist/config/routes/monsieurbiz_sylius_robots_txt_plugin.yaml @@ -0,0 +1,2 @@ +imports: + resource: '@MonsieurBizSyliusRobotsTxtPlugin/Resources/config/routes.yaml' diff --git a/dist/src/Entity/.gitignore b/dist/src/Entity/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/dist/src/Migrations/.gitignore b/dist/src/Migrations/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yaml.dist b/docker-compose.yaml.dist new file mode 100644 index 0000000..ee0776f --- /dev/null +++ b/docker-compose.yaml.dist @@ -0,0 +1,21 @@ +version: '3.8' +services: + database: + image: mysql:8.0 + command: --default-authentication-plugin=mysql_native_password + ports: + - 3306 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: 1 + MYSQL_DATABASE: sylius + volumes: + - database:/var/lib/mysql + + mailer: + image: monsieurbiz/mailcatcher + ports: + - 1025 + - 1080 + +volumes: + database: {} \ No newline at end of file diff --git a/php.ini.dist b/php.ini.dist new file mode 100644 index 0000000..5946850 --- /dev/null +++ b/php.ini.dist @@ -0,0 +1 @@ +memory_limit=-1 \ No newline at end of file diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..279b4be --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,16 @@ + + + + + + + + + + + + src/ + tests/ + + diff --git a/phpmd.xml b/phpmd.xml new file mode 100644 index 0000000..c4e85e1 --- /dev/null +++ b/phpmd.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpspec.yml.dist b/phpspec.yml.dist new file mode 100644 index 0000000..f4d9d49 --- /dev/null +++ b/phpspec.yml.dist @@ -0,0 +1,6 @@ +suites: + main: + namespace: MonsieurBiz\SyliusRobotsTxtPlugin + psr4_prefix: MonsieurBiz\SyliusRobotsTxtPlugin + src_path: src + spec_path: tests diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..8566fa1 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,14 @@ +parameters: + level: max + paths: + - %rootDir%/src/ + + checkMissingIterableValueType: false + checkGenericClassInNonGenericObjectType: false + + excludePaths: + # Makes PHPStan crash + - 'src/DependencyInjection/SyliusRobotsTxtExtension.php' + + # Test dependencies + - 'tests/Application/**/*' diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..f023f90 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,55 @@ + + + + + + tests/Unit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/recipes/1.0-dev/config/packages/monsieurbiz_sylius_robots_txt_plugin.yaml b/recipes/1.0-dev/config/packages/monsieurbiz_sylius_robots_txt_plugin.yaml new file mode 100644 index 0000000..c007128 --- /dev/null +++ b/recipes/1.0-dev/config/packages/monsieurbiz_sylius_robots_txt_plugin.yaml @@ -0,0 +1,2 @@ +imports: + resource: '@MonsieurBizSyliusRobotsTxtPlugin/Resources/config/config.yaml' diff --git a/recipes/1.0-dev/config/routes/monsieurbiz_sylius_robots_txt_plugin.yaml b/recipes/1.0-dev/config/routes/monsieurbiz_sylius_robots_txt_plugin.yaml new file mode 100644 index 0000000..e1c34ba --- /dev/null +++ b/recipes/1.0-dev/config/routes/monsieurbiz_sylius_robots_txt_plugin.yaml @@ -0,0 +1,9 @@ +monsieurbiz_robots_txt_admin: + resource: '@MonsieurBizSyliusRobotsTxtPlugin/Resources/config/routes/admin.yaml' + prefix: '/%sylius_admin.path_name%' + +monsieurbiz_robots_txt_shop: + resource: '@MonsieurBizSyliusRobotsTxtPlugin/Resources/config/routes/shop.yaml' + prefix: '/{_locale}' + requirements: + _locale: ^[A-Za-z]{2,4}(_([A-Za-z]{4}|[0-9]{3}))?(_([A-Za-z]{2}|[0-9]{3}))?$ diff --git a/recipes/1.0-dev/manifest.json b/recipes/1.0-dev/manifest.json new file mode 100644 index 0000000..0d490f1 --- /dev/null +++ b/recipes/1.0-dev/manifest.json @@ -0,0 +1,10 @@ +{ + "bundles": { + "MonsieurBiz\\SyliusRobotsTxtPlugin\\MonsieurBizSyliusRobotsTxtPlugin": [ + "all" + ] + }, + "copy-from-recipe": { + "config/": "%CONFIG_DIR%/" + } +} diff --git a/src/Controller/.gitignore b/src/Controller/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/DependencyInjection/MonsieurBizSyliusRobotsTxtExtension.php b/src/DependencyInjection/MonsieurBizSyliusRobotsTxtExtension.php new file mode 100644 index 0000000..83e30cf --- /dev/null +++ b/src/DependencyInjection/MonsieurBizSyliusRobotsTxtExtension.php @@ -0,0 +1,40 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace MonsieurBiz\SyliusRobotsTxtPlugin\DependencyInjection; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +/** + * @SuppressWarnings(PHPMD.LongClassName) + */ +final class MonsieurBizSyliusRobotsTxtExtension extends Extension +{ + /** + * @inheritdoc + */ + public function load(array $config, ContainerBuilder $container): void + { + $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('services.yaml'); + } + + /** + * @inheritdoc + */ + public function getAlias(): string + { + return 'monsieurbiz_robots_txt'; + } +} diff --git a/src/Entity/.gitignore b/src/Entity/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/MonsieurBizSyliusRobotsTxtPlugin.php b/src/MonsieurBizSyliusRobotsTxtPlugin.php new file mode 100644 index 0000000..2517857 --- /dev/null +++ b/src/MonsieurBizSyliusRobotsTxtPlugin.php @@ -0,0 +1,44 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace MonsieurBiz\SyliusRobotsTxtPlugin; + +use LogicException; +use Sylius\Bundle\CoreBundle\Application\SyliusPluginTrait; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\HttpKernel\Bundle\Bundle; + +final class MonsieurBizSyliusRobotsTxtPlugin extends Bundle +{ + use SyliusPluginTrait; + + /** + * Returns the plugin's container extension. + * + * @throws LogicException + * + * @return ExtensionInterface|null The container extension + */ + public function getContainerExtension(): ?ExtensionInterface + { + if (null === $this->containerExtension) { + $this->containerExtension = false; + $extension = $this->createContainerExtension(); + if (null !== $extension) { + $this->containerExtension = $extension; + } + } + + return $this->containerExtension instanceof ExtensionInterface + ? $this->containerExtension + : null; + } +} diff --git a/src/Resources/config/config.yaml b/src/Resources/config/config.yaml new file mode 100644 index 0000000..e69de29 diff --git a/src/Resources/config/routes/admin.yaml b/src/Resources/config/routes/admin.yaml new file mode 100644 index 0000000..e69de29 diff --git a/src/Resources/config/routes/shop.yaml b/src/Resources/config/routes/shop.yaml new file mode 100644 index 0000000..e69de29 diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml new file mode 100644 index 0000000..bafad59 --- /dev/null +++ b/src/Resources/config/services.yaml @@ -0,0 +1,14 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + MonsieurBiz\SyliusRobotsTxtPlugin\: + resource: '../../*' + exclude: '../../{Entity}' + + MonsieurBiz\SyliusRobotsTxtPlugin\Controller\: + resource: '../../Controller' + tags: [ 'controller.service_arguments' ] +