First commit of project EBS
This commit is contained in:
parent
b160346ee1
commit
e533ba1f15
989 changed files with 74032 additions and 662 deletions
34
.dockerignore
Normal file
34
.dockerignore
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
**/*.log
|
||||||
|
**/*.md
|
||||||
|
**/*.php~
|
||||||
|
**/*.dist.php
|
||||||
|
**/*.dist
|
||||||
|
**/*.cache
|
||||||
|
**/._*
|
||||||
|
**/.dockerignore
|
||||||
|
**/.DS_Store
|
||||||
|
**/.git/
|
||||||
|
**/.gitattributes
|
||||||
|
**/.gitignore
|
||||||
|
**/.gitmodules
|
||||||
|
**/docker-compose.*.yaml
|
||||||
|
**/docker-compose.*.yml
|
||||||
|
**/docker-compose.yaml
|
||||||
|
**/docker-compose.yml
|
||||||
|
**/Dockerfile
|
||||||
|
**/Thumbs.db
|
||||||
|
.github/
|
||||||
|
docs/
|
||||||
|
helm/
|
||||||
|
Makefile
|
||||||
|
node_modules/
|
||||||
|
public/build/
|
||||||
|
public/bundles/
|
||||||
|
tests/
|
||||||
|
var/
|
||||||
|
vendor/
|
||||||
|
.editorconfig
|
||||||
|
.env.*.local
|
||||||
|
.env.local
|
||||||
|
.env.local.php
|
||||||
|
.env.test
|
||||||
72
.editorconfig
Normal file
72
.editorconfig
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
[*.{js,html,ts,tsx}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.php]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.sh]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.xml{,.dist}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.{yaml,yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[.github/workflows/*.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[.gitmodules]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[.php_cs{,.dist}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[.travis.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[composer.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[docker-compose{,.*}.{yaml,yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[Dockerfile]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
||||||
108
.env
Normal file
108
.env
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
# In all environments, the following files are loaded if they exist,
|
||||||
|
# the latter taking precedence over the former:
|
||||||
|
#
|
||||||
|
# * .env contains default values for the environment variables needed by the app
|
||||||
|
# * .env.local uncommitted file with local overrides
|
||||||
|
# * .env.$APP_ENV committed environment-specific defaults
|
||||||
|
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||||
|
#
|
||||||
|
# Real environment variables win over .env files.
|
||||||
|
#
|
||||||
|
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||||
|
# https://symfony.com/doc/current/configuration/secrets.html
|
||||||
|
#
|
||||||
|
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||||
|
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
APP_ENV=dev
|
||||||
|
APP_DEBUG=1
|
||||||
|
APP_SECRET=fd8e6e32f64b1dddcfe849f88de35019
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> doctrine/doctrine-bundle ###
|
||||||
|
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||||
|
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||||
|
#
|
||||||
|
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
|
||||||
|
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8&charset=utf8mb4"
|
||||||
|
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=14&charset=utf8"
|
||||||
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
|
###> nelmio/cors-bundle ###
|
||||||
|
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
|
||||||
|
###< nelmio/cors-bundle ###
|
||||||
|
|
||||||
|
###> symfony/messenger ###
|
||||||
|
# Choose one of the transports below
|
||||||
|
MESSENGER_TRANSPORT_DSN=doctrine://default
|
||||||
|
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||||
|
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||||
|
###< symfony/messenger ###
|
||||||
|
|
||||||
|
###> symfony/mercure-bundle ###
|
||||||
|
# See https://symfony.com/doc/current/mercure.html#configuration
|
||||||
|
# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
|
||||||
|
MERCURE_URL=https://example.com/.well-known/mercure
|
||||||
|
# The public URL of the Mercure hub, used by the browser to connect
|
||||||
|
MERCURE_PUBLIC_URL=https://example.com/.well-known/mercure
|
||||||
|
# The secret used to sign the JWTs
|
||||||
|
MERCURE_JWT_SECRET="!ChangeThisMercureHubJWTSecretKey!"
|
||||||
|
###< symfony/mercure-bundle ###
|
||||||
|
|
||||||
|
###> symfony/mailer ###
|
||||||
|
MAILER_DSN=null://null
|
||||||
|
# MAILER_DSN=smtp://mailer:1025
|
||||||
|
# MAILER_DSN=null://null
|
||||||
|
###< symfony/mailer ###
|
||||||
|
|
||||||
|
###> symfony/google-mailer ###
|
||||||
|
# Gmail SHOULD NOT be used on production, use it in development only.
|
||||||
|
# It can be used with an application password, see https://support.google.com/accounts/answer/185833?visit_id=638042796580302159-1820620508&p=InvalidSecondFactor&rd=1
|
||||||
|
# MAILER_DSN=gmail://USERNAME:PASSWORD@default
|
||||||
|
###< symfony/google-mailer ###
|
||||||
|
|
||||||
|
###> symfony/twilio-notifier ###
|
||||||
|
# SMS_DSN=twilio://SID:TOKEN@default?from=FROM
|
||||||
|
###< symfony/twilio-notifier ###
|
||||||
|
|
||||||
|
###> symfony/ovh-cloud-notifier ###
|
||||||
|
# SMS_DSN=ovhcloud://APPLICATION_KEY:APPLICATION_SECRET@default?consumer_key=CONSUMER_KEY&service_name=SERVICE_NAME
|
||||||
|
###< symfony/ovh-cloud-notifier ###
|
||||||
|
|
||||||
|
###> symfony/notifier ###
|
||||||
|
# This is main the DNS that is used by the notifier component
|
||||||
|
# the other below are just example for two different third party vendors
|
||||||
|
#SMS_DSN=twilio://SID:TOKEN@default?from=FROM
|
||||||
|
SMS_DSN=null://null
|
||||||
|
###< symfony/notifier ###
|
||||||
|
|
||||||
|
###> symfony/fake-sms-notifier ###
|
||||||
|
FAKE_SMS_DSN=fakesms+email://mailer?to=admin&from=PlateformCoop
|
||||||
|
###< symfony/fake-sms-notifier ###
|
||||||
|
|
||||||
|
###> snc/redis-bundle ###
|
||||||
|
# passwords that contain special characters (@, %, :, +) must be urlencoded
|
||||||
|
REDIS_URL=redis://redis
|
||||||
|
###< snc/redis-bundle ###
|
||||||
|
|
||||||
|
###> meilisearch/meilisearch-symfony ###
|
||||||
|
MEILISEARCH_URL=http://meilisearch:7700
|
||||||
|
MEILISEARCH_API_KEY=ms
|
||||||
|
###< meilisearch/meilisearch-symfony ###
|
||||||
|
|
||||||
|
###> payum/payum-bundle ###
|
||||||
|
# @see https://my.mollie.com/dashboard/org_XXXXXXXX/developers/api-keys
|
||||||
|
# even it's a fake key it must start with 'test_' or 'live_' and must be at least 30 characters long
|
||||||
|
PAYUM_APIKEY=test_FRabcdefghijklmnopqrstuvwxyzab
|
||||||
|
PAYUM_GATEWAY=mollie
|
||||||
|
###< payum/payum-bundle ###
|
||||||
|
|
||||||
|
###> league/flysystem-bundle ###
|
||||||
|
STORAGE_BUCKET=images
|
||||||
|
STORAGE_ENDPOINT=http://storage:9000
|
||||||
|
STORAGE_REGION=us-east-1
|
||||||
|
STORAGE_USE_PATH_STYLE_ENDPOINT=true
|
||||||
|
STORAGE_KEY=app
|
||||||
|
STORAGE_SECRET=!ChangeMe!
|
||||||
|
###< league/flysystem-bundle ###
|
||||||
7
.env.test
Normal file
7
.env.test
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# define your env variables for the test env here
|
||||||
|
KERNEL_CLASS='App\Kernel'
|
||||||
|
APP_SECRET='$ecretf0rt3st'
|
||||||
|
SYMFONY_DEPRECATIONS_HELPER=999999
|
||||||
|
PANTHER_APP_ENV=test
|
||||||
|
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots
|
||||||
|
PAYUM_GATEWAY=offline
|
||||||
33
.eslintrc.json
Normal file
33
.eslintrc.json
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"overrides": [
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
2,
|
||||||
|
{ "ignoreComments": true }
|
||||||
|
],
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"single"
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
16
.gitattributes
vendored
Normal file
16
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
|
*.conf text eol=lf
|
||||||
|
*.html text eol=lf
|
||||||
|
*.ini text eol=lf
|
||||||
|
*.js text eol=lf
|
||||||
|
*.json text eol=lf
|
||||||
|
*.md text eol=lf
|
||||||
|
*.php text eol=lf
|
||||||
|
*.sh text eol=lf
|
||||||
|
*.yaml text eol=lf
|
||||||
|
*.yml text eol=lf
|
||||||
|
bin/console text eol=lf
|
||||||
|
|
||||||
|
*.ico binary
|
||||||
|
*.png binary
|
||||||
45
.github/pull_request_template.md
vendored
Normal file
45
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Description
|
||||||
|
|
||||||
|
Please include a summary of the changes and the related issue.
|
||||||
|
Please also include relevant motivation and context.
|
||||||
|
|
||||||
|
Related to # (issue)
|
||||||
|
|
||||||
|
## Type of change
|
||||||
|
|
||||||
|
Please delete options that are not relevant.
|
||||||
|
|
||||||
|
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||||
|
- [ ] New feature (non-breaking change which adds functionality)
|
||||||
|
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||||
|
- [ ] Cleanup/refactoring of an existing feature (code quality change without feature modification)
|
||||||
|
- [ ] Improvment of an existing feature (minor tweak)
|
||||||
|
- [ ] Documentation (no code)
|
||||||
|
|
||||||
|
# How Has This Been Tested?
|
||||||
|
|
||||||
|
Please describe the tests that you ran to verify your changes. Put below at least a file
|
||||||
|
that was modified/added for the tests of this feature/bugfix.
|
||||||
|
|
||||||
|
- [ ] Test A
|
||||||
|
|
||||||
|
# Checklist:
|
||||||
|
|
||||||
|
- [ ] I have assigned myself to the related ticket
|
||||||
|
- [ ] I have read the ticket carefully and the code addresses exactly what is described in it
|
||||||
|
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||||
|
- [ ] Tests pass locally (`make test-complete`)
|
||||||
|
- [ ] Code coverage is still at 100% (`make coverage`)
|
||||||
|
- [ ] My code follows the style guidelines of this project, `make ci` should run without error
|
||||||
|
- [ ] Translations have been added, I didn't put raw text in PHP files or Twig templates
|
||||||
|
- [ ] I have performed a self-review of my code
|
||||||
|
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||||
|
- [ ] I have made corresponding changes to the documentation
|
||||||
|
- [ ] Git rebase have been made, and the PR can be merged without conflict
|
||||||
|
- [ ] All CI checks are ✅
|
||||||
|
- [ ] I have removed the draft status of the PR
|
||||||
|
- [ ] I have removed the WIP tag on the PR and also in the title
|
||||||
|
- [ ] I have added the RFR (ready for review) tag on the PR
|
||||||
|
- [ ] I have added the DEPLOY tag and the feature/fix can be tested on the dedicated environment
|
||||||
|
- [ ] I have assigned someone to review the PR
|
||||||
|
|
||||||
56
.github/workflows/ci.yml
vendored
Normal file
56
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Docker build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Pull images
|
||||||
|
run: docker compose pull
|
||||||
|
- name: Start services
|
||||||
|
run: docker compose up --build -d
|
||||||
|
- name: Wait for services
|
||||||
|
run: |
|
||||||
|
while status="$(docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" "$(docker compose ps -q php)")"; do
|
||||||
|
case $status in
|
||||||
|
starting) sleep 1;;
|
||||||
|
healthy) exit 0;;
|
||||||
|
unhealthy) exit 1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
exit 1
|
||||||
|
- name: Check HTTP reachability
|
||||||
|
run: curl http://localhost
|
||||||
|
- name: Check HTTPS reachability
|
||||||
|
run: curl -k https://localhost
|
||||||
|
- name: Test manifest file
|
||||||
|
run: mkdir -p public/build; docker compose exec -T php echo "{}" > public/build/manifest.json
|
||||||
|
- name: Create test database
|
||||||
|
run: docker compose exec -T php bin/console -e test doctrine:database:create
|
||||||
|
- name: Create database schema
|
||||||
|
run: docker compose exec -T php bin/console -e test doctrine:schema:create
|
||||||
|
- name: Setup Messenger
|
||||||
|
run: docker compose exec -T php bin/console -e test messenger:setup-transports
|
||||||
|
- name: Initializing Fixtures
|
||||||
|
run: docker compose exec -T php bin/console -e test hautelook:fixtures:load --no-interaction --no-bundles
|
||||||
|
- name: Meilisearch indexation
|
||||||
|
run: docker compose exec -T php bin/console -e test app:index-products
|
||||||
|
- name: PHPUnit
|
||||||
|
run: docker compose exec -T php bin/phpunit
|
||||||
|
- name: Doctrine Schema Validator
|
||||||
|
run: docker compose exec -T php bin/console doctrine:schema:validate --skip-sync
|
||||||
|
- name: PHP CS Fixer
|
||||||
|
run: docker compose exec -T php sh -c './vendor/bin/php-cs-fixer fix --allow-risky=yes --dry-run --format=checkstyle | ./vendor/bin/cs2pr'
|
||||||
|
- name: PHPStan
|
||||||
|
run: docker compose exec -T php ./vendor/bin/phpstan analyse --memory-limit=-1 --error-format=github
|
||||||
|
- name: Twig Linter
|
||||||
|
run: docker compose exec -T php ./vendor/bin/twigcs templates/ --exclude vendor
|
||||||
|
- name: Install eslint
|
||||||
|
run: docker run --rm -w "/usr/app" -v "${PWD}":/usr/app gmolaire/yarn yarn add eslint
|
||||||
|
- name: Run eslint on javascript files
|
||||||
|
run: docker run --rm -w "/usr/app" -v "${PWD}":/usr/app gmolaire/yarn yarn lint
|
||||||
33
.github/workflows/cleanup.yml
vendored
Normal file
33
.github/workflows/cleanup.yml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
name: Cleanup
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [ closed ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cleanup:
|
||||||
|
name: Cleanup
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set KUBECONFIG
|
||||||
|
run: |
|
||||||
|
mkdir ~/.kube
|
||||||
|
echo ${{ secrets.KUBECONFIG }} | base64 -d > ~/.kube/config
|
||||||
|
kubectl config view
|
||||||
|
|
||||||
|
- name: Uninstall helm release
|
||||||
|
id: uninstall_helm_release
|
||||||
|
run: |
|
||||||
|
export RELEASE_NAME=pr-$(jq --raw-output .pull_request.number $GITHUB_EVENT_PATH)
|
||||||
|
echo "Uninstalling release ${RELEASE_NAME}"
|
||||||
|
if ! helm uninstall ${RELEASE_NAME} --kube-context nonprod --wait ; then
|
||||||
|
echo "HELM Uninstall has failed !"
|
||||||
|
echo "Please ask the SRE team to manually clean remaining objects"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "HELM uninstall successfull"
|
||||||
|
echo "Cleaning remaining PVC..."
|
||||||
|
kubectl delete pvc -l app.kubernetes.io/instance=$RELEASE_NAME
|
||||||
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
/.env.local
|
||||||
|
/.env.local.php
|
||||||
|
/.env.*.local
|
||||||
|
/config/secrets/prod/prod.decrypt.private.php
|
||||||
|
/public/bundles/
|
||||||
|
/var/
|
||||||
|
/vendor/
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> friendsofphp/php-cs-fixer ###
|
||||||
|
/.php-cs-fixer.php
|
||||||
|
/.php-cs-fixer.cache
|
||||||
|
###< friendsofphp/php-cs-fixer ###
|
||||||
|
|
||||||
|
###> symfony/phpunit-bridge ###
|
||||||
|
###< symfony/phpunit-bridge ###
|
||||||
|
|
||||||
|
###> phpunit/phpunit ###
|
||||||
|
/phpunit.xml
|
||||||
|
.phpunit.result.cache
|
||||||
|
docs/coverage
|
||||||
|
###< phpunit/phpunit ###
|
||||||
|
|
||||||
|
###> symfony/webpack-encore-bundle ###
|
||||||
|
/node_modules/
|
||||||
|
/public/build/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
###< symfony/webpack-encore-bundle ###
|
||||||
|
|
||||||
|
###> league/flysystem-bundle ###
|
||||||
|
storage
|
||||||
|
###< league/flysystem-bundle ###
|
||||||
27
.php-cs-fixer.dist.php
Normal file
27
.php-cs-fixer.dist.php
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
// https://cs.symfony.com/
|
||||||
|
|
||||||
|
$finder = PhpCsFixer\Finder::create()
|
||||||
|
->in(__DIR__)
|
||||||
|
->exclude('var')
|
||||||
|
->exclude('tmp')
|
||||||
|
->exclude('node_modules')
|
||||||
|
;
|
||||||
|
|
||||||
|
return (new PhpCsFixer\Config())->setRules([
|
||||||
|
'@Symfony' => true,
|
||||||
|
'array_syntax' => ['syntax' => 'short'], // https://cs.symfony.com/doc/rules/array_notation/array_syntax.html
|
||||||
|
'declare_strict_types' => true, // https://cs.symfony.com/doc/rules/strict/declare_strict_types.html
|
||||||
|
'php_unit_fqcn_annotation' => false, // https://cs.symfony.com/doc/rules/php_unit/php_unit_fqcn_annotation.html
|
||||||
|
'yoda_style' => false, // https://cs.symfony.com/doc/rules/control_structure/yoda_style.html
|
||||||
|
'phpdoc_to_comment' => false, // https://cs.symfony.com/doc/rules/phpdoc/phpdoc_to_comment.html # Needed for PHPStan @var annotations
|
||||||
|
'native_function_invocation' => [ // https://cs.symfony.com/doc/rules/function_notation/native_function_invocation.html
|
||||||
|
'include' => ['@compiler_optimized'], // https://cs.symfony.com/doc/rules/function_notation/native_function_invocation.html#include
|
||||||
|
'scope' => 'namespaced', // https://cs.symfony.com/doc/rules/function_notation/native_function_invocation.html#scope
|
||||||
|
'strict' => true // https://cs.symfony.com/doc/rules/function_notation/native_function_invocation.html#strict
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->setFinder($finder);
|
||||||
0
.trivyignore
Normal file
0
.trivyignore
Normal file
213
Dockerfile
Normal file
213
Dockerfile
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
# the different stages of this Dockerfile are meant to be built into separate images
|
||||||
|
# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage
|
||||||
|
# https://docs.docker.com/compose/compose-file/#target
|
||||||
|
|
||||||
|
|
||||||
|
# https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
|
||||||
|
ARG PHP_VERSION=8.1
|
||||||
|
ARG CADDY_VERSION=2
|
||||||
|
|
||||||
|
# yarn build
|
||||||
|
FROM gmolaire/yarn AS yarn_build
|
||||||
|
WORKDIR /usr/app
|
||||||
|
RUN apt-get update && apt-get install tar
|
||||||
|
RUN mkdir -p /usr/app/vendor/symfony
|
||||||
|
RUN curl -L https://github.com/symfony/ux-autocomplete/archive/v2.7.1.tar.gz -o ux-autocomplete.tar.gz
|
||||||
|
RUN tar -xzvf ux-autocomplete.tar.gz --directory /usr/app/vendor/symfony
|
||||||
|
RUN mv /usr/app/vendor/symfony/ux-autocomplete-2.7.1 /usr/app/vendor/symfony/ux-autocomplete
|
||||||
|
COPY package.json yarn.lock .
|
||||||
|
RUN yarn install
|
||||||
|
COPY . .
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
# Prod image
|
||||||
|
FROM php:${PHP_VERSION}-fpm-alpine AS app_php
|
||||||
|
|
||||||
|
# needed for security update until base image is updated
|
||||||
|
RUN apk upgrade libcurl curl openssl openssl-dev libressl libcrypto3 libssl3
|
||||||
|
|
||||||
|
# Allow to use development versions of Symfony
|
||||||
|
ARG STABILITY="stable"
|
||||||
|
ENV STABILITY ${STABILITY}
|
||||||
|
|
||||||
|
# Allow to select Symfony version
|
||||||
|
ARG SYMFONY_VERSION=""
|
||||||
|
ENV SYMFONY_VERSION ${SYMFONY_VERSION}
|
||||||
|
|
||||||
|
ENV APP_ENV=prod
|
||||||
|
|
||||||
|
WORKDIR /srv/app
|
||||||
|
|
||||||
|
# php extensions installer: https://github.com/mlocati/docker-php-extension-installer
|
||||||
|
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
|
||||||
|
RUN chmod +x /usr/local/bin/install-php-extensions
|
||||||
|
|
||||||
|
# persistent / runtime deps
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
acl \
|
||||||
|
fcgi \
|
||||||
|
file \
|
||||||
|
gettext \
|
||||||
|
git \
|
||||||
|
nghttp2 \
|
||||||
|
libcrypto3 \
|
||||||
|
libssl3 \
|
||||||
|
;
|
||||||
|
|
||||||
|
RUN set -eux; \
|
||||||
|
install-php-extensions \
|
||||||
|
intl \
|
||||||
|
zip \
|
||||||
|
apcu \
|
||||||
|
opcache \
|
||||||
|
xsl \
|
||||||
|
redis \
|
||||||
|
bcmath \
|
||||||
|
;
|
||||||
|
|
||||||
|
###> doctrine/doctrine-bundle ###
|
||||||
|
RUN apk add --no-cache --virtual .pgsql-deps postgresql-dev; \
|
||||||
|
docker-php-ext-install -j$(nproc) pdo_pgsql; \
|
||||||
|
apk add --no-cache --virtual .pgsql-rundeps so:libpq.so.5; \
|
||||||
|
apk del .pgsql-deps
|
||||||
|
###< doctrine/doctrine-bundle ###
|
||||||
|
###< recipes ###
|
||||||
|
|
||||||
|
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||||
|
COPY docker/php/conf.d/app.ini $PHP_INI_DIR/conf.d/
|
||||||
|
COPY docker/php/conf.d/app.prod.ini $PHP_INI_DIR/conf.d/
|
||||||
|
|
||||||
|
COPY docker/php/php-fpm.d/zz-docker.conf /usr/local/etc/php-fpm.d/zz-docker.conf
|
||||||
|
RUN mkdir -p /var/run/php
|
||||||
|
|
||||||
|
COPY docker/php/docker-healthcheck.sh /usr/local/bin/docker-healthcheck
|
||||||
|
RUN chmod +x /usr/local/bin/docker-healthcheck
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD ["docker-healthcheck"]
|
||||||
|
|
||||||
|
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"]
|
||||||
|
|
||||||
|
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
|
||||||
|
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||||
|
ENV PATH="${PATH}:/root/.composer/vendor/bin"
|
||||||
|
|
||||||
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
RUN chown -R www-data: /srv/app/ /var/run/php/
|
||||||
|
|
||||||
|
# prevent the reinstallation of vendors at every changes in the source code
|
||||||
|
USER www-data
|
||||||
|
COPY --chown=www-data:www-data composer.* symfony.* ./
|
||||||
|
RUN set -eux; \
|
||||||
|
if [ -f composer.json ]; then \
|
||||||
|
composer install --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress; \
|
||||||
|
composer clear-cache; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# copy sources
|
||||||
|
COPY --chown=www-data:www-data . .
|
||||||
|
RUN rm -Rf docker/
|
||||||
|
|
||||||
|
RUN set -eux; \
|
||||||
|
mkdir -p var/cache var/log; \
|
||||||
|
if [ -f composer.json ]; then \
|
||||||
|
composer dump-autoload --classmap-authoritative --no-dev; \
|
||||||
|
composer dump-env prod; \
|
||||||
|
COMPOSER_MEMORY_LIMIT=-1 composer run-script --no-dev post-install-cmd; \
|
||||||
|
chmod +x bin/console; sync; \
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# copy yarn build output
|
||||||
|
COPY --from=yarn_build --chown=www-data:www-data /usr/app/public/build/ public/build/
|
||||||
|
|
||||||
|
# Dev image
|
||||||
|
FROM app_php AS app_php_dev
|
||||||
|
|
||||||
|
USER root
|
||||||
|
|
||||||
|
###> recipes ###
|
||||||
|
###> symfony/panther ###
|
||||||
|
# Chromium and ChromeDriver
|
||||||
|
ENV PANTHER_NO_SANDBOX 1
|
||||||
|
# Not mandatory, but recommended
|
||||||
|
ENV PANTHER_CHROME_ARGUMENTS='--disable-dev-shm-usage'
|
||||||
|
RUN apk add --no-cache chromium chromium-chromedriver
|
||||||
|
|
||||||
|
# Firefox and geckodriver
|
||||||
|
#ARG GECKODRIVER_VERSION=0.29.0
|
||||||
|
#RUN apk add --no-cache firefox
|
||||||
|
#RUN wget -q https://github.com/mozilla/geckodriver/releases/download/v$GECKODRIVER_VERSION/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz; \
|
||||||
|
# tar -zxf geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz -C /usr/bin; \
|
||||||
|
# rm geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz
|
||||||
|
###< symfony/panther ###
|
||||||
|
|
||||||
|
|
||||||
|
# Additional dev tools (graphviz is to have the dot program to generate the workflows' graphs)
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
make \
|
||||||
|
nano \
|
||||||
|
vim \
|
||||||
|
neovim \
|
||||||
|
graphviz \
|
||||||
|
;
|
||||||
|
|
||||||
|
# Load aliases at interactive shell (sh -l)
|
||||||
|
ENV ENV="/etc/profile"
|
||||||
|
|
||||||
|
ENV APP_ENV=dev XDEBUG_MODE=off
|
||||||
|
USER www-data
|
||||||
|
# We must create directories to avoid problems with EasyAdmin which checks rights
|
||||||
|
# even a cloud storgae is used (thoses directories will stay empty when a cloud
|
||||||
|
# storage is used).
|
||||||
|
RUN mkdir -p /srv/app/public/storage/uploads/category
|
||||||
|
RUN mkdir -p /srv/app/public/storage/uploads/menu
|
||||||
|
RUN mkdir -p /srv/app/public/storage/uploads/product
|
||||||
|
RUN mkdir -p /srv/app/public/storage/uploads/user
|
||||||
|
|
||||||
|
USER root
|
||||||
|
VOLUME /srv/app/var/
|
||||||
|
|
||||||
|
RUN rm $PHP_INI_DIR/conf.d/app.prod.ini; \
|
||||||
|
mv "$PHP_INI_DIR/php.ini" "$PHP_INI_DIR/php.ini-production"; \
|
||||||
|
mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
|
||||||
|
|
||||||
|
COPY docker/php/conf.d/app.dev.ini $PHP_INI_DIR/conf.d/
|
||||||
|
|
||||||
|
RUN set -eux; \
|
||||||
|
install-php-extensions xdebug
|
||||||
|
|
||||||
|
RUN rm -f .env.local.php
|
||||||
|
|
||||||
|
# Build Caddy with the Mercure and Vulcain modules
|
||||||
|
# FROM caddy:${CADDY_VERSION}-builder-alpine AS app_caddy_builder
|
||||||
|
|
||||||
|
# Temporary fix for https://github.com/dunglas/mercure/issues/770
|
||||||
|
# https://github.com/dunglas/symfony-docker/pull/407/files
|
||||||
|
|
||||||
|
FROM caddy:2.7-builder-alpine AS app_caddy_builder
|
||||||
|
|
||||||
|
# RUN xcaddy build \
|
||||||
|
# --with github.com/dunglas/mercure \
|
||||||
|
# --with github.com/dunglas/mercure/caddy \
|
||||||
|
# --with github.com/dunglas/vulcain \
|
||||||
|
# --with github.com/dunglas/vulcain/caddy
|
||||||
|
|
||||||
|
RUN xcaddy build \
|
||||||
|
--with github.com/dunglas/mercure/caddy \
|
||||||
|
--with github.com/dunglas/vulcain/caddy
|
||||||
|
|
||||||
|
# Caddy image
|
||||||
|
FROM caddy:${CADDY_VERSION} AS app_caddy
|
||||||
|
|
||||||
|
# needed for security update until base image is updated
|
||||||
|
RUN apk upgrade libcurl curl openssl openssl-dev libressl libcrypto1.1 libssl1.1 libcrypto3 libssl3
|
||||||
|
|
||||||
|
WORKDIR /srv/app
|
||||||
|
|
||||||
|
COPY --from=app_caddy_builder /usr/bin/caddy /usr/bin/caddy
|
||||||
|
COPY --from=app_php /srv/app/public public/
|
||||||
|
COPY docker/caddy/Caddyfile /etc/caddy/Caddyfile
|
||||||
180
ERRORS.md
Normal file
180
ERRORS.md
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
# Errors
|
||||||
|
|
||||||
|
This documention gives solutions for some errors occuring in the project.
|
||||||
|
|
||||||
|
## 1. Makefile
|
||||||
|
|
||||||
|
### Error 1.1
|
||||||
|
|
||||||
|
plateformcoop-ebs$ docker compose exec php ./vendor/bin/php-cs-fixer fix --allow-risky=yes
|
||||||
|
OCI runtime exec failed: exec failed: unable to start container process: exec: "./vendor/bin/php-cs-fixer": permission denied: unknown
|
||||||
|
|
||||||
|
### Solution 1.1
|
||||||
|
|
||||||
|
Verify that the executables in `vendor/bin`have the executblale right:
|
||||||
|
|
||||||
|
cd /srv/app/vendor/bin; chmod +x *
|
||||||
|
|
||||||
|
|
||||||
|
## 2. PHPStan
|
||||||
|
|
||||||
|
### Error 2.1
|
||||||
|
|
||||||
|
tests/Integration/Translator/NotranslatorTest.php
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Service "App\Translator\NoTranslator" is not registered in the container.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
### Solution 2.1
|
||||||
|
|
||||||
|
To resolve this error, run:
|
||||||
|
|
||||||
|
make stan-cc
|
||||||
|
|
||||||
|
|
||||||
|
## 3. PHPUnit
|
||||||
|
|
||||||
|
### Error 3.1
|
||||||
|
|
||||||
|
..........................................make: *** [Makefile:159: test] Error 137
|
||||||
|
|
||||||
|
### Solution 3.1
|
||||||
|
|
||||||
|
Check if there is no `dump()` in a loop.
|
||||||
|
|
||||||
|
### Error 3.2
|
||||||
|
|
||||||
|
..................make: *** [test] Error 139
|
||||||
|
|
||||||
|
### Solution 3.2
|
||||||
|
|
||||||
|
It seems to be a temporary Docker error. Run again the tests. Try the debug mode
|
||||||
|
`make test-debug` if the error is still there to find the faulty tests.
|
||||||
|
|
||||||
|
|
||||||
|
### Error 3.3
|
||||||
|
|
||||||
|
```
|
||||||
|
1) App\Tests\Functional\Controller\User\ServiceRequest\ServiceRequestStatusWorkflowControllerRefuseTest::testTransitionRefuseSuccess
|
||||||
|
|
||||||
|
LogicException: The selected node does not have a form ancestor.
|
||||||
|
|
||||||
|
/srv/app/vendor/symfony/dom-crawler/Form.php:372
|
||||||
|
/srv/app/vendor/symfony/dom-crawler/AbstractUriElement.php:45
|
||||||
|
/srv/app/vendor/symfony/dom-crawler/Form.php:38
|
||||||
|
/srv/app/vendor/symfony/dom-crawler/Crawler.php:838
|
||||||
|
/srv/app/tests/Functional/Controller/User/ServiceRequest/ServiceRequestStatusWorkflowControllerRefuseTest.php:35
|
||||||
|
```
|
||||||
|
|
||||||
|
It's because we have the same traduction in two places.
|
||||||
|
|
||||||
|
```
|
||||||
|
<div class="d-grid col mt-2">
|
||||||
|
<button type="button" class="btn btn-danger"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#refuseModal">
|
||||||
|
<i class="bi bi-x"></i>
|
||||||
|
{{ (i18n_prefix ~ '.link.refuse')|trans }} <== HERE
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<button type="submit"
|
||||||
|
class="btn btn-danger">
|
||||||
|
{{ (i18n_prefix ~ '.link.refuse')|trans }} <== AND HERE
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Solution 3.2
|
||||||
|
|
||||||
|
```
|
||||||
|
<div class="d-grid col mt-2">
|
||||||
|
<button type="button" class="btn btn-danger"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#refuseModal">
|
||||||
|
<i class="bi bi-x"></i>
|
||||||
|
{{ (i18n_prefix ~ '.link.refuse_modal')|trans }} <== CHANGE FIRST KEY TRADE
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the traduction key for the first button
|
||||||
|
|
||||||
|
|
||||||
|
## 4. Geocoding/Nominatim
|
||||||
|
|
||||||
|
### Error 4.1
|
||||||
|
|
||||||
|
Error for all the geocoding tests (poc or modify my address):
|
||||||
|
|
||||||
|
ErrorException: Handling "App\Message\Query\Admin\User\UserAddressQuery" failed: Serialization of 'Closure' is not allowed
|
||||||
|
in /srv/app/vendor/symfony/messenger/Middleware/HandleMessageMiddleware.php:129
|
||||||
|
|
||||||
|
It is because the Nominatim service is down (error 502, bad gateway).
|
||||||
|
Disable the cache in `config/packages/bazinga_geocoder.yaml` to see the real error:
|
||||||
|
|
||||||
|
The geocoder server returned an invalid response (502) for query "https://nominatim.openstreetmap.org/search?format=jsonv2&q=Timipi%2C%20Fives%2C%20france&addressdetails=1&extratags=1&limit=3&accept-language=fr".
|
||||||
|
We could not parse it.
|
||||||
|
|
||||||
|
https://nominatim.openstreetmap.org/search?format=jsonv2&q=Timipi%2C%20Fives%2C%20france&addressdetails=1&extratags=1&limit=3&accept-language=fr"
|
||||||
|
|
||||||
|
502 Bad Gateway
|
||||||
|
nginx
|
||||||
|
|
||||||
|
### Solution 4.1
|
||||||
|
|
||||||
|
Wait.
|
||||||
|
|
||||||
|
It would be nice if the bundle could hande this error correclty and at least return
|
||||||
|
an empty results array if there is such an error.
|
||||||
|
As it is made now, we can't catch this error, which is quite problematic.
|
||||||
|
Create a new issue on the bundle to see what can be done.
|
||||||
|
|
||||||
|
### Todo for 4.1
|
||||||
|
|
||||||
|
Use mocks for the test env.
|
||||||
|
|
||||||
|
|
||||||
|
## 5. Docker
|
||||||
|
|
||||||
|
### Error 5.1
|
||||||
|
|
||||||
|
When running a command with make like `make cs` we have he error:
|
||||||
|
|
||||||
|
OCI runtime exec failed: exec failed: unable to start container process: read init-p: connection reset by peer: unknown
|
||||||
|
|
||||||
|
### Solution 5.1
|
||||||
|
|
||||||
|
Restart Docker.
|
||||||
|
|
||||||
|
|
||||||
|
## 6. Symfony
|
||||||
|
|
||||||
|
### Error 6.1
|
||||||
|
|
||||||
|
When trying to access a controller we just created:
|
||||||
|
|
||||||
|
Could not resolve argument $productId of "App\Controller\User\Product\DeleteProductAction::__invoke()", maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?
|
||||||
|
|
||||||
|
### Solution 6.1
|
||||||
|
|
||||||
|
There is a mismatch between the arguments of the controller action and the route
|
||||||
|
requirements, fix them (eg: `productId` instead of `id`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 7. Meilisearch
|
||||||
|
|
||||||
|
### Error 7.1
|
||||||
|
|
||||||
|
When indexing a document:
|
||||||
|
|
||||||
|
The primary key inference failed as the engine found 2 fields ending with `id` in their names: 'id' and 'ownerId'.
|
||||||
|
Please specify the primary key manually using the `primaryKey` query parameter?
|
||||||
|
|
||||||
|
### Solution 6.1
|
||||||
|
|
||||||
|
The primary key must specified to avoid confusion. It can be set using the second
|
||||||
|
argument of the `addDocument()` functions.
|
||||||
|
|
||||||
|
$this->getIndex()->addDocuments([$this->normalizeProduct($product)], self::PRIMARY_KEY);
|
||||||
680
LICENSE
680
LICENSE
|
|
@ -1,661 +1,19 @@
|
||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
Copyright (c) Fabien Potencier
|
||||||
Version 3, 19 November 2007
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
in the Software without restriction, including without limitation the rights
|
||||||
of this license document, but changing it is not allowed.
|
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
|
||||||
Preamble
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
The GNU Affero General Public License is a free, copyleft license for
|
The above copyright notice and this permission notice shall be included in all
|
||||||
software and other kinds of works, specifically designed to ensure
|
copies or substantial portions of the Software.
|
||||||
cooperation with the community in the case of network server software.
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
The licenses for most software and other practical works are designed
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
to take away your freedom to share and change the works. By contrast,
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
our General Public Licenses are intended to guarantee your freedom to
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
share and change all versions of a program--to make sure it remains free
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
software for all its users.
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
Developers that use our General Public Licenses protect your rights
|
|
||||||
with two steps: (1) assert copyright on the software, and (2) offer
|
|
||||||
you this License which gives you legal permission to copy, distribute
|
|
||||||
and/or modify the software.
|
|
||||||
|
|
||||||
A secondary benefit of defending all users' freedom is that
|
|
||||||
improvements made in alternate versions of the program, if they
|
|
||||||
receive widespread use, become available for other developers to
|
|
||||||
incorporate. Many developers of free software are heartened and
|
|
||||||
encouraged by the resulting cooperation. However, in the case of
|
|
||||||
software used on network servers, this result may fail to come about.
|
|
||||||
The GNU General Public License permits making a modified version and
|
|
||||||
letting the public access it on a server without ever releasing its
|
|
||||||
source code to the public.
|
|
||||||
|
|
||||||
The GNU Affero General Public License is designed specifically to
|
|
||||||
ensure that, in such cases, the modified source code becomes available
|
|
||||||
to the community. It requires the operator of a network server to
|
|
||||||
provide the source code of the modified version running there to the
|
|
||||||
users of that server. Therefore, public use of a modified version, on
|
|
||||||
a publicly accessible server, gives the public access to the source
|
|
||||||
code of the modified version.
|
|
||||||
|
|
||||||
An older license, called the Affero General Public License and
|
|
||||||
published by Affero, was designed to accomplish similar goals. This is
|
|
||||||
a different license, not a version of the Affero GPL, but Affero has
|
|
||||||
released a new version of the Affero GPL which permits relicensing under
|
|
||||||
this license.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, if you modify the
|
|
||||||
Program, your modified version must prominently offer all users
|
|
||||||
interacting with it remotely through a computer network (if your version
|
|
||||||
supports such interaction) an opportunity to receive the Corresponding
|
|
||||||
Source of your version by providing access to the Corresponding Source
|
|
||||||
from a network server at no charge, through some standard or customary
|
|
||||||
means of facilitating copying of software. This Corresponding Source
|
|
||||||
shall include the Corresponding Source for any work covered by version 3
|
|
||||||
of the GNU General Public License that is incorporated pursuant to the
|
|
||||||
following paragraph.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the work with which it is combined will remain governed by version
|
|
||||||
3 of the GNU General Public License.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU Affero General Public License from time to time. Such new versions
|
|
||||||
will be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU Affero General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU Affero General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU Affero General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published
|
|
||||||
by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If your software can interact with users remotely through a computer
|
|
||||||
network, you should also make sure that it provides a way for users to
|
|
||||||
get its source. For example, if your program is a web application, its
|
|
||||||
interface could display a "Source" link that leads users to an archive
|
|
||||||
of the code. There are many ways you could offer source, and different
|
|
||||||
solutions will be better for different programs; see section 13 for the
|
|
||||||
specific requirements.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
||||||
|
|
|
||||||
233
Makefile
Normal file
233
Makefile
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
# Config
|
||||||
|
CURRENT_UID := $(shell id -u)
|
||||||
|
CURRENT_GID := $(shell id -g)
|
||||||
|
|
||||||
|
SHELL = sh
|
||||||
|
REDIS_PORT = 6389
|
||||||
|
|
||||||
|
# Executables (local)
|
||||||
|
DOCKER = docker
|
||||||
|
DOCKER_COMP = docker compose
|
||||||
|
REDIS = redis-cli
|
||||||
|
|
||||||
|
# Docker containers
|
||||||
|
PHP_CONT = $(DOCKER_COMP) exec php
|
||||||
|
|
||||||
|
# see https://hub.docker.com/r/gmolaire/yarn
|
||||||
|
YARN_CONT = $(DOCKER) run -it --rm -w "/usr/app" -v "${PWD}":/usr/app gmolaire/yarn yarn
|
||||||
|
|
||||||
|
# Main executables
|
||||||
|
PHP = $(PHP_CONT) php
|
||||||
|
COMPOSER = $(PHP_CONT) composer
|
||||||
|
SYMFONY = $(PHP_CONT) bin/console
|
||||||
|
PHPUNIT = $(PHP_CONT) bin/phpunit
|
||||||
|
|
||||||
|
# Vendors executables
|
||||||
|
PHPSTAN = $(PHP_CONT) ./vendor/bin/phpstan
|
||||||
|
PHP_CS_FIXER = $(PHP_CONT) ./vendor/bin/php-cs-fixer
|
||||||
|
TWIGCS = $(PHP_CONT) ./vendor/bin/twigcs
|
||||||
|
RECTOR = $(PHP_CONT) ./vendor/bin/rector
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DEFAULT_GOAL = help
|
||||||
|
.PHONY = help build up start down logs sh composer vendor sf cc ci cs lint-twigcs
|
||||||
|
|
||||||
|
## —— 🎵 🐳 The Symfony Docker Makefile 🐳 🎵 —————————————————————————————————
|
||||||
|
help: ## Outputs this help screen
|
||||||
|
@grep -E '(^[a-zA-Z0-9_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'
|
||||||
|
|
||||||
|
## —— Docker 🐳 ————————————————————————————————————————————————————————————————
|
||||||
|
build: ## Builds the Docker images
|
||||||
|
@$(DOCKER_COMP) build --pull
|
||||||
|
|
||||||
|
up: ## Start the docker hub in detached mode (no logs)
|
||||||
|
@$(DOCKER_COMP) up -d
|
||||||
|
|
||||||
|
wait: ## Waits for all containers to be ready
|
||||||
|
@$(DOCKER_COMP) up --wait
|
||||||
|
|
||||||
|
start: ## Starts the main containers (load-fixtures must be done so the caddy service can be healthy)
|
||||||
|
start: up yarn-install load-fixtures yarn-dev wait
|
||||||
|
|
||||||
|
start-dev: ## Start additional and optional dev tools in the docker-compose.override.yml.dist file
|
||||||
|
@$(DOCKER_COMP) -f docker-compose.override.yml.dist up --wait
|
||||||
|
|
||||||
|
stop: ## Stop and remove the docker containers (and volumes) of the project
|
||||||
|
@$(DOCKER_COMP) down -v --remove-orphans
|
||||||
|
|
||||||
|
logs: ## Show live logs
|
||||||
|
@$(DOCKER_COMP) logs --tail=0 --follow
|
||||||
|
|
||||||
|
sh: ## Connect to the PHP FPM container
|
||||||
|
@$(PHP_CONT) sh -l
|
||||||
|
|
||||||
|
linux-fix-perms: ## Fix permissions on Linux
|
||||||
|
$(PHP_CONT) chown -R $(CURRENT_UID):$(CURRENT_GID) .
|
||||||
|
|
||||||
|
## —— Composer 🧙 ——————————————————————————————————————————————————————————————
|
||||||
|
composer: ## Run composer, pass the parameter "c=" to run a given command, example: make composer c='req symfony/orm-pack'
|
||||||
|
@$(eval c ?=)
|
||||||
|
@$(COMPOSER) $(c)
|
||||||
|
|
||||||
|
vendor: composer.lock ## Install vendors according to the current composer.lock file
|
||||||
|
vendor: c=install --prefer-dist --no-progress --no-scripts --no-interaction
|
||||||
|
vendor: composer
|
||||||
|
|
||||||
|
## —— Symfony 🎵 ———————————————————————————————————————————————————————————————
|
||||||
|
sf: ## List all Symfony commands or pass the parameter "c=" to run a given command, example: make sf c=about
|
||||||
|
@$(eval env ?= 'dev')
|
||||||
|
@$(eval c ?=)
|
||||||
|
@$(SYMFONY) $(c) --env=$(env)
|
||||||
|
|
||||||
|
cc: c=c:c ## Clear the cache
|
||||||
|
cc: sf
|
||||||
|
|
||||||
|
purge: ## Purge the all vars files manually
|
||||||
|
@$(PHP_CONT) sh -c "rm -rf /srv/app/var/*"
|
||||||
|
|
||||||
|
## —— Coding standards ✨ ——————————————————————————————————————————————————————
|
||||||
|
stan: ## Run PHPStan. Use the 'path' parameter to check a given file only: make stan path=src/Services/ControllerHelper.php
|
||||||
|
$(eval path ?= )
|
||||||
|
@$(PHPSTAN) analyse -c phpstan.neon --memory-limit 1G -vvv $(path)
|
||||||
|
|
||||||
|
stan-cc: ## Clear manually the PHPStan result cache
|
||||||
|
@$(PHPSTAN) clear-result-cache
|
||||||
|
|
||||||
|
lint-php: ## Lint files with php-cs-fixer (just use fix-php)
|
||||||
|
$(PHP_CS_FIXER) fix --dry-run --allow-risky=yes
|
||||||
|
|
||||||
|
lint-twig: ## Lint Twig files to check they are well formatted (no parse error)
|
||||||
|
@$(SYMFONY) lint:twig --env=dev
|
||||||
|
|
||||||
|
lint-twigcs: ## Check Twig coding style
|
||||||
|
@$(TWIGCS) templates/ --exclude vendor
|
||||||
|
|
||||||
|
lint-container: ## Check there is no problem with the container
|
||||||
|
@$(SYMFONY) lint:container
|
||||||
|
|
||||||
|
lint-yaml: ## Check all YAML files are well formatted
|
||||||
|
@$(SYMFONY) lint:yaml --parse-tags config/ translations/ templates/
|
||||||
|
|
||||||
|
fix-php: ## Fix files with php-cs-fixer
|
||||||
|
@$(PHP_CS_FIXER) fix --allow-risky=yes
|
||||||
|
|
||||||
|
rector: ## Run rector with current rules in rector.php
|
||||||
|
@$(RECTOR) process src/
|
||||||
|
|
||||||
|
ci: ## Run pre-commit checks to ensure the CI will be green
|
||||||
|
ci: cs lint-yaml lint-container lint-twig lint-twigcs yarn-lint doctrine-validate test-complete
|
||||||
|
|
||||||
|
cs: ## Run PHPStan and php-cs-fixer only
|
||||||
|
cs: fix-php stan
|
||||||
|
|
||||||
|
## —— Project ——————————————————————————————————————————————————————————————————
|
||||||
|
load-fixtures: drop-db ## Build the DB, control the schema validity, load fixtures and check the migration status (deb)
|
||||||
|
$(eval env ?= 'dev')
|
||||||
|
@$(SYMFONY) doctrine:database:create --if-not-exists --env=$(env)
|
||||||
|
@$(SYMFONY) doctrine:schema:create --env=$(env)
|
||||||
|
@$(SYMFONY) doctrine:schema:validate --env=$(env)
|
||||||
|
@$(SYMFONY) doctrine:migrations:migrate --env=$(env) --no-interaction
|
||||||
|
@$(SYMFONY) messenger:setup-transports --env=$(env)
|
||||||
|
@$(SYMFONY) hautelook:fixtures:load --no-interaction -vv --no-bundles --env=$(env)
|
||||||
|
@$(SYMFONY) app:index-products --env=$(env)
|
||||||
|
|
||||||
|
drop-db: ## Delete the whole database, useful when having integrity problems for data or constraints
|
||||||
|
$(eval env ?= 'dev')
|
||||||
|
@$(SYMFONY) doctrine:database:drop --env=$(env) --if-exists --force
|
||||||
|
|
||||||
|
load-test-fixtures: env=test ## Allows to use the test fixtures to debug problems
|
||||||
|
load-test-fixtures: load-fixtures
|
||||||
|
|
||||||
|
load-prod-fixtures: env=prod
|
||||||
|
load-prod-fixtures: load-fixtures ## Same than load-fixtures but with only minimum data
|
||||||
|
|
||||||
|
cache-clear: ## Clear the application cache (used for tests)
|
||||||
|
$(eval env ?= 'dev')
|
||||||
|
@$(SYMFONY) c:c --env=$(env)
|
||||||
|
@$(SYMFONY) cache:pool:clear cache.app --env=$(env)
|
||||||
|
|
||||||
|
doctrine-validate: ## Validate the doctrine schema
|
||||||
|
$(eval env ?= 'dev')
|
||||||
|
@$(SYMFONY) doctrine:schema:validate --env=$(env)
|
||||||
|
|
||||||
|
doctrine-migrate: ## Run all the available Doctrine migrations
|
||||||
|
@$(SYMFONY) doctrine:migrations:migrate --no-interaction
|
||||||
|
|
||||||
|
meilisearch-index:
|
||||||
|
$(eval env ?= 'dev')
|
||||||
|
@$(SYMFONY) app:index-products --env=$(env)
|
||||||
|
|
||||||
|
|
||||||
|
## —— Tests ✅ —————————————————————————————————————————————————————————————————
|
||||||
|
test: ## Run tests with optional suite, filter and options
|
||||||
|
@$(eval testsuite ?= 'all')
|
||||||
|
@$(eval filter ?= '.')
|
||||||
|
@$(eval options ?= '--stop-on-failure')
|
||||||
|
@$(PHPUNIT) --testsuite=$(testsuite) --filter=$(filter) $(options)
|
||||||
|
|
||||||
|
test-complete: ## Run all tests without stopping on the first error
|
||||||
|
test-complete: env=test
|
||||||
|
test-complete: options=
|
||||||
|
test-complete: cc load-fixtures test
|
||||||
|
|
||||||
|
test-debug: ## Run all tests in debug mode
|
||||||
|
test-debug: env=test
|
||||||
|
test-debug: options=--debug --stop-on-failure
|
||||||
|
test-debug: cc load-fixtures test
|
||||||
|
|
||||||
|
test-unit: ## Run unit tests only
|
||||||
|
test-unit: env=test
|
||||||
|
test-unit: testsuite=unit
|
||||||
|
test-unit: test
|
||||||
|
|
||||||
|
test-api: ## Run API tests only
|
||||||
|
test-api: env=test
|
||||||
|
test-api: testsuite=api
|
||||||
|
test-api: test
|
||||||
|
|
||||||
|
test-integration: ## Run integration tests only
|
||||||
|
test-integration: env=test
|
||||||
|
test-integration: testsuite=integration
|
||||||
|
test-integration: load-test-fixtures test
|
||||||
|
|
||||||
|
test-functional: ## Run functional tests only
|
||||||
|
test-functional: env=test
|
||||||
|
test-functional: testsuite=functional
|
||||||
|
test-functional: load-test-fixtures test
|
||||||
|
|
||||||
|
test-e2e: ## Run E2E tests only
|
||||||
|
test-e2e: env=test
|
||||||
|
test-e2e: load-test-fixtures test
|
||||||
|
|
||||||
|
coverage: ## Generate the HTML PHPUnit code coverage report locally
|
||||||
|
coverage: env=test
|
||||||
|
coverage: load-test-fixtures
|
||||||
|
# Cache must be generated by PHPUnit so it can run compiler passes
|
||||||
|
@$(PHP_CONT) sh -c "rm -rf /srv/app/var/cache/test"
|
||||||
|
@$(DOCKER_COMP) exec -e XDEBUG_MODE=coverage php php -d xdebug.enable=1 -d memory_limit=-1 bin/phpunit --coverage-html=docs/coverage
|
||||||
|
|
||||||
|
## —— Debug 🐞——————————————————————————————————————————————————————————————————
|
||||||
|
redis: ## Connect to redis with CLI (redis-cli must be installed locally)
|
||||||
|
@$(REDIS) -p $(REDIS_PORT)
|
||||||
|
|
||||||
|
redis-cc: ## Flush all Redis cache
|
||||||
|
@$(REDIS) -p $(REDIS_PORT) flushall
|
||||||
|
|
||||||
|
## —— Yarn 🐱 / JavaScript —————————————————————————————————————————————————————
|
||||||
|
yarn-install: ## Install node dependencies with Yarn
|
||||||
|
@$(YARN_CONT) install
|
||||||
|
|
||||||
|
yarn-dev: ## Build the assets for the dev env
|
||||||
|
@$(YARN_CONT) dev
|
||||||
|
|
||||||
|
yarn-lint: ## Lint JS files
|
||||||
|
@$(YARN_CONT) lint
|
||||||
|
|
||||||
|
yarn-cmd: ## Run a given command
|
||||||
|
@$(eval cmd ?= 'help')
|
||||||
|
@$(YARN_CONT) $(cmd)
|
||||||
|
|
||||||
|
## —— Doc 📚 ———————————————————————————————————————————————————————————————————
|
||||||
|
workflows: ## Generate and update the graphs of all available workflows
|
||||||
|
@$(PHP_CONT) bin/console workflow:dump service_request_status | dot -Tpng -o docs/service_request_status_workflow.png
|
||||||
|
@echo "Done!"
|
||||||
|
|
@ -205,4 +205,4 @@ La page en question bénéficiera de l’accès au reste du framework, à la bas
|
||||||
|
|
||||||
|
|
||||||
# Installation et documentation technique
|
# Installation et documentation technique
|
||||||
La documentation d'installation et configuration technique de la plateforme est disponible sur [cette page]().
|
La documentation d'installation et configuration technique de la plateforme est disponible sur [cette page](docs/README.md).
|
||||||
|
|
|
||||||
18
assets/app.js
Normal file
18
assets/app.js
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Welcome to your app's main JavaScript file!
|
||||||
|
*
|
||||||
|
* We recommend including the built version of this JavaScript file
|
||||||
|
* (and its CSS file) in your base layout (base.html.twig).
|
||||||
|
*/
|
||||||
|
|
||||||
|
// any CSS you import will output into a single css file (app.css in this case)
|
||||||
|
import './styles/global.scss'
|
||||||
|
|
||||||
|
// start the Stimulus application
|
||||||
|
import './stimulus'
|
||||||
|
|
||||||
|
import '@fortawesome/fontawesome-free/js/fontawesome'
|
||||||
|
import '@fortawesome/fontawesome-free/js/solid'
|
||||||
|
import '@fortawesome/fontawesome-free/js/regular'
|
||||||
|
import '@fortawesome/fontawesome-free/js/brands'
|
||||||
15
assets/controllers.json
Normal file
15
assets/controllers.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"controllers": {
|
||||||
|
"@symfony/ux-autocomplete": {
|
||||||
|
"autocomplete": {
|
||||||
|
"enabled": true,
|
||||||
|
"fetch": "eager",
|
||||||
|
"autoimport": {
|
||||||
|
"tom-select/dist/css/tom-select.default.css": true,
|
||||||
|
"tom-select/dist/css/tom-select.bootstrap5.css": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"entrypoints": []
|
||||||
|
}
|
||||||
9
assets/controllers/accordion_controller.js
Normal file
9
assets/controllers/accordion_controller.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Controller } from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
toggle() {
|
||||||
|
const accordionList = this.element.nextElementSibling
|
||||||
|
this.element.lastElementChild.classList.toggle('rotate-180')
|
||||||
|
accordionList.classList.toggle('opened')
|
||||||
|
}
|
||||||
|
}
|
||||||
65
assets/controllers/account_controller.js
Normal file
65
assets/controllers/account_controller.js
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { Controller } from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
|
||||||
|
hiddenUserInput () {
|
||||||
|
const divUserInput = document.querySelector('.user-input')
|
||||||
|
divUserInput.classList.add('hidden')
|
||||||
|
}
|
||||||
|
|
||||||
|
hiddenPlaceInput() {
|
||||||
|
const divUserInput = document.querySelector('.place-input')
|
||||||
|
divUserInput.classList.add('hidden')
|
||||||
|
}
|
||||||
|
connect () {
|
||||||
|
const userInput = this.element.value === 'user'
|
||||||
|
const placeInput = this.element.value === 'place'
|
||||||
|
const inputUserLastname = document.querySelector('.input-lastname')
|
||||||
|
const inputUserFirstname = document.querySelector('.input-firstname')
|
||||||
|
const inputPlaceName = document.querySelector('.input-name')
|
||||||
|
|
||||||
|
const userInputChecked = userInput && this.element.checked
|
||||||
|
const placeInputChecked = placeInput && this.element.checked
|
||||||
|
|
||||||
|
if (userInputChecked) {
|
||||||
|
inputUserFirstname.required = true
|
||||||
|
inputUserLastname.required = true
|
||||||
|
this.hiddenPlaceInput()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placeInputChecked) {
|
||||||
|
inputPlaceName.required = true
|
||||||
|
this.hiddenUserInput()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
choosenType() {
|
||||||
|
const placeInput = this.element.value === 'place'
|
||||||
|
const inputUserLastname = document.querySelector('.input-lastname')
|
||||||
|
const inputUserFirstname = document.querySelector('.input-firstname')
|
||||||
|
const inputPlaceName = document.querySelector('.input-name')
|
||||||
|
|
||||||
|
const divUserInput = document.querySelector('.user-input')
|
||||||
|
const divPlaceInput = document.querySelector('.place-input')
|
||||||
|
|
||||||
|
const placeInputChecked = placeInput && this.element.checked
|
||||||
|
|
||||||
|
if (placeInputChecked) {
|
||||||
|
inputUserFirstname.removeAttribute('required')
|
||||||
|
inputUserLastname.removeAttribute('required')
|
||||||
|
|
||||||
|
inputPlaceName.setAttribute('required', '')
|
||||||
|
|
||||||
|
divPlaceInput.classList.remove('hidden')
|
||||||
|
divUserInput.classList.add('hidden')
|
||||||
|
} else {
|
||||||
|
inputPlaceName.removeAttribute('required')
|
||||||
|
|
||||||
|
inputUserFirstname.setAttribute('required', '')
|
||||||
|
inputUserLastname.setAttribute('required', '')
|
||||||
|
|
||||||
|
divUserInput.classList.remove('hidden')
|
||||||
|
divPlaceInput.classList.add('hidden')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
assets/controllers/calendar_controller.js
Normal file
114
assets/controllers/calendar_controller.js
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import { Controller} from '@hotwired/stimulus'
|
||||||
|
import flatpickr from 'flatpickr'
|
||||||
|
import rangePlugin from 'flatpickr/dist/plugins/rangePlugin'
|
||||||
|
import { French } from 'flatpickr/dist/l10n/fr'
|
||||||
|
export default class extends Controller {
|
||||||
|
static values = {
|
||||||
|
unavailabilities: String
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
this.fp
|
||||||
|
this.fpProductOwner
|
||||||
|
}
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
const unavailabilities = this.unavailabilitiesValue.split(',')
|
||||||
|
|
||||||
|
const selector = this.element.querySelector('#calendar-start-day')
|
||||||
|
|
||||||
|
const commonOptions = {
|
||||||
|
locale: {
|
||||||
|
...French,
|
||||||
|
weekdays: {
|
||||||
|
shorthand: ['D', 'L', 'M', 'M', 'J', 'V', 'S'], // Override shorthand because it is initially in the "lun", "mar", "mer" (etc) format
|
||||||
|
longhand: French.weekdays.longhand,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inline: true,
|
||||||
|
disable: unavailabilities,
|
||||||
|
monthSelectorType: 'static',
|
||||||
|
minDate: 'today',
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
// This flatpickr instance is meant for when a user visits its own product page
|
||||||
|
this.fpProductOwner = flatpickr('#product-owner-calendar', commonOptions)
|
||||||
|
|
||||||
|
// This prevents owner from selecting days
|
||||||
|
this.fpProductOwner.daysContainer.addEventListener('click', (event) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
}, true)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fp = flatpickr(selector, {
|
||||||
|
...commonOptions,
|
||||||
|
allowInput: true,
|
||||||
|
mode: 'range',
|
||||||
|
plugins: [new rangePlugin({ input: '#calendar-end-day'})],
|
||||||
|
onReady(_, __, instance) {
|
||||||
|
let params = (new URL(location)).searchParams
|
||||||
|
const startAt = params.get('startAt')
|
||||||
|
const endAt = params.get('endAt')
|
||||||
|
|
||||||
|
const dates = []
|
||||||
|
|
||||||
|
if (startAt) dates.push(startAt)
|
||||||
|
if (endAt) dates.push(endAt)
|
||||||
|
|
||||||
|
if (dates.length) {
|
||||||
|
instance.setDate(dates, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonServiceRequestPage = document.querySelector('#create_service_request_submit')
|
||||||
|
|
||||||
|
if (!buttonServiceRequestPage) return
|
||||||
|
|
||||||
|
buttonServiceRequestPage.setAttribute('disabled', '')
|
||||||
|
},
|
||||||
|
onChange() {
|
||||||
|
const startAtInput = document.querySelector('#calendar-start-day')
|
||||||
|
const endAtInput = document.querySelector('#calendar-end-day')
|
||||||
|
const startAt = startAtInput.value
|
||||||
|
const endAt = endAtInput.value
|
||||||
|
|
||||||
|
const buttonProductPage = document.querySelector('#service-request')
|
||||||
|
const buttonServiceRequestPage = document.querySelector('#create_service_request_submit')
|
||||||
|
|
||||||
|
if (buttonProductPage) {
|
||||||
|
startAt && endAt
|
||||||
|
? buttonProductPage.removeAttribute('disabled')
|
||||||
|
: buttonProductPage.setAttribute('disabled', '')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonServiceRequestPage) {
|
||||||
|
startAt && endAt
|
||||||
|
? buttonServiceRequestPage.removeAttribute('disabled')
|
||||||
|
: buttonServiceRequestPage.setAttribute('disabled', '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resetDates() {
|
||||||
|
this.fp.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceRequest() {
|
||||||
|
const button = this.element.querySelector('#service-request')
|
||||||
|
const path = button.dataset.path
|
||||||
|
const startAtInput = this.element.querySelector('#calendar-start-day')
|
||||||
|
const endAtInput = this.element.querySelector('#calendar-end-day')
|
||||||
|
const startAt = startAtInput.value
|
||||||
|
const endAt = endAtInput.value
|
||||||
|
|
||||||
|
const url = new URL(path, window.location.origin)
|
||||||
|
url.searchParams.set('startAt', startAt)
|
||||||
|
url.searchParams.set('endAt', endAt)
|
||||||
|
|
||||||
|
location.href = url
|
||||||
|
}
|
||||||
|
}
|
||||||
8
assets/controllers/menu_controller.js
Normal file
8
assets/controllers/menu_controller.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import {Controller} from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
toggle() {
|
||||||
|
const menu = document.querySelector('.menu')
|
||||||
|
menu.classList.toggle('hide')
|
||||||
|
}
|
||||||
|
}
|
||||||
34
assets/controllers/product_controller.js
Normal file
34
assets/controllers/product_controller.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Controller} from '@hotwired/stimulus'
|
||||||
|
import { Toast } from 'bootstrap'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = [ 'activeButton', 'pausedButton', 'activeTag', 'pausedTag' ]
|
||||||
|
|
||||||
|
static values = {
|
||||||
|
route: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
async switchStatus() {
|
||||||
|
const response = await fetch(this.routeValue, { method: 'PATCH' })
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const toastElement = document.querySelector('[data-notification=error]')
|
||||||
|
const toast = new Toast(toastElement)
|
||||||
|
toast.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
const { status } = data
|
||||||
|
|
||||||
|
const toastElement = document.querySelector(`[data-notification=${status}StatusSuccess]`)
|
||||||
|
const toast = new Toast(toastElement)
|
||||||
|
toast.show()
|
||||||
|
|
||||||
|
this.activeButtonTarget.classList.toggle('d-none')
|
||||||
|
this.pausedButtonTarget.classList.toggle('d-none')
|
||||||
|
|
||||||
|
this.activeTagTarget.classList.toggle('d-none')
|
||||||
|
this.pausedTagTarget.classList.toggle('d-none')
|
||||||
|
}
|
||||||
|
}
|
||||||
40
assets/controllers/productupload_controller.js
Normal file
40
assets/controllers/productupload_controller.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { Controller} from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ['input', 'feedback']
|
||||||
|
|
||||||
|
static values = {
|
||||||
|
uploadMaxsizeByFile: Number, // max size by image allowed
|
||||||
|
uploadMaxItems: Number, // max number of images allowed
|
||||||
|
currentImagesCount: Number, // number of images already uploaded
|
||||||
|
feedbackMessage: String, // image too too big feedback
|
||||||
|
maxImagesError: String, // count threshold reached error
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Check the size of each file. Remove the selected files if one is incorrect.
|
||||||
|
* 2. Check the number of images uploaded.
|
||||||
|
*/
|
||||||
|
checkUpload() {
|
||||||
|
const maxAllowedImages = this.uploadMaxItemsValue - this.currentImagesCountValue
|
||||||
|
if (maxAllowedImages < this.inputTarget.files.length) {
|
||||||
|
this.feedbackTarget.innerHTML = this.maxImagesErrorValue
|
||||||
|
this.inputTarget.value = ''
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadMaxsizeByFile = 1048576 * this.uploadMaxsizeByFileValue
|
||||||
|
let feedback = []
|
||||||
|
for (let file of this.inputTarget.files) {
|
||||||
|
if (file.size > uploadMaxsizeByFile) {
|
||||||
|
feedback.push(this.feedbackMessageValue.replace('%file%', file.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feedback.length > 0) {
|
||||||
|
this.feedbackTarget.innerHTML = feedback.join('<br/>')
|
||||||
|
this.inputTarget.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
assets/controllers/productvisibility_controller.js
Normal file
18
assets/controllers/productvisibility_controller.js
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Controller} from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ['public', 'groups']
|
||||||
|
|
||||||
|
connect () {
|
||||||
|
if (this.publicTarget.checked) {
|
||||||
|
this.hideGroups()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hideGroups() {
|
||||||
|
this.groupsTarget.classList.add('hidden')
|
||||||
|
}
|
||||||
|
showGroups() {
|
||||||
|
this.groupsTarget.classList.remove('hidden')
|
||||||
|
}
|
||||||
|
}
|
||||||
14
assets/controllers/read-more_controller.js
Normal file
14
assets/controllers/read-more_controller.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import {Controller} from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
toggle() {
|
||||||
|
const readMoreContainer = document.querySelector('.read')
|
||||||
|
const buttonToggle = this.element
|
||||||
|
const opened = readMoreContainer.classList.contains('less')
|
||||||
|
|
||||||
|
readMoreContainer.classList.toggle('less')
|
||||||
|
readMoreContainer.classList.toggle('more')
|
||||||
|
|
||||||
|
buttonToggle.innerHTML = opened ? 'Voir plus' : 'Voir moins'
|
||||||
|
}
|
||||||
|
}
|
||||||
16
assets/controllers/search_controller.js
Normal file
16
assets/controllers/search_controller.js
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Controller} from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = [ 'form' ]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the form to blank values (input reset doesn't work with prefilled values).
|
||||||
|
*/
|
||||||
|
reset() {
|
||||||
|
this.formTarget.elements['p[q]'].value = ''
|
||||||
|
this.formTarget.elements['p[category]'].value = ''
|
||||||
|
this.formTarget.elements['p[place]'].value = ''
|
||||||
|
this.formTarget.elements['p[city]'].value = ''
|
||||||
|
this.formTarget.elements['p[distance]'].forEach(radio => radio.checked = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
11
assets/controllers/tooltips_controller.js
Normal file
11
assets/controllers/tooltips_controller.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Controller } from '@hotwired/stimulus'
|
||||||
|
import { Tooltip } from 'bootstrap'
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
connect() {
|
||||||
|
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
||||||
|
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||||
|
return new Tooltip(tooltipTriggerEl)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
21
assets/stimulus.js
Normal file
21
assets/stimulus.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { startStimulusApp } from '@symfony/stimulus-bridge'
|
||||||
|
import { Application } from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
import PasswordVisibility from 'stimulus-password-visibility'
|
||||||
|
import Carousel from 'stimulus-carousel'
|
||||||
|
import 'swiper/swiper-bundle.css'
|
||||||
|
|
||||||
|
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
||||||
|
export const app = startStimulusApp(require.context(
|
||||||
|
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
|
||||||
|
true,
|
||||||
|
/\.[jt]sx?$/
|
||||||
|
))
|
||||||
|
|
||||||
|
// register any custom, 3rd party controllers here
|
||||||
|
// app.register('some_controller_name', SomeImportedController);
|
||||||
|
|
||||||
|
const application = Application.start()
|
||||||
|
application.register('carousel', Carousel)
|
||||||
|
application.register('password-visibility', PasswordVisibility)
|
||||||
|
|
||||||
18
assets/styles/_accordion.scss
Normal file
18
assets/styles/_accordion.scss
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
.accordion.rotate-180 {
|
||||||
|
transition: transform .3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion {
|
||||||
|
transition: transform .3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-list {
|
||||||
|
max-height: 0;
|
||||||
|
transition: max-height .3s ease-out;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.opened {
|
||||||
|
max-height: 500px;
|
||||||
|
transition: max-height .3s ease-in;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
assets/styles/_address.scss
Normal file
18
assets/styles/_address.scss
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
.address-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&-checkbox {
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
> p {
|
||||||
|
margin: 0;
|
||||||
|
color: $heading-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
assets/styles/_calendar.scss
Normal file
73
assets/styles/_calendar.scss
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
.flatpickr-calendar {
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-month,
|
||||||
|
.cur-year {
|
||||||
|
font-size: $font-size-base !important;
|
||||||
|
font-weight: $font-weight-normal !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-month {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-year {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrowUp,
|
||||||
|
.arrowDown {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-current-month {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-weekdays {
|
||||||
|
margin-top: $spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-weekday {
|
||||||
|
font-weight: $font-weight-normal !important;
|
||||||
|
color: $gray-600 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-day {
|
||||||
|
color: $primary !important;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
background: $primary;
|
||||||
|
color: $white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.inRange {
|
||||||
|
color: $black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.prevMonthDay,
|
||||||
|
&.nextMonthDay {
|
||||||
|
color: rgba($gray-600, .5) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-disabled {
|
||||||
|
color: $gray-600 !important;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-prev-month,
|
||||||
|
.flatpickr-next-month {
|
||||||
|
svg {
|
||||||
|
fill: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
22
assets/styles/_card.scss
Normal file
22
assets/styles/_card.scss
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
.card {
|
||||||
|
.img-container {
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
height: 310px;
|
||||||
|
}
|
||||||
|
@media (max-width: 1025px) {
|
||||||
|
height: 235px;
|
||||||
|
}
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.img {
|
||||||
|
object-fit: contain;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-default {
|
||||||
|
object-fit: cover;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
assets/styles/_chat.scss
Normal file
36
assets/styles/_chat.scss
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
.chat-content {
|
||||||
|
margin-bottom: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-action {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 992px) {
|
||||||
|
.chat-container {
|
||||||
|
max-height: 800px;
|
||||||
|
overflow-y: auto;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.chat-content {
|
||||||
|
margin-bottom: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-action {
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
.conversation-textarea {
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 992px) and (max-width: 1199px) {
|
||||||
|
.chat-content {
|
||||||
|
margin-bottom: 150px;
|
||||||
|
}
|
||||||
|
.chat-action {
|
||||||
|
width: 66.6%;
|
||||||
|
}
|
||||||
|
}
|
||||||
81
assets/styles/_connexion.scss
Normal file
81
assets/styles/_connexion.scss
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#account_create_step2_form_type,
|
||||||
|
#create_group_form_type
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> .form-check {
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label.required:after,
|
||||||
|
legend.required:after
|
||||||
|
{
|
||||||
|
content: "*" !important;
|
||||||
|
color: #B02A37;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.form-check-label.required:after {
|
||||||
|
content: '' !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#account_create_step2_form_plainPassword_first:invalid,
|
||||||
|
#account_create_step2_form_plainPassword_second:invalid,
|
||||||
|
#login-password:invalid {
|
||||||
|
background-image: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#account_create_step2_form_plainPassword_first:valid,
|
||||||
|
#account_create_step2_form_plainPassword_second:valid,
|
||||||
|
#login-password:valid {
|
||||||
|
background-image: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-visibility {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> input {
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .eye {
|
||||||
|
background-color: transparent;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: var(--bs-border-radius-sm) !important;
|
||||||
|
border-top-right-radius: var(--bs-border-radius-sm) !important;
|
||||||
|
height: fit-content;
|
||||||
|
padding: 4px 8px 1.2px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> input.is-invalid ~ .eye {
|
||||||
|
border: 1px solid #B02A37;
|
||||||
|
}
|
||||||
|
|
||||||
|
> input.is-invalid ~ span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.was-validated {
|
||||||
|
> .password {
|
||||||
|
> .password-visibility {
|
||||||
|
> input:invalid ~ .eye {
|
||||||
|
border: 1px solid #B02A37;
|
||||||
|
}
|
||||||
|
|
||||||
|
> input:valid ~ .eye {
|
||||||
|
border: 1px solid #198754;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
59
assets/styles/_conversations.scss
Normal file
59
assets/styles/_conversations.scss
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
.conversations {
|
||||||
|
&-link {
|
||||||
|
transition: background .3s;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background: rgba($gray-300, 0.3);
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-img {
|
||||||
|
width: 74px;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation {
|
||||||
|
&-message {
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
&.system {
|
||||||
|
border: 1px solid $gray-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.from_recipient,
|
||||||
|
&.from_owner {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.from_recipient {
|
||||||
|
background: $blue-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.from_owner {
|
||||||
|
margin-left: auto;
|
||||||
|
background: $blue-500;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
.conversation-messageValue {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&-messageValue {
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-textarea {
|
||||||
|
height: calc(1.5em + 0.75rem + 2px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-modal-width.col-sm-2 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
23
assets/styles/_custom-variables.scss
Normal file
23
assets/styles/_custom-variables.scss
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
$white: #FFFFFF;
|
||||||
|
$gray: #D4D9DF;
|
||||||
|
$gray-100: #F8F9FA;
|
||||||
|
$gray-900: #667080;
|
||||||
|
$blue-100: #CCE5FF;
|
||||||
|
$blue-200: #B8DAFF;
|
||||||
|
$blue-500: #0D6EFD;
|
||||||
|
$blue-900: #031633;
|
||||||
|
$red: #B02A37;
|
||||||
|
$green: #198754;
|
||||||
|
$yellow: #FFC107;
|
||||||
|
$gray-border: #CED4DA;
|
||||||
|
|
||||||
|
$dark: $blue-900;
|
||||||
|
$light: $gray-100;
|
||||||
|
$primary: $blue-500;
|
||||||
|
|
||||||
|
$heading-color: #152536;
|
||||||
|
$body-color: #6c757d;
|
||||||
|
|
||||||
|
//FONT
|
||||||
|
$bolder: 600;
|
||||||
|
$font-weight-bolder: $bolder;
|
||||||
51
assets/styles/_grid.scss
Normal file
51
assets/styles/_grid.scss
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
// GRID PAGE LOAN
|
||||||
|
.grid-template-loans {
|
||||||
|
display: grid;
|
||||||
|
grid-template-areas:
|
||||||
|
"product calendar"
|
||||||
|
"message calendar";
|
||||||
|
column-gap: 2rem;
|
||||||
|
grid-template-rows: 100px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GRID PAGE PRODUCT
|
||||||
|
.grid-template-product {
|
||||||
|
display: grid;
|
||||||
|
grid-template-areas:
|
||||||
|
"info lender"
|
||||||
|
"info calendar";
|
||||||
|
grid-template-columns: 45rem 3fr;
|
||||||
|
column-gap: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
&-lender {
|
||||||
|
grid-area: lender;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-product {
|
||||||
|
grid-area: product;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-message {
|
||||||
|
grid-area: message;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-calendar {
|
||||||
|
grid-area: calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
grid-area: info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 992px) {
|
||||||
|
.grid-template-loans, .grid-template-product, .grid-template-conversation {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.lender {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
assets/styles/_group.scss
Normal file
21
assets/styles/_group.scss
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
.card-group {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
div {
|
||||||
|
span.badge {
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 991px) {
|
||||||
|
.group-list {
|
||||||
|
li {
|
||||||
|
border-bottom: 1px solid $gray;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
assets/styles/_headings.scss
Normal file
34
assets/styles/_headings.scss
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
color: $heading-color;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 48.41px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 38.73px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 33.89px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 29.05px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 24.2px;
|
||||||
|
}
|
||||||
11
assets/styles/_lender.scss
Normal file
11
assets/styles/_lender.scss
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
.avatar {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
font-size: 24px;
|
||||||
|
|
||||||
|
&-icon {
|
||||||
|
&::before {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
assets/styles/_my-account.scss
Normal file
39
assets/styles/_my-account.scss
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
.myAccount{
|
||||||
|
border-bottom: 1px solid $gray-border;
|
||||||
|
> .myAccount-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
> svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
> path {
|
||||||
|
fill: $secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.myAccount-body {
|
||||||
|
> div {
|
||||||
|
> svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
> path {
|
||||||
|
fill: $secondary;
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-switch {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
.myAccount {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
assets/styles/_pagination.scss
Normal file
41
assets/styles/_pagination.scss
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
._pagination {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
> .pagination-items {
|
||||||
|
padding: 8px 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(102, 112, 128, 0.25) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .pagination-list {
|
||||||
|
> ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
> li {
|
||||||
|
padding: 8px 16px;
|
||||||
|
margin-right: 8px;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
&.current {
|
||||||
|
background-color: rgba(102, 112, 128, 0.25) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(102, 112, 128, 0.25) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
assets/styles/_product-list.scss
Normal file
33
assets/styles/_product-list.scss
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
.product-type {
|
||||||
|
border-radius: 4px 0 0 4px !important;
|
||||||
|
border: 1px solid $primary !important;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0 4px 4px 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#p_distance {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
.form-check {
|
||||||
|
.form-check-label {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-search {
|
||||||
|
> input {
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
background-color: transparent;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: var(--bs-border-radius-sm) !important;
|
||||||
|
border-top-right-radius: var(--bs-border-radius-sm) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
85
assets/styles/_product.scss
Normal file
85
assets/styles/_product.scss
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
.color-svg-secondary {
|
||||||
|
> svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
path {
|
||||||
|
fill: $secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-img{
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-wrapper {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-slide {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button-next,
|
||||||
|
.swiper-button-prev {
|
||||||
|
background: rgba($black, .5);
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 0;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.read {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.more {
|
||||||
|
max-height: 80px;
|
||||||
|
transition: max-height .3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.less {
|
||||||
|
max-height: 500px;
|
||||||
|
transition: max-height .3s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-toggle {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
> svg {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-application {
|
||||||
|
padding: 8px 12px;
|
||||||
|
background-color: $secondary;
|
||||||
|
width: fit-content;
|
||||||
|
> p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
> .comment-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
> p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
assets/styles/_reset.scss
Normal file
10
assets/styles/_reset.scss
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-top: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
15
assets/styles/_upload.scss
Normal file
15
assets/styles/_upload.scss
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
.upload {
|
||||||
|
width: fit-content;
|
||||||
|
.upload-input {
|
||||||
|
padding: 62px;
|
||||||
|
border: 1px solid $blue-200;
|
||||||
|
background-color: $blue-100;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=file] {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 0;
|
||||||
|
height: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
112
assets/styles/_utilities.scss
Normal file
112
assets/styles/_utilities.scss
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-180 {
|
||||||
|
transform: rotate(-180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.-rotate-90 {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-90 {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray {
|
||||||
|
color: $gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-blue-500 {
|
||||||
|
color: $blue-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fit-content {
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-7 {
|
||||||
|
font-size: $font-size-base * .75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lh-0 {
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-primary-100 {
|
||||||
|
background-color: $blue-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-primary-200 {
|
||||||
|
border: 1px solid $blue-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-bg-blue-custom {
|
||||||
|
color: $blue-500;
|
||||||
|
border: 1px solid $blue-200;
|
||||||
|
background-color: $blue-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.featured-image {
|
||||||
|
width: 74px;
|
||||||
|
height: 74px;
|
||||||
|
border-radius: 4px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-image {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
.img-avatar {
|
||||||
|
display: inline-block;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center center;
|
||||||
|
border-radius: 50%
|
||||||
|
}
|
||||||
|
.bg-secondary-subtle {
|
||||||
|
background: $gray-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fw-medium {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-user-avatar {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fit-content {
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.white-space-normal{
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
> input {
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
&-button {
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-left: none;
|
||||||
|
background-color: $white;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: var(--bs-border-radius-sm) !important;
|
||||||
|
border-top-right-radius: var(--bs-border-radius-sm) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 992px) {
|
||||||
|
.img-funding {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
assets/styles/global.scss
Normal file
46
assets/styles/global.scss
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
// customize some Bootstrap variables
|
||||||
|
// $primary: darken(#428bca, 20%); // muse rebuild to see the change
|
||||||
|
|
||||||
|
@import "custom-variables";
|
||||||
|
|
||||||
|
// the ~ allows you to reference things in node_modules
|
||||||
|
@import "~bootstrap/scss/bootstrap";
|
||||||
|
@import "~bootstrap-icons/font/bootstrap-icons";
|
||||||
|
@import "~flatpickr/dist/flatpickr.min.css";
|
||||||
|
|
||||||
|
@import "reset";
|
||||||
|
@import "product-list";
|
||||||
|
@import "card";
|
||||||
|
@import "pagination";
|
||||||
|
@import "product";
|
||||||
|
@import "utilities";
|
||||||
|
@import "my-account";
|
||||||
|
@import "connexion";
|
||||||
|
@import "conversations";
|
||||||
|
@import "accordion";
|
||||||
|
@import "calendar";
|
||||||
|
@import "headings";
|
||||||
|
@import "lender";
|
||||||
|
@import "grid";
|
||||||
|
@import "upload";
|
||||||
|
@import "address";
|
||||||
|
@import "chat";
|
||||||
|
@import "group";
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
// Hack to force footer in the bottom of the page
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
}
|
||||||
17
bin/console
Executable file
17
bin/console
Executable file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Kernel;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||||
|
|
||||||
|
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
|
||||||
|
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||||
|
|
||||||
|
return function (array $context) {
|
||||||
|
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||||
|
|
||||||
|
return new Application($kernel);
|
||||||
|
};
|
||||||
19
bin/phpunit
Executable file
19
bin/phpunit
Executable file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if (!ini_get('date.timezone')) {
|
||||||
|
ini_set('date.timezone', 'UTC');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_file(dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit')) {
|
||||||
|
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
|
||||||
|
require PHPUNIT_COMPOSER_INSTALL;
|
||||||
|
PHPUnit\TextUI\Command::main();
|
||||||
|
} else {
|
||||||
|
if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
|
||||||
|
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
|
||||||
|
}
|
||||||
180
composer.json
Normal file
180
composer.json
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
{
|
||||||
|
"name": "platformcoop/ebs",
|
||||||
|
"type": "project",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "APES : Platforme d'échange de services et de biens",
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"prefer-stable": true,
|
||||||
|
"repositories": {
|
||||||
|
"coopTilleuls/payum-mollie": {
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "git@github.com:coopTilleuls/payum-mollie.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1.11",
|
||||||
|
"ext-apcu": "*",
|
||||||
|
"ext-ctype": "*",
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"ext-intl": "*",
|
||||||
|
"ext-xsl": "*",
|
||||||
|
"ext-zip": "*",
|
||||||
|
"api-platform/core": "^3.1",
|
||||||
|
"craue/formflow-bundle": "^3.6",
|
||||||
|
"doctrine/annotations": "^1.0",
|
||||||
|
"doctrine/doctrine-bundle": "^2.7",
|
||||||
|
"doctrine/doctrine-migrations-bundle": "^3.2",
|
||||||
|
"doctrine/orm": "^2.13",
|
||||||
|
"easycorp/easyadmin-bundle": "v4.5.1",
|
||||||
|
"friendsofsymfony/ckeditor-bundle": "^2.4",
|
||||||
|
"geocoder-php/nominatim-provider": "^5.6",
|
||||||
|
"handcraftedinthealps/goodby-csv": "^1.4",
|
||||||
|
"hautelook/alice-bundle": "^2.11",
|
||||||
|
"knplabs/knp-paginator-bundle": "^6.1",
|
||||||
|
"league/commonmark": "^2.3",
|
||||||
|
"league/flysystem-aws-s3-v3": "^3.15",
|
||||||
|
"league/flysystem-bundle": "^3.0",
|
||||||
|
"league/flysystem-google-cloud-storage": "^3.15",
|
||||||
|
"league/flysystem-memory": "^3.10",
|
||||||
|
"meilisearch/meilisearch-php": "^1.0",
|
||||||
|
"moneyphp/money": "^3.3",
|
||||||
|
"nelmio/cors-bundle": "^2.2",
|
||||||
|
"nesbot/carbon": "^2.66",
|
||||||
|
"nyholm/psr7": "^1.0",
|
||||||
|
"odolbeau/phone-number-bundle": "^3.9",
|
||||||
|
"payum/offline": "^1.7",
|
||||||
|
"payum/payum-bundle": "^2.5",
|
||||||
|
"phpdocumentor/reflection-docblock": "^5.3",
|
||||||
|
"phpstan/phpdoc-parser": "^1.11",
|
||||||
|
"sensio/framework-extra-bundle": "^6.2",
|
||||||
|
"snc/redis-bundle": "^4.3",
|
||||||
|
"stof/doctrine-extensions-bundle": "^1.7",
|
||||||
|
"symfony/asset": "6.2.*",
|
||||||
|
"symfony/cache": "6.2.*",
|
||||||
|
"symfony/clock": "6.2.*",
|
||||||
|
"symfony/console": "6.2.*",
|
||||||
|
"symfony/doctrine-messenger": "6.2.*",
|
||||||
|
"symfony/dotenv": "6.2.*",
|
||||||
|
"symfony/expression-language": "6.2.*",
|
||||||
|
"symfony/fake-sms-notifier": "6.2.*",
|
||||||
|
"symfony/flex": "^2",
|
||||||
|
"symfony/form": "6.2.*",
|
||||||
|
"symfony/framework-bundle": "6.2.*",
|
||||||
|
"symfony/google-mailer": "6.2.*",
|
||||||
|
"symfony/html-sanitizer": "6.2.*",
|
||||||
|
"symfony/http-client": "6.2.*",
|
||||||
|
"symfony/mailer": "6.2.*",
|
||||||
|
"symfony/mercure-bundle": "^0.3.5",
|
||||||
|
"symfony/messenger": "6.2.*",
|
||||||
|
"symfony/mime": "6.2.*",
|
||||||
|
"symfony/monolog-bundle": "^3.8",
|
||||||
|
"symfony/notifier": "6.2.*",
|
||||||
|
"symfony/ovh-cloud-notifier": "6.2.*",
|
||||||
|
"symfony/property-access": "6.2.*",
|
||||||
|
"symfony/property-info": "6.2.*",
|
||||||
|
"symfony/proxy-manager-bridge": "6.2.*",
|
||||||
|
"symfony/rate-limiter": "6.2.*",
|
||||||
|
"symfony/requirements-checker": "^2.0",
|
||||||
|
"symfony/runtime": "6.2.*",
|
||||||
|
"symfony/security-bundle": "6.2.*",
|
||||||
|
"symfony/serializer": "6.2.*",
|
||||||
|
"symfony/translation-contracts": "^3.2",
|
||||||
|
"symfony/twig-bridge": "6.2.*",
|
||||||
|
"symfony/twig-bundle": "6.2.*",
|
||||||
|
"symfony/twilio-notifier": "6.2.*",
|
||||||
|
"symfony/uid": "6.2.*",
|
||||||
|
"symfony/ux-autocomplete": "^2.7",
|
||||||
|
"symfony/validator": "6.2.*",
|
||||||
|
"symfony/webpack-encore-bundle": "^1.16",
|
||||||
|
"symfony/workflow": "6.2.*",
|
||||||
|
"symfony/yaml": "6.2.*",
|
||||||
|
"twig/cssinliner-extra": "^3.4",
|
||||||
|
"twig/extra-bundle": "^3.4",
|
||||||
|
"twig/inky-extra": "^3.4",
|
||||||
|
"twig/intl-extra": "^3.5",
|
||||||
|
"twig/markdown-extra": "^3.4",
|
||||||
|
"twig/twig": "^2.12|^3.0",
|
||||||
|
"webbaard/payum-mollie": "^1.0",
|
||||||
|
"webmozart/assert": "^1.11",
|
||||||
|
"willdurand/geocoder-bundle": "^5.18"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"composer/package-versions-deprecated": true,
|
||||||
|
"symfony/flex": true,
|
||||||
|
"symfony/runtime": true,
|
||||||
|
"phpstan/extension-installer": true,
|
||||||
|
"php-http/discovery": true
|
||||||
|
},
|
||||||
|
"optimize-autoloader": true,
|
||||||
|
"preferred-install": {
|
||||||
|
"*": "dist"
|
||||||
|
},
|
||||||
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"App\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"App\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"replace": {
|
||||||
|
"symfony/polyfill-ctype": "*",
|
||||||
|
"symfony/polyfill-iconv": "*",
|
||||||
|
"symfony/polyfill-php72": "*",
|
||||||
|
"symfony/polyfill-php73": "*",
|
||||||
|
"symfony/polyfill-php74": "*",
|
||||||
|
"symfony/polyfill-php80": "*",
|
||||||
|
"symfony/polyfill-php81": "*"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"auto-scripts": {
|
||||||
|
"cache:clear": "symfony-cmd",
|
||||||
|
"ckeditor:install --tag=4.22.1": "symfony-cmd",
|
||||||
|
"assets:install %PUBLIC_DIR%": "symfony-cmd",
|
||||||
|
"requirements-checker": "script"
|
||||||
|
},
|
||||||
|
"post-install-cmd": [
|
||||||
|
"@auto-scripts"
|
||||||
|
],
|
||||||
|
"post-update-cmd": [
|
||||||
|
"@auto-scripts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/symfony": "*"
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"symfony": {
|
||||||
|
"allow-contrib": false,
|
||||||
|
"require": "6.2.*",
|
||||||
|
"docker": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ekino/phpstan-banned-code": "^1.0",
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.12",
|
||||||
|
"friendsoftwig/twigcs": "^6.1",
|
||||||
|
"phpstan/extension-installer": "^1.1",
|
||||||
|
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||||
|
"phpstan/phpstan-doctrine": "^1.3",
|
||||||
|
"phpstan/phpstan-strict-rules": "^1.4",
|
||||||
|
"phpstan/phpstan-symfony": "^1.2",
|
||||||
|
"phpstan/phpstan-webmozart-assert": "^1.2",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"rector/rector": "^0.14.5",
|
||||||
|
"staabm/annotate-pull-request-from-checkstyle": "^1.8",
|
||||||
|
"symfony/browser-kit": "6.2.*",
|
||||||
|
"symfony/css-selector": "6.2.*",
|
||||||
|
"symfony/debug-bundle": "6.2.*",
|
||||||
|
"symfony/maker-bundle": "^1.47",
|
||||||
|
"symfony/panther": "^2.0",
|
||||||
|
"symfony/phpunit-bridge": "^6.1",
|
||||||
|
"symfony/web-profiler-bundle": "6.2.*",
|
||||||
|
"zenstruck/messenger-test": "^1.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
18594
composer.lock
generated
Normal file
18594
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
23
composer.md
Normal file
23
composer.md
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Note regarding composer.json
|
||||||
|
|
||||||
|
## Meilisearch
|
||||||
|
|
||||||
|
meilisearch/meilisearch-php
|
||||||
|
|
||||||
|
Is locked to `v0.26.0` to prevent this error:
|
||||||
|
|
||||||
|
Executing script cache:clear [KO]
|
||||||
|
[KO]
|
||||||
|
Script cache:clear returned with error code 1
|
||||||
|
!!
|
||||||
|
!! In DebugClassLoader.php line 327:
|
||||||
|
!!
|
||||||
|
!! Case mismatch between loaded and declared class names: "MeiliSearch\Client"
|
||||||
|
!! vs "Meilisearch\Client".
|
||||||
|
!!
|
||||||
|
!!
|
||||||
|
!!
|
||||||
|
Script @auto-scripts was called via post-update-cmd
|
||||||
|
|
||||||
|
|
||||||
|
I have opened a ticket https://github.com/meilisearch/meilisearch-php/issues/452.
|
||||||
36
config/bundles.php
Normal file
36
config/bundles.php
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||||
|
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
|
||||||
|
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||||
|
Bazinga\GeocoderBundle\BazingaGeocoderBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||||
|
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||||
|
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||||
|
Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['all' => true],
|
||||||
|
Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['all' => true],
|
||||||
|
Hautelook\AliceBundle\HautelookAliceBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||||
|
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||||
|
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||||
|
Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
|
||||||
|
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||||
|
EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
|
||||||
|
Craue\FormFlowBundle\CraueFormFlowBundle::class => ['all' => true],
|
||||||
|
Zenstruck\Messenger\Test\ZenstruckMessengerTestBundle::class => ['dev' => true, 'test' => true],
|
||||||
|
Snc\RedisBundle\SncRedisBundle::class => ['all' => true],
|
||||||
|
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
|
||||||
|
League\FlysystemBundle\FlysystemBundle::class => ['all' => true],
|
||||||
|
Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
|
||||||
|
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
||||||
|
Symfony\UX\Autocomplete\AutocompleteBundle::class => ['all' => true],
|
||||||
|
Payum\Bundle\PayumBundle\PayumBundle::class => ['all' => true],
|
||||||
|
FOS\CKEditorBundle\FOSCKEditorBundle::class => ['all' => true],
|
||||||
|
Misd\PhoneNumberBundle\MisdPhoneNumberBundle::class => ['all' => true],
|
||||||
|
];
|
||||||
24
config/packages/api_platform.yaml
Normal file
24
config/packages/api_platform.yaml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
api_platform:
|
||||||
|
title: 'PlateformCoop API'
|
||||||
|
description: 'List of PlateformCoop API endpoints. Most of them require to be logged.'
|
||||||
|
|
||||||
|
# The version of the API.
|
||||||
|
version: '%app_version%'
|
||||||
|
|
||||||
|
openapi:
|
||||||
|
# The contact information for the exposed API.
|
||||||
|
contact:
|
||||||
|
# The identifying name of the contact person/organization.
|
||||||
|
name: APES
|
||||||
|
# The URL pointing to the contact information. MUST be in the format of a URL.
|
||||||
|
url: http://www.apes-hdf.org/page-96-0-0.html
|
||||||
|
# The email address of the contact person/organization. MUST be in the format of an email address.
|
||||||
|
email: contact@apes-hdf.org
|
||||||
|
# A URL to the Terms of Service for the API. MUST be in the format of a URL.
|
||||||
|
termsOfService: https://github.com/ApesHDF/EBS/blob/main/LICENSE
|
||||||
|
# The license information for the exposed API.
|
||||||
|
license:
|
||||||
|
# The license name used for the API.
|
||||||
|
name: MIT
|
||||||
|
# URL to the license used for the API. MUST be in the format of a URL.
|
||||||
|
url: https://github.com/ApesHDF/EBS/blob/main/LICENSE
|
||||||
24
config/packages/bazinga_geocoder.yaml
Normal file
24
config/packages/bazinga_geocoder.yaml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
# we need a PSR16 cache for bazinga_geoloc
|
||||||
|
cache.geoloc.psr16:
|
||||||
|
class: Symfony\Component\Cache\Psr16Cache
|
||||||
|
arguments: ['@cache.geoloc']
|
||||||
|
|
||||||
|
# See the docs at https://github.com/geocoder-php/BazingaGeocoderBundle
|
||||||
|
bazinga_geocoder:
|
||||||
|
# The local IP (127.0.0.1) will be replaced by the fake_ip
|
||||||
|
# see https://github.com/geocoder-php/BazingaGeocoderBundle/blob/5.0.0/Resources/doc/index.md#fake-local-ip
|
||||||
|
fake_ip: 92.159.11.105 # Lomme
|
||||||
|
providers:
|
||||||
|
nominatim:
|
||||||
|
# https://github.com/geocoder-php/nominatim-provider
|
||||||
|
factory: Bazinga\GeocoderBundle\ProviderFactory\NominatimFactory
|
||||||
|
|
||||||
|
# https://github.com/geocoder-php/BazingaGeocoderBundle/blob/master/doc/cache.md
|
||||||
|
cache: 'cache.geoloc.psr16'
|
||||||
|
cache_lifetime: 86400
|
||||||
|
cache_precision: ~
|
||||||
23
config/packages/cache.yaml
Normal file
23
config/packages/cache.yaml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
framework:
|
||||||
|
cache:
|
||||||
|
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||||
|
prefix_seed: platformecoop/ebs
|
||||||
|
|
||||||
|
# The "app" cache stores to the filesystem by default.
|
||||||
|
# The data in this cache should persist between deploys.
|
||||||
|
# app: cache.adapter.filesystem
|
||||||
|
|
||||||
|
# Other options include:
|
||||||
|
# Redis
|
||||||
|
app: cache.adapter.redis
|
||||||
|
default_redis_provider: "%env(REDIS_URL)%"
|
||||||
|
|
||||||
|
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||||
|
#app: cache.adapter.apcu
|
||||||
|
|
||||||
|
# Namespaced pools use the above "app" backend by default
|
||||||
|
pools:
|
||||||
|
# Specific pool for Geolocation stuff
|
||||||
|
cache.geoloc:
|
||||||
|
adapter: cache.app
|
||||||
|
default_lifetime: 3600
|
||||||
5
config/packages/debug.yaml
Normal file
5
config/packages/debug.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
when@dev:
|
||||||
|
debug:
|
||||||
|
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
|
||||||
|
# See the "server:dump" command to start a new server.
|
||||||
|
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
|
||||||
44
config/packages/doctrine.yaml
Normal file
44
config/packages/doctrine.yaml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
doctrine:
|
||||||
|
dbal:
|
||||||
|
url: '%env(resolve:DATABASE_URL)%'
|
||||||
|
|
||||||
|
# IMPORTANT: You MUST configure your server version,
|
||||||
|
# either here or in the DATABASE_URL env var (see .env file)
|
||||||
|
server_version: '14' # to synchronize with docker-compose.yml
|
||||||
|
|
||||||
|
orm:
|
||||||
|
auto_generate_proxy_classes: true
|
||||||
|
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||||
|
auto_mapping: true
|
||||||
|
mappings:
|
||||||
|
App:
|
||||||
|
is_bundle: false
|
||||||
|
dir: '%kernel.project_dir%/src/Entity'
|
||||||
|
prefix: 'App\Entity'
|
||||||
|
alias: App
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
doctrine:
|
||||||
|
dbal:
|
||||||
|
# "TEST_TOKEN" is typically set by ParaTest
|
||||||
|
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
|
||||||
|
logging: false
|
||||||
|
|
||||||
|
when@prod:
|
||||||
|
doctrine:
|
||||||
|
orm:
|
||||||
|
auto_generate_proxy_classes: false
|
||||||
|
query_cache_driver:
|
||||||
|
type: pool
|
||||||
|
pool: doctrine.system_cache_pool
|
||||||
|
result_cache_driver:
|
||||||
|
type: pool
|
||||||
|
pool: doctrine.result_cache_pool
|
||||||
|
|
||||||
|
framework:
|
||||||
|
cache:
|
||||||
|
pools:
|
||||||
|
doctrine.result_cache_pool:
|
||||||
|
adapter: cache.app
|
||||||
|
doctrine.system_cache_pool:
|
||||||
|
adapter: cache.system
|
||||||
7
config/packages/doctrine_migrations.yaml
Normal file
7
config/packages/doctrine_migrations.yaml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
doctrine_migrations:
|
||||||
|
migrations_paths:
|
||||||
|
# namespace is arbitrary but should be different from App\Migrations
|
||||||
|
# as migrations classes should NOT be autoloaded
|
||||||
|
'DoctrineMigrations': '%kernel.project_dir%/migrations'
|
||||||
|
enable_profiler: false
|
||||||
|
organize_migrations: BY_YEAR
|
||||||
100
config/packages/flysystem.yaml
Normal file
100
config/packages/flysystem.yaml
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
parameters:
|
||||||
|
# physical storage path
|
||||||
|
upload_dir: '%kernel.project_dir%/public/storage/uploads'
|
||||||
|
category_upload_dir: '%upload_dir%/category'
|
||||||
|
user_upload_dir: '%upload_dir%/user'
|
||||||
|
product_upload_dir: '%upload_dir%/product'
|
||||||
|
|
||||||
|
# relative URL path
|
||||||
|
base_path: '/storage/uploads'
|
||||||
|
category_base_path: '%base_path%/category'
|
||||||
|
user_base_path: '%base_path%/user'
|
||||||
|
product_base_path: '%base_path%/product'
|
||||||
|
|
||||||
|
# S3 Bucket config
|
||||||
|
storage_bucket: '%env(resolve:STORAGE_BUCKET)%'
|
||||||
|
|
||||||
|
# Read the documentation at https://github.com/thephpleague/flysystem-bundle/blob/master/docs/1-getting-started.md
|
||||||
|
flysystem:
|
||||||
|
storages:
|
||||||
|
category.storage:
|
||||||
|
adapter: 'local'
|
||||||
|
options:
|
||||||
|
directory: '%category_upload_dir%'
|
||||||
|
public_url: '%category_base_path%'
|
||||||
|
|
||||||
|
# local
|
||||||
|
user.storage:
|
||||||
|
adapter: 'local'
|
||||||
|
options:
|
||||||
|
directory: '%user_upload_dir%'
|
||||||
|
public_url: '%user_base_path%'
|
||||||
|
|
||||||
|
# Test S3 config locally with the min.io service (@see the docker compose files)
|
||||||
|
# user.storage:
|
||||||
|
# adapter: 'aws'
|
||||||
|
# visibility: public
|
||||||
|
# options:
|
||||||
|
# bucket: '%storage_bucket%'
|
||||||
|
# prefix: 'user'
|
||||||
|
# client: 'Aws\S3\S3Client'
|
||||||
|
|
||||||
|
product.storage:
|
||||||
|
adapter: 'local'
|
||||||
|
options:
|
||||||
|
directory: '%product_upload_dir%'
|
||||||
|
public_url: '%product_base_path%'
|
||||||
|
default.storage:
|
||||||
|
adapter: 'local'
|
||||||
|
options:
|
||||||
|
directory: '%upload_dir%'
|
||||||
|
public_url: '%base_path%'
|
||||||
|
|
||||||
|
# memory storage in the test env so we don't have to manipulate actual files
|
||||||
|
when@test:
|
||||||
|
flysystem:
|
||||||
|
storages:
|
||||||
|
category.storage:
|
||||||
|
adapter: 'memory'
|
||||||
|
public_url: '%category_base_path%'
|
||||||
|
user.storage:
|
||||||
|
adapter: 'memory'
|
||||||
|
public_url: '%user_base_path%'
|
||||||
|
product.storage:
|
||||||
|
adapter: 'memory'
|
||||||
|
public_url: '%product_base_path%'
|
||||||
|
default.storage:
|
||||||
|
adapter: 'memory'
|
||||||
|
public_url: '%base_path%'
|
||||||
|
|
||||||
|
# S3 compatible bucket in the production environment
|
||||||
|
when@prod:
|
||||||
|
flysystem:
|
||||||
|
storages:
|
||||||
|
category.storage:
|
||||||
|
adapter: 'aws'
|
||||||
|
visibility: public
|
||||||
|
options:
|
||||||
|
bucket: '%storage_bucket%'
|
||||||
|
prefix: 'category'
|
||||||
|
client: 'Aws\S3\S3Client'
|
||||||
|
user.storage:
|
||||||
|
adapter: 'aws'
|
||||||
|
visibility: public
|
||||||
|
options:
|
||||||
|
bucket: '%storage_bucket%'
|
||||||
|
prefix: 'user'
|
||||||
|
client: 'Aws\S3\S3Client'
|
||||||
|
product.storage:
|
||||||
|
adapter: 'aws'
|
||||||
|
visibility: public
|
||||||
|
options:
|
||||||
|
bucket: '%storage_bucket%'
|
||||||
|
prefix: 'product'
|
||||||
|
client: 'Aws\S3\S3Client'
|
||||||
|
default.storage:
|
||||||
|
adapter: 'aws'
|
||||||
|
visibility: public
|
||||||
|
options:
|
||||||
|
bucket: '%storage_bucket%'
|
||||||
|
client: 'Aws\S3\S3Client'
|
||||||
10
config/packages/fos_ckeditor.yaml
Normal file
10
config/packages/fos_ckeditor.yaml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Read the documentation: https://symfony.com/doc/current/bundles/FOSCKEditorBundle/index.html
|
||||||
|
|
||||||
|
twig:
|
||||||
|
form_themes:
|
||||||
|
- '@FOSCKEditor/Form/ckeditor_widget.html.twig'
|
||||||
|
|
||||||
|
fos_ck_editor:
|
||||||
|
configs:
|
||||||
|
main_config:
|
||||||
|
toolbar: full
|
||||||
29
config/packages/framework.yaml
Normal file
29
config/packages/framework.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# see https://symfony.com/doc/current/reference/configuration/framework.html
|
||||||
|
framework:
|
||||||
|
secret: '%env(APP_SECRET)%'
|
||||||
|
csrf_protection: true
|
||||||
|
http_method_override: false
|
||||||
|
|
||||||
|
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||||
|
# Remove or comment this section to explicitly disable session support.
|
||||||
|
session:
|
||||||
|
# handler_id: null # native session handler
|
||||||
|
handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler
|
||||||
|
cookie_secure: auto
|
||||||
|
cookie_samesite: lax
|
||||||
|
storage_factory_id: session.storage.factory.native
|
||||||
|
|
||||||
|
#esi: true
|
||||||
|
#fragments: true
|
||||||
|
php_errors:
|
||||||
|
log: true
|
||||||
|
|
||||||
|
# i18n
|
||||||
|
# this parameter with allowed routing prefix, @see LocalesCompilerPass
|
||||||
|
enabled_locales: ['fr']
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
framework:
|
||||||
|
test: true
|
||||||
|
session:
|
||||||
|
storage_factory_id: session.storage.factory.mock_file
|
||||||
13
config/packages/hautelook_alice.yaml
Normal file
13
config/packages/hautelook_alice.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
hautelook_alice:
|
||||||
|
fixtures_path: 'fixtures' # Path to which to look for fixtures relative to the project directory or the bundle path. May be a string or an array of strings.
|
||||||
|
root_dirs:
|
||||||
|
- '%kernel.project_dir%'
|
||||||
|
|
||||||
|
when@dev: &dev
|
||||||
|
hautelook_alice:
|
||||||
|
fixtures_path: 'fixtures'
|
||||||
|
|
||||||
|
when@test: *dev
|
||||||
|
|
||||||
|
# An instance can be initialized thanks to the prod fixtures
|
||||||
|
when@prod: *dev
|
||||||
10
config/packages/http_discovery.yaml
Normal file
10
config/packages/http_discovery.yaml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
services:
|
||||||
|
Psr\Http\Message\RequestFactoryInterface: '@http_discovery.psr17_factory'
|
||||||
|
Psr\Http\Message\ResponseFactoryInterface: '@http_discovery.psr17_factory'
|
||||||
|
Psr\Http\Message\ServerRequestFactoryInterface: '@http_discovery.psr17_factory'
|
||||||
|
Psr\Http\Message\StreamFactoryInterface: '@http_discovery.psr17_factory'
|
||||||
|
Psr\Http\Message\UploadedFileFactoryInterface: '@http_discovery.psr17_factory'
|
||||||
|
Psr\Http\Message\UriFactoryInterface: '@http_discovery.psr17_factory'
|
||||||
|
|
||||||
|
http_discovery.psr17_factory:
|
||||||
|
class: Http\Discovery\Psr17Factory
|
||||||
4
config/packages/knp_paginator.yaml
Normal file
4
config/packages/knp_paginator.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# https://github.com/KnpLabs/KnpPaginatorBundle#configuration-example
|
||||||
|
knp_paginator:
|
||||||
|
template:
|
||||||
|
pagination: '@KnpPaginator/Pagination/bootstrap_v5_pagination.html.twig'
|
||||||
10
config/packages/mailer.yaml
Normal file
10
config/packages/mailer.yaml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
framework:
|
||||||
|
mailer:
|
||||||
|
dsn: '%env(MAILER_DSN)%'
|
||||||
|
envelope:
|
||||||
|
sender: 'notifications@example.com'
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
framework:
|
||||||
|
mailer:
|
||||||
|
dsn: 'null://null'
|
||||||
9
config/packages/meilisearch.yaml
Normal file
9
config/packages/meilisearch.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Meilisearch
|
||||||
|
parameters:
|
||||||
|
meilisearchUrl: '%env(string:MEILISEARCH_URL)%'
|
||||||
|
meilisearchApiKey: '%env(string:MEILISEARCH_API_KEY)%'
|
||||||
|
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
8
config/packages/mercure.yaml
Normal file
8
config/packages/mercure.yaml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
mercure:
|
||||||
|
hubs:
|
||||||
|
default:
|
||||||
|
url: '%env(MERCURE_URL)%'
|
||||||
|
public_url: '%env(MERCURE_PUBLIC_URL)%'
|
||||||
|
jwt:
|
||||||
|
secret: '%env(MERCURE_JWT_SECRET)%'
|
||||||
|
publish: '*'
|
||||||
33
config/packages/messenger.yaml
Normal file
33
config/packages/messenger.yaml
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
framework:
|
||||||
|
messenger:
|
||||||
|
# https://symfony.com/doc/current/messenger/multiple_buses.html
|
||||||
|
default_bus: command.bus
|
||||||
|
buses:
|
||||||
|
query.bus: # $queryBus
|
||||||
|
command.bus: # $commandBus
|
||||||
|
|
||||||
|
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
|
||||||
|
failure_transport: failed
|
||||||
|
|
||||||
|
transports:
|
||||||
|
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
||||||
|
sync: 'sync://'
|
||||||
|
async: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||||
|
failed: '%env(MESSENGER_TRANSPORT_DSN)%?queue_name=failed'
|
||||||
|
|
||||||
|
routing:
|
||||||
|
# Sync
|
||||||
|
'*': sync # default routing for all messages until not changed
|
||||||
|
|
||||||
|
# Route your messages to the transports
|
||||||
|
# Async
|
||||||
|
# 'App\Message\YourMessage': async
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
framework:
|
||||||
|
messenger:
|
||||||
|
transports:
|
||||||
|
# replace with your transport name here (e.g., my_transport: 'in-memory://')
|
||||||
|
# For more Messenger testing tools, see https://github.com/zenstruck/messenger-test
|
||||||
|
async: 'test://'
|
||||||
|
# sync: 'test://'
|
||||||
6
config/packages/misd_phone_number.yaml
Normal file
6
config/packages/misd_phone_number.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# To persist libphonenumber\PhoneNumber objects, add the Misd\PhoneNumberBundle\Doctrine\DBAL\Types\PhoneNumberType mapping to your application's config.
|
||||||
|
# This requires: doctrine/doctrine-bundle
|
||||||
|
doctrine:
|
||||||
|
dbal:
|
||||||
|
types:
|
||||||
|
phone_number: Misd\PhoneNumberBundle\Doctrine\DBAL\Types\PhoneNumberType
|
||||||
11
config/packages/mollie.yaml
Normal file
11
config/packages/mollie.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true # Automatically injects dependencies in your services.
|
||||||
|
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||||
|
|
||||||
|
# @see https://github.com/webbaard/payum-mollie#symfony-integration
|
||||||
|
app.payum.mollie.factory:
|
||||||
|
class: Payum\Core\Bridge\Symfony\Builder\GatewayFactoryBuilder
|
||||||
|
arguments: [PayHelper\Payum\Mollie\MollieGatewayFactory]
|
||||||
|
tags:
|
||||||
|
- { name: payum.gateway_factory_builder, factory: mollie }
|
||||||
61
config/packages/monolog.yaml
Normal file
61
config/packages/monolog.yaml
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
monolog:
|
||||||
|
channels:
|
||||||
|
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||||
|
|
||||||
|
when@dev:
|
||||||
|
monolog:
|
||||||
|
handlers:
|
||||||
|
main:
|
||||||
|
type: stream
|
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
|
level: debug
|
||||||
|
channels: ["!event"]
|
||||||
|
# uncomment to get logging in your browser
|
||||||
|
# you may have to allow bigger header sizes in your Web server configuration
|
||||||
|
#firephp:
|
||||||
|
# type: firephp
|
||||||
|
# level: info
|
||||||
|
#chromephp:
|
||||||
|
# type: chromephp
|
||||||
|
# level: info
|
||||||
|
console:
|
||||||
|
type: console
|
||||||
|
process_psr_3_messages: false
|
||||||
|
channels: ["!event", "!doctrine", "!console"]
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
monolog:
|
||||||
|
handlers:
|
||||||
|
main:
|
||||||
|
type: fingers_crossed
|
||||||
|
action_level: error
|
||||||
|
handler: nested
|
||||||
|
excluded_http_codes: [404, 405]
|
||||||
|
channels: ["!event"]
|
||||||
|
nested:
|
||||||
|
type: stream
|
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
|
level: debug
|
||||||
|
|
||||||
|
when@prod:
|
||||||
|
monolog:
|
||||||
|
handlers:
|
||||||
|
main:
|
||||||
|
type: fingers_crossed
|
||||||
|
action_level: error
|
||||||
|
handler: nested
|
||||||
|
excluded_http_codes: [404, 405]
|
||||||
|
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||||
|
nested:
|
||||||
|
type: stream
|
||||||
|
path: php://stderr
|
||||||
|
level: debug
|
||||||
|
formatter: monolog.formatter.json
|
||||||
|
console:
|
||||||
|
type: console
|
||||||
|
process_psr_3_messages: false
|
||||||
|
channels: ["!event", "!doctrine"]
|
||||||
|
deprecation:
|
||||||
|
type: stream
|
||||||
|
channels: [deprecation]
|
||||||
|
path: php://stderr
|
||||||
15
config/packages/nelmio_alice.yaml
Normal file
15
config/packages/nelmio_alice.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
hautelook_alice:
|
||||||
|
root_dirs:
|
||||||
|
|
||||||
|
when@dev: &dev
|
||||||
|
nelmio_alice:
|
||||||
|
functions_blacklist:
|
||||||
|
- 'current'
|
||||||
|
- 'shuffle'
|
||||||
|
- 'date'
|
||||||
|
- 'time'
|
||||||
|
- 'file'
|
||||||
|
- 'md5'
|
||||||
|
- 'sha1'
|
||||||
|
|
||||||
|
when@test: *dev
|
||||||
10
config/packages/nelmio_cors.yaml
Normal file
10
config/packages/nelmio_cors.yaml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
nelmio_cors:
|
||||||
|
defaults:
|
||||||
|
origin_regex: true
|
||||||
|
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
||||||
|
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||||
|
allow_headers: ['Content-Type', 'Authorization']
|
||||||
|
expose_headers: ['Link']
|
||||||
|
max_age: 3600
|
||||||
|
paths:
|
||||||
|
'^/': null
|
||||||
29
config/packages/notifier.yaml
Normal file
29
config/packages/notifier.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
framework:
|
||||||
|
notifier:
|
||||||
|
texter_transports:
|
||||||
|
sms_service: '%env(SMS_DSN)%' # change in your .env.local to test with a real API key
|
||||||
|
# sms_service: 'null://null' # use this to deactivate totally SMS
|
||||||
|
|
||||||
|
channel_policy:
|
||||||
|
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
|
||||||
|
urgent: ['email']
|
||||||
|
high: ['email']
|
||||||
|
medium: ['email']
|
||||||
|
low: ['email']
|
||||||
|
|
||||||
|
admin_recipients:
|
||||||
|
- { email: admin@example.com }
|
||||||
|
|
||||||
|
when@dev:
|
||||||
|
framework:
|
||||||
|
notifier:
|
||||||
|
texter_transports:
|
||||||
|
fakesms: 'fakesms+email://mailer?to=TO&from=FROM'
|
||||||
|
|
||||||
|
# don't send real SMS in test env, but we are still able to check that the code
|
||||||
|
# tried to send something with the AssertCount assertions (@see tests)
|
||||||
|
when@test:
|
||||||
|
framework:
|
||||||
|
notifier:
|
||||||
|
texter_transports:
|
||||||
|
sms_service: 'null://null'
|
||||||
21
config/packages/nyholm_psr7.yaml
Normal file
21
config/packages/nyholm_psr7.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
services:
|
||||||
|
# Register nyholm/psr7 services for autowiring with PSR-17 (HTTP factories)
|
||||||
|
Psr\Http\Message\RequestFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||||
|
Psr\Http\Message\ResponseFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||||
|
Psr\Http\Message\ServerRequestFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||||
|
Psr\Http\Message\StreamFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||||
|
Psr\Http\Message\UploadedFileFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||||
|
Psr\Http\Message\UriFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||||
|
|
||||||
|
# Register nyholm/psr7 services for autowiring with HTTPlug factories
|
||||||
|
Http\Message\MessageFactory: '@nyholm.psr7.httplug_factory'
|
||||||
|
Http\Message\RequestFactory: '@nyholm.psr7.httplug_factory'
|
||||||
|
Http\Message\ResponseFactory: '@nyholm.psr7.httplug_factory'
|
||||||
|
Http\Message\StreamFactory: '@nyholm.psr7.httplug_factory'
|
||||||
|
Http\Message\UriFactory: '@nyholm.psr7.httplug_factory'
|
||||||
|
|
||||||
|
nyholm.psr7.psr17_factory:
|
||||||
|
class: Nyholm\Psr7\Factory\Psr17Factory
|
||||||
|
|
||||||
|
nyholm.psr7.httplug_factory:
|
||||||
|
class: Nyholm\Psr7\Factory\HttplugFactory
|
||||||
21
config/packages/payum.yaml
Normal file
21
config/packages/payum.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# https://github.com/Payum/PayumBundle
|
||||||
|
payum:
|
||||||
|
security:
|
||||||
|
token_storage:
|
||||||
|
App\Entity\PaymentToken: { doctrine: orm }
|
||||||
|
|
||||||
|
storages:
|
||||||
|
App\Entity\Payment: { doctrine: orm }
|
||||||
|
|
||||||
|
gateways:
|
||||||
|
# For tests but can also be used for offline payments like cash.
|
||||||
|
offline:
|
||||||
|
factory: offline
|
||||||
|
|
||||||
|
# https://github.com/webbaard/payum-mollie
|
||||||
|
# fork for PHP 8.0+
|
||||||
|
# see config/packages/mollie.yaml
|
||||||
|
mollie:
|
||||||
|
factory: mollie
|
||||||
|
apiKey: '%env(string:PAYUM_APIKEY)%'
|
||||||
|
method: creditcard # one of directdebit, creditcard or directdebit_oneoff
|
||||||
12
config/packages/routing.yaml
Normal file
12
config/packages/routing.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
framework:
|
||||||
|
router:
|
||||||
|
utf8: true
|
||||||
|
|
||||||
|
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
||||||
|
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
||||||
|
#default_uri: http://localhost
|
||||||
|
|
||||||
|
when@prod:
|
||||||
|
framework:
|
||||||
|
router:
|
||||||
|
strict_requirements: null
|
||||||
67
config/packages/security.yaml
Normal file
67
config/packages/security.yaml
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
security:
|
||||||
|
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
|
||||||
|
password_hashers:
|
||||||
|
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||||
|
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
|
||||||
|
providers:
|
||||||
|
# used to reload user from session & other features (e.g. switch_user)
|
||||||
|
app_user_provider:
|
||||||
|
entity:
|
||||||
|
class: App\Entity\User
|
||||||
|
property: email
|
||||||
|
firewalls:
|
||||||
|
dev:
|
||||||
|
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||||
|
security: false
|
||||||
|
main:
|
||||||
|
lazy: true
|
||||||
|
provider: app_user_provider
|
||||||
|
# checkers are in src/Security/Checker
|
||||||
|
user_checker: security.user_checker.chain.main
|
||||||
|
|
||||||
|
# activate different ways to authenticate
|
||||||
|
# https://symfony.com/doc/current/security.html#the-firewall
|
||||||
|
|
||||||
|
# https://symfony.com/doc/current/security/impersonating_user.html
|
||||||
|
switch_user:
|
||||||
|
parameter: _switch_user
|
||||||
|
|
||||||
|
form_login:
|
||||||
|
login_path: app_login
|
||||||
|
check_path: app_login
|
||||||
|
enable_csrf: true
|
||||||
|
default_target_path: app_user_my_account
|
||||||
|
|
||||||
|
# https://symfony.com/doc/current/security.html#logging-out
|
||||||
|
logout:
|
||||||
|
path: app_logout
|
||||||
|
target: app_login
|
||||||
|
|
||||||
|
entry_point: App\Security\EntryPoint\AuthenticationEntryPoint
|
||||||
|
|
||||||
|
login_throttling:
|
||||||
|
max_attempts: 2
|
||||||
|
|
||||||
|
# Easy way to control access for large sections of your site
|
||||||
|
# Note: Only the *first* access control that matches will be used
|
||||||
|
access_control:
|
||||||
|
- { path: ^/admin, roles: [ROLE_ADMIN, ROLE_GROUP_ADMIN] }
|
||||||
|
# to synchronize with MyAccountAction
|
||||||
|
- { path: ^/en/my-account/, roles: ROLE_USER }
|
||||||
|
- { path: ^/fr/mon-compte/, roles: ROLE_USER }
|
||||||
|
|
||||||
|
role_hierarchy:
|
||||||
|
ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH, ROLE_GROUP_ADMIN]
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
security:
|
||||||
|
password_hashers:
|
||||||
|
# By default, password hashers are resource intensive and take time. This is
|
||||||
|
# important to generate secure password hashes. In tests however, secure hashes
|
||||||
|
# are not important, waste resources and increase test times. The following
|
||||||
|
# reduces the work factor to the lowest possible values.
|
||||||
|
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
|
||||||
|
algorithm: auto
|
||||||
|
cost: 4 # Lowest possible value for bcrypt
|
||||||
|
time_cost: 3 # Lowest possible value for argon
|
||||||
|
memory_cost: 10 # Lowest possible value for argon
|
||||||
7
config/packages/sensio_framework_extra.yaml
Normal file
7
config/packages/sensio_framework_extra.yaml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# https://stackoverflow.com/q/69809320/633864
|
||||||
|
sensio_framework_extra:
|
||||||
|
router:
|
||||||
|
annotations: false
|
||||||
|
request:
|
||||||
|
converters: false
|
||||||
|
auto_convert: false
|
||||||
27
config/packages/snc_redis.yaml
Normal file
27
config/packages/snc_redis.yaml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler:
|
||||||
|
arguments:
|
||||||
|
- '@snc_redis.session'
|
||||||
|
- { 'ttl': 3600 }
|
||||||
|
|
||||||
|
# Define your clients here. The example below connects to database 0 of the default Redis server.
|
||||||
|
#
|
||||||
|
# See https://github.com/snc/SncRedisBundle/blob/master/docs/README.md for instructions on
|
||||||
|
# how to configure the bundle.
|
||||||
|
snc_redis:
|
||||||
|
clients:
|
||||||
|
default:
|
||||||
|
type: phpredis
|
||||||
|
alias: default
|
||||||
|
dsn: "%env(REDIS_URL)%"
|
||||||
|
logging: '%kernel.debug%'
|
||||||
|
|
||||||
|
# use in framework.
|
||||||
|
session:
|
||||||
|
type: phpredis
|
||||||
|
alias: session
|
||||||
|
dsn: "%env(REDIS_URL)%/1"
|
||||||
|
logging: '%kernel.debug%'
|
||||||
10
config/packages/stof_doctrine_extensions.yaml
Normal file
10
config/packages/stof_doctrine_extensions.yaml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Read the documentation: https://symfony.com/doc/current/bundles/StofDoctrineExtensionsBundle/index.html
|
||||||
|
# See the official DoctrineExtensions documentation for more details: https://github.com/doctrine-extensions/DoctrineExtensions/tree/main/doc
|
||||||
|
stof_doctrine_extensions:
|
||||||
|
default_locale: fr_FR
|
||||||
|
orm:
|
||||||
|
default:
|
||||||
|
timestampable: true
|
||||||
|
sluggable: true
|
||||||
|
sortable: true
|
||||||
|
tree: true
|
||||||
16
config/packages/translation.yaml
Normal file
16
config/packages/translation.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
parameters:
|
||||||
|
requirements_locales: null # @see LocalesCompilerPass
|
||||||
|
|
||||||
|
framework:
|
||||||
|
default_locale: fr
|
||||||
|
translator:
|
||||||
|
default_path: '%kernel.project_dir%/translations'
|
||||||
|
fallbacks:
|
||||||
|
- fr
|
||||||
|
# providers:
|
||||||
|
# crowdin:
|
||||||
|
# dsn: '%env(CROWDIN_DSN)%'
|
||||||
|
# loco:
|
||||||
|
# dsn: '%env(LOCO_DSN)%'
|
||||||
|
# lokalise:
|
||||||
|
# dsn: '%env(LOKALISE_DSN)%'
|
||||||
16
config/packages/twig.yaml
Normal file
16
config/packages/twig.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
twig:
|
||||||
|
default_path: '%kernel.project_dir%/templates'
|
||||||
|
form_themes: ['bootstrap_5_horizontal_layout.html.twig'] # bootstrap_5_layout.html.twig
|
||||||
|
globals:
|
||||||
|
app_version: '%app_version%'
|
||||||
|
upload_images_allowed_extensions: '%upload_maxsize_by_file%'
|
||||||
|
upload_maxsize_by_file: '%upload_maxsize_by_file%'
|
||||||
|
upload_maxsize_total: '%upload_maxsize_total%'
|
||||||
|
upload_max_images: '%upload_max_images%'
|
||||||
|
brand: '%brand%'
|
||||||
|
role_user: !php/const App\Entity\User::ROLE_USER
|
||||||
|
role_admin: !php/const App\Entity\User::ROLE_ADMIN
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
twig:
|
||||||
|
strict_variables: true
|
||||||
4
config/packages/uid.yaml
Normal file
4
config/packages/uid.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
framework:
|
||||||
|
uid:
|
||||||
|
# default_uuid_version: 7
|
||||||
|
# time_based_uuid_version: 7
|
||||||
13
config/packages/validator.yaml
Normal file
13
config/packages/validator.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
framework:
|
||||||
|
validation:
|
||||||
|
email_validation_mode: html5
|
||||||
|
|
||||||
|
# Enables validator auto-mapping support.
|
||||||
|
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
|
||||||
|
#auto_mapping:
|
||||||
|
# App\Entity\: []
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
framework:
|
||||||
|
validation:
|
||||||
|
not_compromised_password: false
|
||||||
17
config/packages/web_profiler.yaml
Normal file
17
config/packages/web_profiler.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
when@dev:
|
||||||
|
web_profiler:
|
||||||
|
toolbar: '%kernel.debug%'
|
||||||
|
intercept_redirects: false
|
||||||
|
|
||||||
|
framework:
|
||||||
|
profiler:
|
||||||
|
only_exceptions: false
|
||||||
|
collect_serializer_data: true
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
web_profiler:
|
||||||
|
toolbar: false
|
||||||
|
intercept_redirects: false
|
||||||
|
|
||||||
|
framework:
|
||||||
|
profiler: { collect: false }
|
||||||
50
config/packages/webpack_encore.yaml
Normal file
50
config/packages/webpack_encore.yaml
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
webpack_encore:
|
||||||
|
# The path where Encore is building the assets - i.e. Encore.setOutputPath()
|
||||||
|
output_path: '%kernel.project_dir%/public/build'
|
||||||
|
# If multiple builds are defined (as shown below), you can disable the default build:
|
||||||
|
# output_path: false
|
||||||
|
|
||||||
|
# Set attributes that will be rendered on all script and link tags
|
||||||
|
script_attributes:
|
||||||
|
defer: true
|
||||||
|
# Uncomment (also under link_attributes) if using Turbo Drive
|
||||||
|
# https://turbo.hotwired.dev/handbook/drive#reloading-when-assets-change
|
||||||
|
# 'data-turbo-track': reload
|
||||||
|
# link_attributes:
|
||||||
|
# Uncomment if using Turbo Drive
|
||||||
|
# 'data-turbo-track': reload
|
||||||
|
|
||||||
|
# If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials')
|
||||||
|
# crossorigin: 'anonymous'
|
||||||
|
|
||||||
|
# Preload all rendered script and link tags automatically via the HTTP/2 Link header
|
||||||
|
# preload: true
|
||||||
|
|
||||||
|
# Throw an exception if the entrypoints.json file is missing or an entry is missing from the data
|
||||||
|
strict_mode: false
|
||||||
|
|
||||||
|
# If you have multiple builds:
|
||||||
|
# builds:
|
||||||
|
# pass "frontend" as the 3rg arg to the Twig functions
|
||||||
|
# {{ encore_entry_script_tags('entry1', null, 'frontend') }}
|
||||||
|
|
||||||
|
# frontend: '%kernel.project_dir%/public/frontend/build'
|
||||||
|
|
||||||
|
# Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
|
||||||
|
# Put in config/packages/prod/webpack_encore.yaml
|
||||||
|
# cache: true
|
||||||
|
|
||||||
|
framework:
|
||||||
|
assets:
|
||||||
|
json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
|
||||||
|
|
||||||
|
when@prod:
|
||||||
|
webpack_encore:
|
||||||
|
# Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
|
||||||
|
# Available in version 1.2
|
||||||
|
cache: true
|
||||||
|
strict_mode: true
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
webpack_encore:
|
||||||
|
strict_mode: false
|
||||||
56
config/packages/workflow.yaml
Normal file
56
config/packages/workflow.yaml
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
# https://symfony.com/doc/current/workflow.html#configuration
|
||||||
|
# Get the generated services :
|
||||||
|
# $ php bin/console debug:autowiring workflow
|
||||||
|
# Generate the graphs in "/docs":
|
||||||
|
# $ make workflows
|
||||||
|
framework:
|
||||||
|
workflows:
|
||||||
|
service_request_status:
|
||||||
|
type: 'state_machine'
|
||||||
|
audit_trail:
|
||||||
|
enabled: true
|
||||||
|
marking_store:
|
||||||
|
type: 'method'
|
||||||
|
# for now workflow uses strings not enums
|
||||||
|
# @see https://github.com/symfony/symfony/issues/44211
|
||||||
|
property: 'statusRaw'
|
||||||
|
supports:
|
||||||
|
- App\Entity\ServiceRequest
|
||||||
|
initial_marking: new
|
||||||
|
# @see ServiceRequestStatus
|
||||||
|
places:
|
||||||
|
- new
|
||||||
|
- to_confirm
|
||||||
|
- confirmed
|
||||||
|
- refused
|
||||||
|
- finished
|
||||||
|
# @see ServiceRequestStatusWorkflow
|
||||||
|
transitions:
|
||||||
|
# owner confirmation
|
||||||
|
accept:
|
||||||
|
from: new
|
||||||
|
to: to_confirm
|
||||||
|
# the owner modifies the dates and accept the request
|
||||||
|
modifyOwner:
|
||||||
|
from: new
|
||||||
|
to: to_confirm
|
||||||
|
# the recipient modifies the dates and ask the owner to validate again
|
||||||
|
modifyRecipient:
|
||||||
|
from: to_confirm
|
||||||
|
to: new
|
||||||
|
# recipient confirmation
|
||||||
|
confirm:
|
||||||
|
from: to_confirm
|
||||||
|
to: confirmed
|
||||||
|
# transaction manually finalized by the owner
|
||||||
|
finalize:
|
||||||
|
from: confirmed
|
||||||
|
to: finished
|
||||||
|
# transaction auto-finalized by the system
|
||||||
|
autoFinalize:
|
||||||
|
from: confirmed
|
||||||
|
to: finished
|
||||||
|
# refusal from the owner or recipient
|
||||||
|
refuse:
|
||||||
|
from: [new, to_confirm, confirmed]
|
||||||
|
to: refused
|
||||||
11
config/packages_extra/doctrine.yaml
Normal file
11
config/packages_extra/doctrine.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# additional services related to Doctrine
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
# Needed to activate autowiring for the Doctrine listener
|
||||||
|
App\Doctrine\Listener\:
|
||||||
|
resource: '../../src/Doctrine/Listener'
|
||||||
|
tags:
|
||||||
|
- { name: doctrine.orm.entity_listener }
|
||||||
53
config/packages_extra/flysystem.yaml
Normal file
53
config/packages_extra/flysystem.yaml
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
# additional services related to Flysystem
|
||||||
|
parameters:
|
||||||
|
# Allowed extensions for images
|
||||||
|
upload_images_allowed_extensions: ['png', 'jpg', 'jpeg']
|
||||||
|
|
||||||
|
# Allowed maxsize by file (mb)
|
||||||
|
upload_maxsize_by_file: 1
|
||||||
|
|
||||||
|
# Allowed maxsize for multiple uploads (mb)
|
||||||
|
upload_maxsize_total: 5
|
||||||
|
|
||||||
|
# Max number of photos/images by product
|
||||||
|
upload_max_images: 5
|
||||||
|
|
||||||
|
# S3 Bucket config
|
||||||
|
storage_endpoint: '%env(string:STORAGE_ENDPOINT)%'
|
||||||
|
storage_region: '%env(string:STORAGE_REGION)%'
|
||||||
|
storage_use_path_style_endpoint: '%env(bool:STORAGE_USE_PATH_STYLE_ENDPOINT)%'
|
||||||
|
storage_key: '%env(string:STORAGE_KEY)%'
|
||||||
|
storage_secret: '%env(string:STORAGE_SECRET)%'
|
||||||
|
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
_instanceof:
|
||||||
|
App\Twig\FlysystemImageInterface:
|
||||||
|
tags: [app.flysystem_image_extension]
|
||||||
|
|
||||||
|
App\Twig\FlysystemImagesInterface:
|
||||||
|
tags: [app.flysystem_images_extension]
|
||||||
|
|
||||||
|
App\Twig\:
|
||||||
|
resource: '../../src/Twig/'
|
||||||
|
|
||||||
|
App\Twig\ImageExtensionCollection:
|
||||||
|
arguments:
|
||||||
|
- !tagged_iterator app.flysystem_image_extension
|
||||||
|
|
||||||
|
App\Twig\ImagesExtensionCollection:
|
||||||
|
arguments:
|
||||||
|
- !tagged_iterator app.flysystem_images_extension
|
||||||
|
|
||||||
|
Aws\S3\S3Client:
|
||||||
|
arguments:
|
||||||
|
- endpoint: '%storage_endpoint%'
|
||||||
|
version: 'latest'
|
||||||
|
region: '%storage_region%'
|
||||||
|
use_path_style_endpoint: '%storage_use_path_style_endpoint%'
|
||||||
|
credentials:
|
||||||
|
key: '%storage_key%'
|
||||||
|
secret: '%storage_secret%'
|
||||||
17
config/packages_extra/mailer.yaml
Normal file
17
config/packages_extra/mailer.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# additional services related to the mailer
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
_instanceof:
|
||||||
|
App\Mailer\Email\EmailInterface:
|
||||||
|
tags: ['app.email']
|
||||||
|
|
||||||
|
# we need to reload EmailInterface objects here so the correct tag is applied
|
||||||
|
App\Mailer\Email\:
|
||||||
|
resource: '../../src/Mailer/Email/'
|
||||||
|
|
||||||
|
App\Mailer\EmailCollection:
|
||||||
|
arguments:
|
||||||
|
- !tagged_iterator app.email
|
||||||
11
config/packages_extra/uuid.yaml
Normal file
11
config/packages_extra/uuid.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# additional services related to the uuid component
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
# Activate these commands
|
||||||
|
Symfony\Component\Uid\Command\GenerateUlidCommand: ~
|
||||||
|
Symfony\Component\Uid\Command\GenerateUuidCommand: ~
|
||||||
|
Symfony\Component\Uid\Command\InspectUlidCommand: ~
|
||||||
|
Symfony\Component\Uid\Command\InspectUuidCommand: ~
|
||||||
7
config/preload.php
Normal file
7
config/preload.php
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||||
|
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||||
|
}
|
||||||
13
config/routes.yaml
Normal file
13
config/routes.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# load everyting in Controller and use attributes
|
||||||
|
controllers:
|
||||||
|
resource: ../src/Controller/
|
||||||
|
type: attribute
|
||||||
|
|
||||||
|
# avoid to have an empty and not used function in SecurityController
|
||||||
|
app_logout:
|
||||||
|
path: /logout
|
||||||
|
|
||||||
|
# Payoum:
|
||||||
|
# @see https://github.com/Payum/Payum/blob/master/docs/symfony/get-it-started.md#payum-bundle-get-it-started"
|
||||||
|
payum_all:
|
||||||
|
resource: "@PayumBundle/Resources/config/routing/all.xml"
|
||||||
12
config/routes/annotations.yaml
Normal file
12
config/routes/annotations.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
controllers:
|
||||||
|
resource: '../../src/Controller/'
|
||||||
|
type: annotation
|
||||||
|
# the prefix is only used when i18n are not explicitly defined
|
||||||
|
# allowed prefixes are defined by the "kernel.enabled_locales" parameter
|
||||||
|
# @see config/packages/framework.yaml
|
||||||
|
prefix: /{_locale}
|
||||||
|
|
||||||
|
# No prefix for the root route :) it handles "/" and redirects
|
||||||
|
root:
|
||||||
|
resource: '../../src/Controller/AppController.php'
|
||||||
|
type: annotation
|
||||||
4
config/routes/api_platform.yaml
Normal file
4
config/routes/api_platform.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
api_platform:
|
||||||
|
resource: .
|
||||||
|
type: api_platform
|
||||||
|
prefix: /api
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue