From ca8b1a11e43a638b204ede276134c1cbb95c3cc1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:17:39 +0000 Subject: [PATCH 1/9] Initial plan From 4a7f2f3edf0e347e390c417a631227f12830001b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:23:11 +0000 Subject: [PATCH 2/9] Add Docker development environment setup files Co-authored-by: ruslanbaidan <3246171+ruslanbaidan@users.noreply.github.com> --- .dockerignore | 46 +++++ .env.dev | 18 ++ .gitignore | 2 + Dockerfile | 114 ++++++++++++ Dockerfile.stats | 38 ++++ README.docker.md | 344 +++++++++++++++++++++++++++++++++++++ docker-compose.dev.yml | 124 +++++++++++++ docker-entrypoint.sh | 156 +++++++++++++++++ docker-stats-entrypoint.sh | 97 +++++++++++ 9 files changed, 939 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.dev create mode 100644 Dockerfile create mode 100644 Dockerfile.stats create mode 100644 README.docker.md create mode 100644 docker-compose.dev.yml create mode 100644 docker-entrypoint.sh create mode 100644 docker-stats-entrypoint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f568e03 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,46 @@ +# Git files +.git +.gitignore +.github + +# Documentation +README.md +CHANGELOG.md +AUTHORS +LICENSE +SECURITY.md +*.md + +# Development files +vagrant/ +wsl/ +INSTALL/ +.idea +.vscode +.DS_Store + +# Dependencies (will be installed in container) +vendor/ +node_modules/ + +# Data directories (will be mounted as volumes) +data/ + +# Build artifacts +public/css/ +public/js/ +public/img/ +public/flags/ +public/views/ + +# Logs +*.log +npm-debug.log + +# Cache +*.cache +.docker-initialized + +# Environment files (should be configured separately) +.env +.env.dev diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..1cf1339 --- /dev/null +++ b/.env.dev @@ -0,0 +1,18 @@ +# MariaDB Configuration +DBPASSWORD_ADMIN=root +DBNAME_COMMON=monarc_common +DBNAME_CLI=monarc_cli +DBUSER_MONARC=sqlmonarcuser +DBPASSWORD_MONARC=sqlmonarcuser + +# Stats Service Configuration +STATS_HOST=0.0.0.0 +STATS_PORT=5005 +STATS_DB_NAME=statsservice +STATS_DB_USER=sqlmonarcuser +STATS_DB_PASSWORD=sqlmonarcuser +# Generate a random secret key for production use: +# openssl rand -hex 32 +STATS_SECRET_KEY=changeme_generate_random_secret_key_for_production +# This will be generated by stats service on first run +STATS_API_KEY=will_be_generated_on_first_run diff --git a/.gitignore b/.gitignore index 9fb0019..c2db730 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ bin/ data/* !data/fonts .docker/mariaDb/data/* +.env +.docker-initialized diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..eab8cd8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,114 @@ +FROM ubuntu:22.04 + +# Prevent interactive prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive +ENV LANGUAGE=en_US.UTF-8 +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 + +# Install system dependencies +RUN apt-get update && apt-get upgrade -y && \ + apt-get install -y \ + vim \ + zip \ + unzip \ + git \ + gettext \ + curl \ + gsfonts \ + apache2 \ + php8.1 \ + php8.1-cli \ + php8.1-common \ + php8.1-mysql \ + php8.1-zip \ + php8.1-gd \ + php8.1-mbstring \ + php8.1-curl \ + php8.1-xml \ + php8.1-bcmath \ + php8.1-intl \ + php8.1-imagick \ + php8.1-xdebug \ + locales \ + wget \ + ca-certificates \ + gnupg && \ + locale-gen en_US.UTF-8 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Configure PHP +RUN sed -i 's/upload_max_filesize = .*/upload_max_filesize = 200M/' /etc/php/8.1/apache2/php.ini && \ + sed -i 's/post_max_size = .*/post_max_size = 50M/' /etc/php/8.1/apache2/php.ini && \ + sed -i 's/max_execution_time = .*/max_execution_time = 100/' /etc/php/8.1/apache2/php.ini && \ + sed -i 's/max_input_time = .*/max_input_time = 223/' /etc/php/8.1/apache2/php.ini && \ + sed -i 's/memory_limit = .*/memory_limit = 512M/' /etc/php/8.1/apache2/php.ini && \ + sed -i 's/session\.gc_maxlifetime = .*/session.gc_maxlifetime = 604800/' /etc/php/8.1/apache2/php.ini && \ + sed -i 's/session\.gc_probability = .*/session.gc_probability = 1/' /etc/php/8.1/apache2/php.ini && \ + sed -i 's/session\.gc_divisor = .*/session.gc_divisor = 1000/' /etc/php/8.1/apache2/php.ini + +# Configure Xdebug for development +RUN echo "zend_extension=xdebug.so" > /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.mode=debug" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.discover_client_host=1" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.idekey=IDEKEY" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini + +# Enable Apache modules +RUN a2enmod rewrite ssl headers + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Install Node.js and npm +RUN mkdir -p /etc/apt/keyrings && \ + curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_15.x nodistro main" > /etc/apt/sources.list.d/nodesource.list && \ + apt-get update && \ + apt-get install -y nodejs npm && \ + npm install -g grunt-cli && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Set working directory +WORKDIR /var/www/html/monarc + +# Configure Apache +RUN echo '\n\ + ServerName localhost\n\ + DocumentRoot /var/www/html/monarc/public\n\ +\n\ + \n\ + DirectoryIndex index.php\n\ + AllowOverride All\n\ + Require all granted\n\ + \n\ +\n\ + \n\ + Header always set X-Content-Type-Options nosniff\n\ + Header always set X-XSS-Protection "1; mode=block"\n\ + Header always set X-Robots-Tag none\n\ + Header always set X-Frame-Options SAMEORIGIN\n\ + \n\ +\n\ + SetEnv APP_ENV development\n\ + SetEnv APP_DIR /var/www/html/monarc\n\ +' > /etc/apache2/sites-available/000-default.conf + +# Allow Apache override to all +RUN sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf + +# Create necessary directories +RUN mkdir -p /var/www/html/monarc/data/cache \ + /var/www/html/monarc/data/LazyServices/Proxy \ + /var/www/html/monarc/data/DoctrineORMModule/Proxy \ + /var/www/html/monarc/data/import/files + +# Copy entrypoint script +COPY docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +EXPOSE 80 + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["apache2-foreground"] diff --git a/Dockerfile.stats b/Dockerfile.stats new file mode 100644 index 0000000..a2b9bee --- /dev/null +++ b/Dockerfile.stats @@ -0,0 +1,38 @@ +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV LANGUAGE=en_US.UTF-8 +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 +ENV FLASK_APP=runserver.py +ENV STATS_CONFIG=production.py + +# Install dependencies +RUN apt-get update && \ + apt-get install -y \ + git \ + curl \ + python3 \ + python3-pip \ + python3-venv \ + nodejs \ + npm \ + postgresql-client \ + locales && \ + locale-gen en_US.UTF-8 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Install Poetry +RUN curl -sSL https://install.python-poetry.org | python3 - && \ + ln -s /root/.local/bin/poetry /usr/local/bin/poetry + +WORKDIR /var/www/stats-service + +# Copy entrypoint script +COPY docker-stats-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-stats-entrypoint.sh + +EXPOSE 5005 + +ENTRYPOINT ["docker-stats-entrypoint.sh"] diff --git a/README.docker.md b/README.docker.md new file mode 100644 index 0000000..1f26cb2 --- /dev/null +++ b/README.docker.md @@ -0,0 +1,344 @@ +# Docker Development Environment for MONARC FrontOffice + +This guide explains how to set up a local development environment for MONARC FrontOffice using Docker. + +## Prerequisites + +- Docker Engine 20.10 or later +- Docker Compose V2 (comes with Docker Desktop) +- At least 8GB of RAM available for Docker +- At least 20GB of free disk space + +## Quick Start + +1. **Clone the repository** (if you haven't already): + ```bash + git clone https://github.com/monarc-project/MonarcAppFO + cd MonarcAppFO + ``` + +2. **Copy the environment file**: + ```bash + cp .env.dev .env + ``` + +3. **Customize environment variables** (optional): + Edit `.env` file to change default passwords and configuration: + ```bash + # Generate a secure secret key for stats service + openssl rand -hex 32 + # Update STATS_SECRET_KEY in .env with the generated value + ``` + +4. **Start the development environment**: + ```bash + docker-compose -f docker-compose.dev.yml up --build + ``` + + The first run will take several minutes as it: + - Builds the Docker images + - Installs all dependencies (PHP, Node.js, Python) + - Clones frontend repositories + - Initializes databases + - Sets up the stats service + - Creates the initial admin user + +5. **Access the application**: + - MONARC FrontOffice: http://localhost:5001 + - Stats Service: http://localhost:5005 + - MailCatcher (email testing): http://localhost:1080 + +6. **Login credentials**: + - Username: `admin@admin.localhost` + - Password: `admin` + +## Services + +The development environment includes the following services: + +| Service | Description | Port | Container Name | +|---------|-------------|------|----------------| +| monarc | Main FrontOffice application (PHP/Apache) | 5001 | monarc-fo-app | +| db | MariaDB database | 3306 | monarc-fo-db | +| postgres | PostgreSQL database (for stats) | 5432 | monarc-fo-postgres | +| stats-service | MONARC Statistics Service | 5005 | monarc-fo-stats | +| mailcatcher | Email testing tool | 1080 (web), 1025 (SMTP) | monarc-fo-mailcatcher | + +## Development Workflow + +### Live Code Editing + +The application source code is mounted as a volume, so changes you make on your host machine will be immediately reflected in the container. After making changes: + +1. **PHP/Backend changes**: Apache automatically reloads modified files +2. **Frontend changes**: You may need to rebuild the frontend: + ```bash + docker exec -it monarc-fo-app bash + cd /var/www/html/monarc + ./scripts/update-all.sh -d + ``` + +### Accessing the Container + +To access the MONARC application container: +```bash +docker exec -it monarc-fo-app bash +``` + +To access the stats service container: +```bash +docker exec -it monarc-fo-stats bash +``` + +### Database Access + +Connect to MariaDB: +```bash +docker exec -it monarc-fo-db mysql -usqlmonarcuser -psqlmonarcuser monarc_common +``` + +Connect to PostgreSQL: +```bash +docker exec -it monarc-fo-postgres psql -U sqlmonarcuser -d statsservice +``` + +### Viewing Logs + +View logs for all services: +```bash +docker-compose -f docker-compose.dev.yml logs -f +``` + +View logs for a specific service: +```bash +docker-compose -f docker-compose.dev.yml logs -f monarc +docker-compose -f docker-compose.dev.yml logs -f stats-service +``` + +### Restarting Services + +Restart all services: +```bash +docker-compose -f docker-compose.dev.yml restart +``` + +Restart a specific service: +```bash +docker-compose -f docker-compose.dev.yml restart monarc +``` + +### Stopping the Environment + +Stop all services (keeps data): +```bash +docker-compose -f docker-compose.dev.yml stop +``` + +Stop and remove containers (keeps volumes/data): +```bash +docker-compose -f docker-compose.dev.yml down +``` + +Stop and remove everything including data: +```bash +docker-compose -f docker-compose.dev.yml down -v +``` + +## Common Tasks + +### Resetting the Database + +To completely reset the databases: +```bash +docker-compose -f docker-compose.dev.yml down -v +docker-compose -f docker-compose.dev.yml up --build +``` + +### Installing New PHP Dependencies + +```bash +docker exec -it monarc-fo-app bash +composer require package/name +``` + +### Installing New Node Dependencies + +```bash +docker exec -it monarc-fo-app bash +cd node_modules/ng_client # or ng_anr +npm install package-name +``` + +### Running Database Migrations + +```bash +docker exec -it monarc-fo-app bash +php ./vendor/robmorgan/phinx/bin/phinx migrate -c ./module/Monarc/FrontOffice/migrations/phinx.php +``` + +### Creating Database Seeds + +```bash +docker exec -it monarc-fo-app bash +php ./bin/phinx seed:run -c ./module/Monarc/FrontOffice/migrations/phinx.php +``` + +### Rebuilding Frontend + +```bash +docker exec -it monarc-fo-app bash +cd /var/www/html/monarc +./scripts/update-all.sh -d +``` + +## Debugging + +### Xdebug Configuration + +Xdebug is pre-configured in the development environment. To use it: + +1. Configure your IDE to listen on port 9003 +2. Set the IDE key to `IDEKEY` +3. Start debugging in your IDE +4. Trigger a request to the application + +For PhpStorm: +- Go to Settings → PHP → Debug +- Set Xdebug port to 9003 +- Enable "Can accept external connections" +- Set the path mappings: `/var/www/html/monarc` → your local project path + +### Checking Service Health + +```bash +# Check if all services are running +docker-compose -f docker-compose.dev.yml ps + +# Check specific service health +docker-compose -f docker-compose.dev.yml ps monarc +``` + +## Troubleshooting + +### Port Conflicts + +If you get port conflicts, you can change the ports in the `docker-compose.dev.yml` file: +```yaml +ports: + - "5001:80" # Change 5001 to another available port +``` + +### Permission Issues + +If you encounter permission issues with mounted volumes: +```bash +docker exec -it monarc-fo-app bash +chown -R www-data:www-data /var/www/html/monarc/data +chmod -R 775 /var/www/html/monarc/data +``` + +### Database Connection Issues + +Check if the database is healthy: +```bash +docker-compose -f docker-compose.dev.yml ps db +``` + +If needed, restart the database: +```bash +docker-compose -f docker-compose.dev.yml restart db +``` + +### Stats Service Issues + +Check stats service logs: +```bash +docker-compose -f docker-compose.dev.yml logs stats-service +``` + +Restart the stats service: +```bash +docker-compose -f docker-compose.dev.yml restart stats-service +``` + +### Rebuilding from Scratch + +If something goes wrong and you want to start fresh: +```bash +# Stop everything +docker-compose -f docker-compose.dev.yml down -v + +# Remove all related containers, images, and volumes +docker system prune -a + +# Rebuild and start +docker-compose -f docker-compose.dev.yml up --build +``` + +## Performance Optimization + +For better performance on macOS and Windows: + +1. **Use Docker volume mounts for dependencies**: The compose file already uses named volumes for `vendor` and `node_modules` to improve performance. + +2. **Allocate more resources**: In Docker Desktop settings, increase: + - CPUs: 4 or more + - Memory: 8GB or more + - Swap: 2GB or more + +3. **Enable caching**: The Dockerfile uses apt cache and composer optimizations. + +## Comparison with Vagrant + +| Feature | Docker | Vagrant | +|---------|--------|---------| +| Startup time | Fast (~2-3 min) | Slow (~10-15 min) | +| Resource usage | Lower | Higher | +| Isolation | Container-level | VM-level | +| Portability | Excellent | Good | +| Live code reload | Yes | Yes | +| Learning curve | Moderate | Low | + +## Environment Variables Reference + +All environment variables are defined in the `.env` file: + +| Variable | Description | Default | +|----------|-------------|---------| +| `DBPASSWORD_ADMIN` | MariaDB root password | `root` | +| `DBNAME_COMMON` | Common database name | `monarc_common` | +| `DBNAME_CLI` | CLI database name | `monarc_cli` | +| `DBUSER_MONARC` | Database user | `sqlmonarcuser` | +| `DBPASSWORD_MONARC` | Database password | `sqlmonarcuser` | +| `STATS_HOST` | Stats service host | `0.0.0.0` | +| `STATS_PORT` | Stats service port | `5005` | +| `STATS_DB_NAME` | Stats database name | `statsservice` | +| `STATS_DB_USER` | Stats database user | `sqlmonarcuser` | +| `STATS_DB_PASSWORD` | Stats database password | `sqlmonarcuser` | +| `STATS_SECRET_KEY` | Stats service secret key | `changeme_generate_random_secret_key_for_production` | + +## Security Notes + +⚠️ **Important**: The default credentials provided are for development only. Never use these in production! + +For production deployments: +1. Change all default passwords +2. Generate a secure `STATS_SECRET_KEY` using `openssl rand -hex 32` +3. Use proper SSL/TLS certificates +4. Follow security best practices + +## Additional Resources + +- [MONARC Website](https://www.monarc.lu) +- [MONARC Documentation](https://www.monarc.lu/documentation) +- [GitHub Repository](https://github.com/monarc-project/MonarcAppFO) +- [MonarcAppBO (BackOffice)](https://github.com/monarc-project/MonarcAppBO) + +## Getting Help + +If you encounter issues: + +1. Check the [troubleshooting section](#troubleshooting) +2. Review the logs: `docker-compose -f docker-compose.dev.yml logs` +3. Open an issue on [GitHub](https://github.com/monarc-project/MonarcAppFO/issues) +4. Join the MONARC community discussions diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..6803d71 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,124 @@ +version: '3.8' + +services: + # MariaDB database for MONARC + db: + image: mariadb:10.11 + container_name: monarc-fo-db + environment: + MYSQL_ROOT_PASSWORD: ${DBPASSWORD_ADMIN} + MYSQL_DATABASE: ${DBNAME_COMMON} + MYSQL_USER: ${DBUSER_MONARC} + MYSQL_PASSWORD: ${DBPASSWORD_MONARC} + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_general_ci + - --bind-address=0.0.0.0 + ports: + - "3306:3306" + volumes: + - db_data:/var/lib/mysql + networks: + - monarc-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DBPASSWORD_ADMIN}"] + interval: 10s + timeout: 5s + retries: 5 + + # PostgreSQL database for stats service + postgres: + image: postgres:15 + container_name: monarc-fo-postgres + environment: + POSTGRES_USER: ${STATS_DB_USER} + POSTGRES_PASSWORD: ${STATS_DB_PASSWORD} + POSTGRES_DB: ${STATS_DB_NAME} + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - monarc-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${STATS_DB_USER}"] + interval: 10s + timeout: 5s + retries: 5 + + # Stats service + stats-service: + build: + context: . + dockerfile: Dockerfile.stats + container_name: monarc-fo-stats + environment: + STATS_HOST: ${STATS_HOST} + STATS_PORT: ${STATS_PORT} + STATS_DB_HOST: postgres + STATS_DB_NAME: ${STATS_DB_NAME} + STATS_DB_USER: ${STATS_DB_USER} + STATS_DB_PASSWORD: ${STATS_DB_PASSWORD} + STATS_SECRET_KEY: ${STATS_SECRET_KEY} + ports: + - "5005:5005" + depends_on: + postgres: + condition: service_healthy + networks: + - monarc-network + volumes: + - stats_data:/var/www/stats-service + + # MailCatcher for email testing + mailcatcher: + image: sj26/mailcatcher:latest + container_name: monarc-fo-mailcatcher + ports: + - "1080:1080" # Web interface + - "1025:1025" # SMTP + networks: + - monarc-network + + # Main MONARC FrontOffice application + monarc: + build: + context: . + dockerfile: Dockerfile + container_name: monarc-fo-app + environment: + DBHOST: db + DBNAME_COMMON: ${DBNAME_COMMON} + DBNAME_CLI: ${DBNAME_CLI} + DBUSER_MONARC: ${DBUSER_MONARC} + DBPASSWORD_MONARC: ${DBPASSWORD_MONARC} + STATS_API_KEY: ${STATS_API_KEY} + APP_ENV: development + APP_DIR: /var/www/html/monarc + ports: + - "5001:80" + depends_on: + db: + condition: service_healthy + stats-service: + condition: service_started + networks: + - monarc-network + volumes: + # Mount the application code for live development + - ./:/var/www/html/monarc + # Preserve vendor directory in named volume for better performance + - vendor_data:/var/www/html/monarc/vendor + - node_modules_data:/var/www/html/monarc/node_modules + working_dir: /var/www/html/monarc + +networks: + monarc-network: + driver: bridge + +volumes: + db_data: + postgres_data: + stats_data: + vendor_data: + node_modules_data: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..b022597 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,156 @@ +#!/bin/bash +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}Starting MONARC FrontOffice setup...${NC}" + +# Wait for database to be ready +echo -e "${YELLOW}Waiting for MariaDB to be ready...${NC}" +while ! mysqladmin ping -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" --silent 2>/dev/null; do + echo "Waiting for MariaDB..." + sleep 2 +done +echo -e "${GREEN}MariaDB is ready!${NC}" + +# Check if this is the first run +if [ ! -f "/var/www/html/monarc/.docker-initialized" ]; then + echo -e "${GREEN}First run detected, initializing application...${NC}" + + cd /var/www/html/monarc + + # Install composer dependencies + if [ ! -d "vendor" ]; then + echo -e "${YELLOW}Installing Composer dependencies...${NC}" + composer install --ignore-platform-req=php + fi + + # Create module symlinks + echo -e "${YELLOW}Creating module symlinks...${NC}" + mkdir -p module/Monarc + cd module/Monarc + ln -sfn ./../../vendor/monarc/core Core + ln -sfn ./../../vendor/monarc/frontoffice FrontOffice + cd /var/www/html/monarc + + # Clone frontend repositories + echo -e "${YELLOW}Setting up frontend repositories...${NC}" + mkdir -p node_modules + cd node_modules + + if [ ! -d "ng_client" ]; then + git clone --config core.fileMode=false https://github.com/monarc-project/ng-client.git ng_client + fi + + if [ ! -d "ng_anr" ]; then + git clone --config core.fileMode=false https://github.com/monarc-project/ng-anr.git ng_anr + fi + + cd /var/www/html/monarc + + # Check if database exists and create if needed + echo -e "${YELLOW}Setting up databases...${NC}" + DB_EXISTS=$(mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" -e "SHOW DATABASES LIKE '${DBNAME_CLI}';" | grep -c "${DBNAME_CLI}" || true) + + if [ "$DB_EXISTS" -eq 0 ]; then + echo -e "${YELLOW}Creating databases...${NC}" + mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" -e "CREATE DATABASE ${DBNAME_CLI} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" + mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" -e "CREATE DATABASE ${DBNAME_COMMON} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" + + echo -e "${YELLOW}Populating databases...${NC}" + mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" ${DBNAME_COMMON} < db-bootstrap/monarc_structure.sql + mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" ${DBNAME_COMMON} < db-bootstrap/monarc_data.sql + fi + + # Generate local config if it doesn't exist + if [ ! -f "config/autoload/local.php" ]; then + echo -e "${YELLOW}Creating local configuration...${NC}" + cat > config/autoload/local.php < [ + 'connection' => [ + 'orm_default' => [ + 'params' => [ + 'host' => '${DBHOST}', + 'user' => '${DBUSER_MONARC}', + 'password' => '${DBPASSWORD_MONARC}', + 'dbname' => '${DBNAME_COMMON}', + ], + ], + 'orm_cli' => [ + 'params' => [ + 'host' => '${DBHOST}', + 'user' => '${DBUSER_MONARC}', + 'password' => '${DBPASSWORD_MONARC}', + 'dbname' => '${DBNAME_CLI}', + ], + ], + ], + ], + + 'activeLanguages' => array('fr','en','de','nl','es','ro','it','ja','pl','pt','ru','zh'), + + 'appVersion' => \$package_json['version'], + + 'checkVersion' => false, + 'appCheckingURL' => 'https://version.monarc.lu/check/MONARC', + + 'email' => [ + 'name' => 'MONARC', + 'from' => 'info@monarc.lu', + ], + + 'mospApiUrl' => 'https://objects.monarc.lu/api/', + + 'monarc' => [ + 'ttl' => 60, // timeout + 'salt' => '', // private salt for password encryption + ], + + 'statsApi' => [ + 'baseUrl' => 'http://stats-service:5005', + 'apiKey' => '${STATS_API_KEY}', + ], + + 'import' => [ + 'uploadFolder' => '\$appdir/data/import/files', + 'isBackgroundProcessActive' => false, + ], +]; +EOF + fi + + # Update and build frontend + echo -e "${YELLOW}Building frontend...${NC}" + ./scripts/update-all.sh -d + + # Seed database with initial user + echo -e "${YELLOW}Creating initial user and client...${NC}" + php ./bin/phinx seed:run -c ./module/Monarc/FrontOffice/migrations/phinx.php + + # Set permissions + echo -e "${YELLOW}Setting permissions...${NC}" + chown -R www-data:www-data /var/www/html/monarc/data + chmod -R 775 /var/www/html/monarc/data + + # Mark initialization as complete + touch /var/www/html/monarc/.docker-initialized + echo -e "${GREEN}Initialization complete!${NC}" +else + echo -e "${GREEN}Application already initialized, starting services...${NC}" +fi + +# Execute the main command +exec apache2-foreground diff --git a/docker-stats-entrypoint.sh b/docker-stats-entrypoint.sh new file mode 100644 index 0000000..cd6cb12 --- /dev/null +++ b/docker-stats-entrypoint.sh @@ -0,0 +1,97 @@ +#!/bin/bash +set -e + +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo -e "${GREEN}Starting MONARC Stats Service setup...${NC}" + +# Wait for PostgreSQL to be ready +echo -e "${YELLOW}Waiting for PostgreSQL to be ready...${NC}" +until PGPASSWORD=$STATS_DB_PASSWORD psql -h "$STATS_DB_HOST" -U "$STATS_DB_USER" -d postgres -c '\q' 2>/dev/null; do + echo "Waiting for PostgreSQL..." + sleep 2 +done +echo -e "${GREEN}PostgreSQL is ready!${NC}" + +# Check if this is the first run +if [ ! -f "/var/www/stats-service/.docker-initialized" ]; then + echo -e "${GREEN}First run detected, initializing stats service...${NC}" + + # Clone the stats service repository + if [ ! -d "/var/www/stats-service/.git" ]; then + echo -e "${YELLOW}Cloning stats-service repository...${NC}" + cd /var/www + git clone https://github.com/monarc-project/stats-service stats-service-tmp + cp -r stats-service-tmp/* stats-service/ + cp -r stats-service-tmp/.git stats-service/ + rm -rf stats-service-tmp + cd /var/www/stats-service + fi + + # Install npm dependencies + echo -e "${YELLOW}Installing npm dependencies...${NC}" + npm ci + + # Install Python dependencies with Poetry + echo -e "${YELLOW}Installing Python dependencies with Poetry...${NC}" + poetry install --no-dev + + # Create instance directory and configuration + echo -e "${YELLOW}Creating configuration...${NC}" + mkdir -p instance + cat > instance/production.py < Date: Mon, 12 Jan 2026 16:25:26 +0000 Subject: [PATCH 3/9] Fix Docker configuration and improve setup Co-authored-by: ruslanbaidan <3246171+ruslanbaidan@users.noreply.github.com> --- .env.dev | 5 +++-- Dockerfile | 3 ++- README.docker.md | 15 ++++++++++++++- docker-compose.dev.yml | 2 -- docker-entrypoint.sh | 4 ++-- docker-stats-entrypoint.sh | 0 6 files changed, 21 insertions(+), 8 deletions(-) mode change 100644 => 100755 docker-entrypoint.sh mode change 100644 => 100755 docker-stats-entrypoint.sh diff --git a/.env.dev b/.env.dev index 1cf1339..049c9ba 100644 --- a/.env.dev +++ b/.env.dev @@ -14,5 +14,6 @@ STATS_DB_PASSWORD=sqlmonarcuser # Generate a random secret key for production use: # openssl rand -hex 32 STATS_SECRET_KEY=changeme_generate_random_secret_key_for_production -# This will be generated by stats service on first run -STATS_API_KEY=will_be_generated_on_first_run +# Stats API Key - Leave empty on first run, it will be generated by the stats service +# After first run, get it from the stats service logs or container +STATS_API_KEY= diff --git a/Dockerfile b/Dockerfile index eab8cd8..ad70470 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,7 @@ RUN apt-get update && apt-get upgrade -y && \ gettext \ curl \ gsfonts \ + mariadb-client \ apache2 \ php8.1 \ php8.1-cli \ @@ -111,4 +112,4 @@ RUN chmod +x /usr/local/bin/docker-entrypoint.sh EXPOSE 80 ENTRYPOINT ["docker-entrypoint.sh"] -CMD ["apache2-foreground"] +CMD ["apachectl", "-D", "FOREGROUND"] diff --git a/README.docker.md b/README.docker.md index 1f26cb2..efc4a76 100644 --- a/README.docker.md +++ b/README.docker.md @@ -48,7 +48,20 @@ This guide explains how to set up a local development environment for MONARC Fro - Stats Service: http://localhost:5005 - MailCatcher (email testing): http://localhost:1080 -6. **Login credentials**: +6. **(Optional) Configure Stats API Key**: + The stats service generates an API key on first run. To retrieve it: + ```bash + # Check the stats service logs for the API key + docker-compose -f docker-compose.dev.yml logs stats-service | grep "Token:" + + # Or create a new client and get the key + docker exec -it monarc-fo-stats poetry run flask client_create --name monarc + + # Update the .env file with the API key and restart the monarc service + docker-compose -f docker-compose.dev.yml restart monarc + ``` + +7. **Login credentials**: - Username: `admin@admin.localhost` - Password: `admin` diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 6803d71..0941b81 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: # MariaDB database for MONARC db: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh old mode 100644 new mode 100755 index b022597..2c836c2 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -121,7 +121,7 @@ return [ 'statsApi' => [ 'baseUrl' => 'http://stats-service:5005', - 'apiKey' => '${STATS_API_KEY}', + 'apiKey' => '${STATS_API_KEY:-}', ], 'import' => [ @@ -153,4 +153,4 @@ else fi # Execute the main command -exec apache2-foreground +exec apachectl -D FOREGROUND diff --git a/docker-stats-entrypoint.sh b/docker-stats-entrypoint.sh old mode 100644 new mode 100755 From fa3ef0d0e294e2b1bdcb2548205c5d9375882f33 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:28:00 +0000 Subject: [PATCH 4/9] Add helper script and improve documentation Co-authored-by: ruslanbaidan <3246171+ruslanbaidan@users.noreply.github.com> --- README.docker.md | 126 ++++++++++++++++++++++++++++++++++++----------- docker-dev.sh | 122 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 28 deletions(-) create mode 100755 docker-dev.sh diff --git a/README.docker.md b/README.docker.md index efc4a76..95cab6d 100644 --- a/README.docker.md +++ b/README.docker.md @@ -11,6 +11,43 @@ This guide explains how to set up a local development environment for MONARC Fro ## Quick Start +### Option 1: Using the Helper Script (Recommended) + +1. **Clone the repository** (if you haven't already): + ```bash + git clone https://github.com/monarc-project/MonarcAppFO + cd MonarcAppFO + ``` + +2. **Start the development environment**: + ```bash + ./docker-dev.sh start + ``` + + This will automatically: + - Create `.env` file from `.env.dev` if it doesn't exist + - Build and start all services + - Display access URLs + + The first run will take several minutes as it: + - Builds the Docker images + - Installs all dependencies (PHP, Node.js, Python) + - Clones frontend repositories + - Initializes databases + - Sets up the stats service + - Creates the initial admin user + +3. **Access the application**: + - MONARC FrontOffice: http://localhost:5001 + - Stats Service: http://localhost:5005 + - MailCatcher (email testing): http://localhost:1080 + +4. **Login credentials**: + - Username: `admin@admin.localhost` + - Password: `admin` + +### Option 2: Using Docker Compose Directly + 1. **Clone the repository** (if you haven't already): ```bash git clone https://github.com/monarc-project/MonarcAppFO @@ -35,14 +72,6 @@ This guide explains how to set up a local development environment for MONARC Fro docker-compose -f docker-compose.dev.yml up --build ``` - The first run will take several minutes as it: - - Builds the Docker images - - Installs all dependencies (PHP, Node.js, Python) - - Clones frontend repositories - - Initializes databases - - Sets up the stats service - - Creates the initial admin user - 5. **Access the application**: - MONARC FrontOffice: http://localhost:5001 - Stats Service: http://localhost:5005 @@ -51,7 +80,10 @@ This guide explains how to set up a local development environment for MONARC Fro 6. **(Optional) Configure Stats API Key**: The stats service generates an API key on first run. To retrieve it: ```bash - # Check the stats service logs for the API key + # Using helper script + ./docker-dev.sh stats-key + + # Or manually check logs docker-compose -f docker-compose.dev.yml logs stats-service | grep "Token:" # Or create a new client and get the key @@ -79,6 +111,25 @@ The development environment includes the following services: ## Development Workflow +### Helper Script Commands + +The `docker-dev.sh` script provides convenient commands for managing the development environment: + +```bash +./docker-dev.sh start # Start all services +./docker-dev.sh stop # Stop all services +./docker-dev.sh restart # Restart all services +./docker-dev.sh logs # View logs from all services +./docker-dev.sh logs-app # View logs from MONARC application +./docker-dev.sh logs-stats # View logs from stats service +./docker-dev.sh shell # Open a shell in the MONARC container +./docker-dev.sh shell-stats # Open a shell in the stats service container +./docker-dev.sh db # Open MySQL client +./docker-dev.sh status # Show status of all services +./docker-dev.sh stats-key # Show the stats API key +./docker-dev.sh reset # Reset everything (removes all data) +``` + ### Live Code Editing The application source code is mounted as a volume, so changes you make on your host machine will be immediately reflected in the container. After making changes: @@ -93,67 +144,86 @@ The application source code is mounted as a volume, so changes you make on your ### Accessing the Container -To access the MONARC application container: +Using helper script: ```bash -docker exec -it monarc-fo-app bash +./docker-dev.sh shell # MONARC application +./docker-dev.sh shell-stats # Stats service ``` -To access the stats service container: +Or directly with docker: ```bash -docker exec -it monarc-fo-stats bash +docker exec -it monarc-fo-app bash # MONARC application +docker exec -it monarc-fo-stats bash # Stats service ``` ### Database Access -Connect to MariaDB: +Using helper script: ```bash -docker exec -it monarc-fo-db mysql -usqlmonarcuser -psqlmonarcuser monarc_common +./docker-dev.sh db # Connect to MariaDB ``` -Connect to PostgreSQL: +Or directly with docker: ```bash +# Connect to MariaDB +docker exec -it monarc-fo-db mysql -usqlmonarcuser -psqlmonarcuser monarc_common + +# Connect to PostgreSQL docker exec -it monarc-fo-postgres psql -U sqlmonarcuser -d statsservice ``` ### Viewing Logs -View logs for all services: +Using helper script: ```bash -docker-compose -f docker-compose.dev.yml logs -f +./docker-dev.sh logs # All services +./docker-dev.sh logs-app # MONARC application only +./docker-dev.sh logs-stats # Stats service only ``` -View logs for a specific service: +Or directly with docker compose: ```bash +# View logs for all services +docker-compose -f docker-compose.dev.yml logs -f + +# View logs for a specific service docker-compose -f docker-compose.dev.yml logs -f monarc docker-compose -f docker-compose.dev.yml logs -f stats-service ``` ### Restarting Services -Restart all services: +Using helper script: ```bash -docker-compose -f docker-compose.dev.yml restart +./docker-dev.sh restart # Restart all services ``` -Restart a specific service: +Or directly with docker compose: ```bash +# Restart all services +docker-compose -f docker-compose.dev.yml restart + +# Restart a specific service docker-compose -f docker-compose.dev.yml restart monarc ``` ### Stopping the Environment -Stop all services (keeps data): +Using helper script: ```bash -docker-compose -f docker-compose.dev.yml stop +./docker-dev.sh stop # Stop all services (keeps data) +./docker-dev.sh reset # Stop and remove everything including data ``` -Stop and remove containers (keeps volumes/data): +Or directly with docker compose: ```bash +# Stop all services (keeps data) +docker-compose -f docker-compose.dev.yml stop + +# Stop and remove containers (keeps volumes/data) docker-compose -f docker-compose.dev.yml down -``` -Stop and remove everything including data: -```bash +# Stop and remove everything including data docker-compose -f docker-compose.dev.yml down -v ``` diff --git a/docker-dev.sh b/docker-dev.sh new file mode 100755 index 0000000..42f21f5 --- /dev/null +++ b/docker-dev.sh @@ -0,0 +1,122 @@ +#!/bin/bash +# Helper script for managing MONARC Docker development environment + +set -e + +COMPOSE_FILE="docker-compose.dev.yml" + +# Colors for output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +usage() { + echo -e "${GREEN}MONARC Docker Development Environment Manager${NC}" + echo "" + echo "Usage: $0 [command]" + echo "" + echo "Commands:" + echo " start Start all services (builds on first run)" + echo " stop Stop all services" + echo " restart Restart all services" + echo " logs View logs from all services" + echo " logs-app View logs from MONARC application" + echo " logs-stats View logs from stats service" + echo " shell Open a shell in the MONARC container" + echo " shell-stats Open a shell in the stats service container" + echo " db Open MySQL client in the database" + echo " reset Reset everything (removes all data)" + echo " status Show status of all services" + echo " stats-key Show the stats API key" + echo "" +} + +check_env() { + if [ ! -f .env ]; then + echo -e "${YELLOW}No .env file found. Creating from .env.dev...${NC}" + cp .env.dev .env + echo -e "${GREEN}.env file created. You can edit it to customize configuration.${NC}" + fi +} + +case "$1" in + start) + check_env + echo -e "${GREEN}Starting MONARC development environment...${NC}" + docker compose -f $COMPOSE_FILE up -d --build + echo -e "${GREEN}Services started!${NC}" + echo -e "MONARC FrontOffice: http://localhost:5001" + echo -e "Stats Service: http://localhost:5005" + echo -e "MailCatcher: http://localhost:1080" + echo -e "\n${YELLOW}To view logs: $0 logs${NC}" + ;; + + stop) + echo -e "${YELLOW}Stopping all services...${NC}" + docker compose -f $COMPOSE_FILE stop + echo -e "${GREEN}Services stopped.${NC}" + ;; + + restart) + echo -e "${YELLOW}Restarting all services...${NC}" + docker compose -f $COMPOSE_FILE restart + echo -e "${GREEN}Services restarted.${NC}" + ;; + + logs) + docker compose -f $COMPOSE_FILE logs -f + ;; + + logs-app) + docker compose -f $COMPOSE_FILE logs -f monarc + ;; + + logs-stats) + docker compose -f $COMPOSE_FILE logs -f stats-service + ;; + + shell) + echo -e "${GREEN}Opening shell in MONARC container...${NC}" + docker exec -it monarc-fo-app bash + ;; + + shell-stats) + echo -e "${GREEN}Opening shell in stats service container...${NC}" + docker exec -it monarc-fo-stats bash + ;; + + db) + echo -e "${GREEN}Opening MySQL client...${NC}" + docker exec -it monarc-fo-db mysql -usqlmonarcuser -psqlmonarcuser monarc_common + ;; + + reset) + echo -e "${RED}WARNING: This will remove all data!${NC}" + read -p "Are you sure? (yes/no): " confirm + if [ "$confirm" = "yes" ]; then + echo -e "${YELLOW}Stopping and removing all containers, volumes, and data...${NC}" + docker compose -f $COMPOSE_FILE down -v + echo -e "${GREEN}Reset complete. Run '$0 start' to start fresh.${NC}" + else + echo -e "${GREEN}Reset cancelled.${NC}" + fi + ;; + + status) + docker compose -f $COMPOSE_FILE ps + ;; + + stats-key) + echo -e "${GREEN}Retrieving stats API key...${NC}" + docker compose -f $COMPOSE_FILE logs stats-service | grep "Token:" | tail -1 + echo -e "\n${YELLOW}Note: Update this key in your .env file and restart MONARC service:${NC}" + echo -e " 1. Edit .env and set STATS_API_KEY=" + echo -e " 2. Run: docker compose -f $COMPOSE_FILE restart monarc" + ;; + + *) + usage + exit 1 + ;; +esac From e6bd605f6b7467349bee2a50c35bba414a561485 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:29:13 +0000 Subject: [PATCH 5/9] Update main README and add Docker installation guide Co-authored-by: ruslanbaidan <3246171+ruslanbaidan@users.noreply.github.com> --- INSTALL/INSTALL.docker.md | 186 ++++++++++++++++++++++++++++++++++++++ README.md | 16 ++++ 2 files changed, 202 insertions(+) create mode 100644 INSTALL/INSTALL.docker.md diff --git a/INSTALL/INSTALL.docker.md b/INSTALL/INSTALL.docker.md new file mode 100644 index 0000000..7c9bddc --- /dev/null +++ b/INSTALL/INSTALL.docker.md @@ -0,0 +1,186 @@ +# Docker Installation Guide for MONARC FrontOffice + +This document provides installation instructions for setting up MONARC FrontOffice using Docker for development purposes. + +## Quick Installation + +```bash +# Clone the repository +git clone https://github.com/monarc-project/MonarcAppFO +cd MonarcAppFO + +# Start with the helper script (recommended) +./docker-dev.sh start + +# Or use docker-compose directly +cp .env.dev .env +docker compose -f docker-compose.dev.yml up -d --build +``` + +## What Gets Installed + +The Docker setup includes: + +1. **MONARC FrontOffice Application** + - Ubuntu 22.04 base + - PHP 8.1 with all required extensions + - Apache web server + - Composer for PHP dependencies + - Node.js for frontend + - All MONARC modules and dependencies + +2. **MariaDB 10.11** + - Database for MONARC application data + - Pre-configured with proper character sets + +3. **PostgreSQL 15** + - Database for the statistics service + +4. **Stats Service** + - Python/Flask application + - Poetry for dependency management + - Integrated with MONARC FrontOffice + +5. **MailCatcher** + - Email testing interface + - SMTP server for development + +## First Time Setup + +When you start the environment for the first time: + +1. Docker images will be built (5-10 minutes) +2. Dependencies will be installed automatically +3. Databases will be created and initialized +4. Frontend repositories will be cloned and built +5. Initial admin user will be created + +## Access URLs + +After startup, access the application at: + +- **MONARC FrontOffice**: http://localhost:5001 +- **Stats Service**: http://localhost:5005 +- **MailCatcher**: http://localhost:1080 + +## Default Credentials + +- **Username**: admin@admin.localhost +- **Password**: admin + +⚠️ **Security Warning**: Change these credentials before deploying to production! + +## System Requirements + +- Docker Engine 20.10 or later +- Docker Compose V2 +- At least 8GB RAM available for Docker +- At least 20GB free disk space +- Linux, macOS, or Windows with WSL2 + +## Configuration + +Environment variables are defined in the `.env` file (copied from `.env.dev`): + +- Database credentials +- Service ports +- Secret keys + +You can customize these before starting the environment. + +## Troubleshooting + +### Port Conflicts + +If ports 5001, 5005, 3306, 5432, or 1080 are already in use: + +1. Edit `docker-compose.dev.yml` +2. Change the host port (left side of the port mapping) +3. Example: Change `"5001:80"` to `"8001:80"` + +### Permission Issues + +If you encounter permission errors: + +```bash +docker exec -it monarc-fo-app bash +chown -R www-data:www-data /var/www/html/monarc/data +chmod -R 775 /var/www/html/monarc/data +``` + +### Service Not Starting + +Check the logs: + +```bash +./docker-dev.sh logs +# or +docker compose -f docker-compose.dev.yml logs +``` + +### Reset Everything + +To start completely fresh: + +```bash +./docker-dev.sh reset +# or +docker compose -f docker-compose.dev.yml down -v +``` + +## Common Tasks + +### View Logs +```bash +./docker-dev.sh logs +``` + +### Access Container Shell +```bash +./docker-dev.sh shell +``` + +### Access Database +```bash +./docker-dev.sh db +``` + +### Stop Services +```bash +./docker-dev.sh stop +``` + +### Restart Services +```bash +./docker-dev.sh restart +``` + +## Comparison with Other Installation Methods + +| Method | Complexity | Time | Best For | +|--------|-----------|------|----------| +| Docker | Low | Fast (2-5 min startup) | Development | +| Vagrant | Medium | Slow (10-15 min startup) | Development | +| Manual | High | Slow (30+ min) | Production | +| VM | Low | Medium | Testing | + +## Next Steps + +After installation: + +1. Read the [full Docker documentation](README.docker.md) +2. Review the [MONARC documentation](https://www.monarc.lu/documentation) +3. Configure the stats API key (optional) +4. Start developing! + +## Getting Help + +- **Documentation**: [README.docker.md](README.docker.md) +- **MONARC Website**: https://www.monarc.lu +- **GitHub Issues**: https://github.com/monarc-project/MonarcAppFO/issues +- **Community**: https://www.monarc.lu/community + +## License + +This project is licensed under the GNU Affero General Public License version 3. +See [LICENSE](LICENSE) for details. diff --git a/README.md b/README.md index 21a8a85..ffdbdf6 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,22 @@ For installation instructions see You can also use the provided [Virtual Machine](https://vm.monarc.lu). +Development Environment +----------------------- + +For local development, you can use either: + +- **Docker** (recommended): See [README.docker.md](README.docker.md) for instructions + ```bash + ./docker-dev.sh start + ``` + +- **Vagrant**: See [vagrant/README.rst](vagrant/README.rst) for instructions + ```bash + cd vagrant && vagrant up + ``` + + Contributing ------------ From 27b38321d190139644cfb963083b0b27466b4bff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:31:29 +0000 Subject: [PATCH 6/9] Address code review feedback - fix Poetry flag, quoting, and unused file Co-authored-by: ruslanbaidan <3246171+ruslanbaidan@users.noreply.github.com> --- docker-dev.sh | 20 ++++++++++---------- docker-entrypoint.sh | 2 +- docker-stats-entrypoint.sh | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docker-dev.sh b/docker-dev.sh index 42f21f5..c55b340 100755 --- a/docker-dev.sh +++ b/docker-dev.sh @@ -44,7 +44,7 @@ case "$1" in start) check_env echo -e "${GREEN}Starting MONARC development environment...${NC}" - docker compose -f $COMPOSE_FILE up -d --build + docker compose -f "$COMPOSE_FILE" up -d --build echo -e "${GREEN}Services started!${NC}" echo -e "MONARC FrontOffice: http://localhost:5001" echo -e "Stats Service: http://localhost:5005" @@ -54,26 +54,26 @@ case "$1" in stop) echo -e "${YELLOW}Stopping all services...${NC}" - docker compose -f $COMPOSE_FILE stop + docker compose -f "$COMPOSE_FILE" stop echo -e "${GREEN}Services stopped.${NC}" ;; restart) echo -e "${YELLOW}Restarting all services...${NC}" - docker compose -f $COMPOSE_FILE restart + docker compose -f "$COMPOSE_FILE" restart echo -e "${GREEN}Services restarted.${NC}" ;; logs) - docker compose -f $COMPOSE_FILE logs -f + docker compose -f "$COMPOSE_FILE" logs -f ;; logs-app) - docker compose -f $COMPOSE_FILE logs -f monarc + docker compose -f "$COMPOSE_FILE" logs -f monarc ;; logs-stats) - docker compose -f $COMPOSE_FILE logs -f stats-service + docker compose -f "$COMPOSE_FILE" logs -f stats-service ;; shell) @@ -96,7 +96,7 @@ case "$1" in read -p "Are you sure? (yes/no): " confirm if [ "$confirm" = "yes" ]; then echo -e "${YELLOW}Stopping and removing all containers, volumes, and data...${NC}" - docker compose -f $COMPOSE_FILE down -v + docker compose -f "$COMPOSE_FILE" down -v echo -e "${GREEN}Reset complete. Run '$0 start' to start fresh.${NC}" else echo -e "${GREEN}Reset cancelled.${NC}" @@ -104,15 +104,15 @@ case "$1" in ;; status) - docker compose -f $COMPOSE_FILE ps + docker compose -f "$COMPOSE_FILE" ps ;; stats-key) echo -e "${GREEN}Retrieving stats API key...${NC}" - docker compose -f $COMPOSE_FILE logs stats-service | grep "Token:" | tail -1 + docker compose -f "$COMPOSE_FILE" logs stats-service | grep "Token:" | tail -1 echo -e "\n${YELLOW}Note: Update this key in your .env file and restart MONARC service:${NC}" echo -e " 1. Edit .env and set STATS_API_KEY=" - echo -e " 2. Run: docker compose -f $COMPOSE_FILE restart monarc" + echo -e " 2. Run: docker compose -f \"\$COMPOSE_FILE\" restart monarc" ;; *) diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 2c836c2..b914616 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -125,7 +125,7 @@ return [ ], 'import' => [ - 'uploadFolder' => '\$appdir/data/import/files', + 'uploadFolder' => '$appdir/data/import/files', 'isBackgroundProcessActive' => false, ], ]; diff --git a/docker-stats-entrypoint.sh b/docker-stats-entrypoint.sh index cd6cb12..7127751 100755 --- a/docker-stats-entrypoint.sh +++ b/docker-stats-entrypoint.sh @@ -36,7 +36,7 @@ if [ ! -f "/var/www/stats-service/.docker-initialized" ]; then # Install Python dependencies with Poetry echo -e "${YELLOW}Installing Python dependencies with Poetry...${NC}" - poetry install --no-dev + poetry install --only=main # Create instance directory and configuration echo -e "${YELLOW}Creating configuration...${NC}" @@ -83,7 +83,7 @@ EOF # Create client for MONARC and capture the API key echo -e "${YELLOW}Creating MONARC client...${NC}" - poetry run flask client_create --name admin_localhost | tee /tmp/client_output.txt + poetry run flask client_create --name admin_localhost # Mark initialization as complete touch /var/www/stats-service/.docker-initialized From 1126e90c84af153ac6a873b74c5fe0b5dbfdf76b Mon Sep 17 00:00:00 2001 From: Ruslan Baidan Date: Fri, 16 Jan 2026 19:48:43 +0100 Subject: [PATCH 7/9] Fixed the docker run and made it possible to use the BackOffice common DB. --- .env.dev | 20 +++++ .gitignore | 2 + Dockerfile | 66 +++++++------- INSTALL/INSTALL.docker.md | 24 ++--- Makefile | 104 ++++++++++++++++++++++ README.docker.md | 151 ++++++++++++++++++++------------ README.md | 2 +- docker-compose.dev.yml | 118 ++++++++++++++----------- docker-dev.sh | 122 -------------------------- docker-entrypoint.sh | 103 ++++++++++++++-------- docker/db-init/10-dev-grants.sh | 12 +++ 11 files changed, 413 insertions(+), 311 deletions(-) create mode 100644 Makefile delete mode 100755 docker-dev.sh create mode 100644 docker/db-init/10-dev-grants.sh diff --git a/.env.dev b/.env.dev index 049c9ba..1981b09 100644 --- a/.env.dev +++ b/.env.dev @@ -1,9 +1,29 @@ # MariaDB Configuration +DBHOST=fodb +DBPORT_HOST=3307 DBPASSWORD_ADMIN=root DBNAME_COMMON=monarc_common DBNAME_CLI=monarc_cli DBUSER_MONARC=sqlmonarcuser DBPASSWORD_MONARC=sqlmonarcuser +# Set USE_BO_COMMON=1 and DBHOST to the BackOffice DB host to reuse monarc_common. +USE_BO_COMMON=1 + +# Shared Docker network name (must exist when using external network) +MONARC_NETWORK_NAME=monarc-network + +# Node.js major version for frontend build tooling +NODE_MAJOR=16 + +# Optional: set to 0/false/no to disable Xdebug in the image build +XDEBUG_ENABLED=1 +XDEBUG_MODE=debug +XDEBUG_START_WITH_REQUEST=trigger +# On Linux, set XDEBUG_CLIENT_HOST to your Docker bridge (often 172.17.0.1). +XDEBUG_CLIENT_HOST=host.docker.internal +XDEBUG_CLIENT_PORT=9003 +XDEBUG_IDEKEY=IDEKEY +XDEBUG_DISCOVER_CLIENT_HOST=0 # Stats Service Configuration STATS_HOST=0.0.0.0 diff --git a/.gitignore b/.gitignore index c2db730..606ef8d 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ data/* .docker/mariaDb/data/* .env .docker-initialized +docker/db_data +.vscode diff --git a/Dockerfile b/Dockerfile index ad70470..27e423b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,14 @@ FROM ubuntu:22.04 +ARG XDEBUG_ENABLED=1 +ARG XDEBUG_MODE=debug +ARG XDEBUG_START_WITH_REQUEST=trigger +ARG XDEBUG_CLIENT_HOST=host.docker.internal +ARG XDEBUG_CLIENT_PORT=9003 +ARG XDEBUG_IDEKEY=IDEKEY +ARG XDEBUG_DISCOVER_CLIENT_HOST=0 +ARG NODE_MAJOR=16 + # Prevent interactive prompts during package installation ENV DEBIAN_FRONTEND=noninteractive ENV LANGUAGE=en_US.UTF-8 @@ -8,33 +17,15 @@ ENV LC_ALL=en_US.UTF-8 # Install system dependencies RUN apt-get update && apt-get upgrade -y && \ - apt-get install -y \ - vim \ - zip \ - unzip \ - git \ - gettext \ - curl \ - gsfonts \ - mariadb-client \ - apache2 \ - php8.1 \ - php8.1-cli \ - php8.1-common \ - php8.1-mysql \ - php8.1-zip \ - php8.1-gd \ - php8.1-mbstring \ - php8.1-curl \ - php8.1-xml \ - php8.1-bcmath \ - php8.1-intl \ - php8.1-imagick \ - php8.1-xdebug \ - locales \ - wget \ - ca-certificates \ - gnupg && \ + packages="vim zip unzip git gettext curl gsfonts mariadb-client apache2 php8.1 php8.1-cli \ + php8.1-common php8.1-mysql php8.1-zip php8.1-gd php8.1-mbstring php8.1-curl php8.1-xml \ + php8.1-bcmath php8.1-intl php8.1-imagick locales wget ca-certificates gnupg \ + build-essential python3 pkg-config libcairo2-dev libpango1.0-dev libjpeg-dev \ + libgif-dev librsvg2-dev libpixman-1-dev"; \ + if [ "$XDEBUG_ENABLED" = "1" ] || [ "$XDEBUG_ENABLED" = "true" ] || [ "$XDEBUG_ENABLED" = "yes" ]; then \ + packages="$packages php8.1-xdebug"; \ + fi; \ + apt-get install -y $packages && \ locale-gen en_US.UTF-8 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -50,23 +41,32 @@ RUN sed -i 's/upload_max_filesize = .*/upload_max_filesize = 200M/' /etc/php/8.1 sed -i 's/session\.gc_divisor = .*/session.gc_divisor = 1000/' /etc/php/8.1/apache2/php.ini # Configure Xdebug for development -RUN echo "zend_extension=xdebug.so" > /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ - echo "xdebug.mode=debug" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ - echo "xdebug.discover_client_host=1" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ - echo "xdebug.idekey=IDEKEY" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini +RUN if [ "$XDEBUG_ENABLED" = "1" ] || [ "$XDEBUG_ENABLED" = "true" ] || [ "$XDEBUG_ENABLED" = "yes" ]; then \ + echo "zend_extension=xdebug.so" > /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.mode=${XDEBUG_MODE}" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.start_with_request=${XDEBUG_START_WITH_REQUEST}" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.client_host=${XDEBUG_CLIENT_HOST}" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.client_port=${XDEBUG_CLIENT_PORT}" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.discover_client_host=${XDEBUG_DISCOVER_CLIENT_HOST}" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini && \ + echo "xdebug.idekey=${XDEBUG_IDEKEY}" >> /etc/php/8.1/apache2/conf.d/20-xdebug.ini; \ + fi # Enable Apache modules RUN a2enmod rewrite ssl headers +# Set global ServerName to avoid AH00558 warning +RUN echo "ServerName localhost" > /etc/apache2/conf-available/servername.conf \ + && a2enconf servername + # Install Composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Install Node.js and npm RUN mkdir -p /etc/apt/keyrings && \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_15.x nodistro main" > /etc/apt/sources.list.d/nodesource.list && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" > /etc/apt/sources.list.d/nodesource.list && \ apt-get update && \ - apt-get install -y nodejs npm && \ + apt-get install -y nodejs && \ npm install -g grunt-cli && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/INSTALL/INSTALL.docker.md b/INSTALL/INSTALL.docker.md index 7c9bddc..365bcd1 100644 --- a/INSTALL/INSTALL.docker.md +++ b/INSTALL/INSTALL.docker.md @@ -9,10 +9,10 @@ This document provides installation instructions for setting up MONARC FrontOffi git clone https://github.com/monarc-project/MonarcAppFO cd MonarcAppFO -# Start with the helper script (recommended) -./docker-dev.sh start +# Start with the Makefile (recommended) +make start -# Or use docker-compose directly +# Or use docker compose directly cp .env.dev .env docker compose -f docker-compose.dev.yml up -d --build ``` @@ -92,12 +92,14 @@ You can customize these before starting the environment. ### Port Conflicts -If ports 5001, 5005, 3306, 5432, or 1080 are already in use: +If ports 5001, 5005, 3307, 5432, or 1080 are already in use: 1. Edit `docker-compose.dev.yml` 2. Change the host port (left side of the port mapping) 3. Example: Change `"5001:80"` to `"8001:80"` +You can also change the MariaDB host port by setting `DBPORT_HOST` in `.env`. + ### Permission Issues If you encounter permission errors: @@ -113,7 +115,7 @@ chmod -R 775 /var/www/html/monarc/data Check the logs: ```bash -./docker-dev.sh logs +make logs # or docker compose -f docker-compose.dev.yml logs ``` @@ -123,7 +125,7 @@ docker compose -f docker-compose.dev.yml logs To start completely fresh: ```bash -./docker-dev.sh reset +make reset # or docker compose -f docker-compose.dev.yml down -v ``` @@ -132,27 +134,27 @@ docker compose -f docker-compose.dev.yml down -v ### View Logs ```bash -./docker-dev.sh logs +make logs ``` ### Access Container Shell ```bash -./docker-dev.sh shell +make shell ``` ### Access Database ```bash -./docker-dev.sh db +make db ``` ### Stop Services ```bash -./docker-dev.sh stop +make stop ``` ### Restart Services ```bash -./docker-dev.sh restart +make restart ``` ## Comparison with Other Installation Methods diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..551882a --- /dev/null +++ b/Makefile @@ -0,0 +1,104 @@ +.DEFAULT_GOAL := help + +SHELL := /bin/bash + +ENV ?= dev +COMPOSE_FILE ?= docker-compose.$(ENV).yml +COMPOSE := docker compose -f $(COMPOSE_FILE) + +GREEN := \033[0;32m +YELLOW := \033[1;33m +RED := \033[0;31m +NC := \033[0m + +.PHONY: help check-env start stop restart logs logs-app logs-stats shell shell-stats db reset status stats-key + +help: + @printf "%b\n" "$(GREEN)MONARC FrontOffice Docker Development Environment Manager$(NC)" + @printf "\n%b\n" "Usage: make " + @printf "%b\n" "Environment: ENV= (default: dev, uses docker-compose..yml)" + @printf "\n%b\n" "Commands:" + @printf " %-12s %s\n" "start" "Start all services (builds on first run)" + @printf " %-12s %s\n" "stop" "Stop all services" + @printf " %-12s %s\n" "restart" "Restart all services" + @printf " %-12s %s\n" "logs" "View logs from all services" + @printf " %-12s %s\n" "logs-app" "View logs from MONARC application" + @printf " %-12s %s\n" "logs-stats" "View logs from stats service" + @printf " %-12s %s\n" "shell" "Open a shell in the MONARC container" + @printf " %-12s %s\n" "shell-stats" "Open a shell in the stats service container" + @printf " %-12s %s\n" "db" "Open MySQL client in the database" + @printf " %-12s %s\n" "stats-key" "Show the stats API key" + @printf " %-12s %s\n" "reset" "Reset everything (removes all data)" + @printf " %-12s %s\n" "status" "Show status of all services" + +check-env: + @if [ ! -f .env ]; then \ + printf "%b\n" "$(YELLOW)No .env file found. Creating from .env.dev...$(NC)"; \ + cp .env.dev .env; \ + printf "%b\n" "$(GREEN).env file created. You can edit it to customize configuration.$(NC)"; \ + fi + +start: check-env + @printf "%b\n" "$(GREEN)Starting MONARC FrontOffice development environment...$(NC)" + @$(COMPOSE) up -d --build + @printf "%b\n" "$(GREEN)Services started!$(NC)" + @printf "%b\n" "MONARC FrontOffice: http://localhost:5001" + @printf "%b\n" "Stats Service: http://localhost:5005" + @printf "%b\n" "MailCatcher: http://localhost:1080" + @printf "\n%b\n" "$(YELLOW)To view logs: make logs ENV=$(ENV)$(NC)" + +stop: + @printf "%b\n" "$(YELLOW)Stopping all services...$(NC)" + @$(COMPOSE) stop + @printf "%b\n" "$(GREEN)Services stopped.$(NC)" + +restart: + @printf "%b\n" "$(YELLOW)Restarting all services...$(NC)" + @$(COMPOSE) restart + @printf "%b\n" "$(GREEN)Services restarted.$(NC)" + +logs: + @$(COMPOSE) logs -f + +logs-app: + @$(COMPOSE) logs -f monarc + +logs-stats: + @$(COMPOSE) logs -f stats-service + +shell: + @printf "%b\n" "$(GREEN)Opening shell in MONARC container...$(NC)" + @docker exec -it monarc-fo-app bash + +shell-stats: + @printf "%b\n" "$(GREEN)Opening shell in stats service container...$(NC)" + @docker exec -it monarc-fo-stats bash + +db: + @printf "%b\n" "$(GREEN)Opening MySQL client...$(NC)" + @if [ -f .env ]; then \ + export $$(grep -v '^#' .env | xargs); \ + fi; \ + export MYSQL_PWD="$${DBPASSWORD_MONARC:-sqlmonarcuser}"; \ + docker exec -it monarc-fo-db mysql -u"$${DBUSER_MONARC:-sqlmonarcuser}" "$${DBNAME_COMMON:-monarc_common}" + +stats-key: + @printf "%b\n" "$(GREEN)Retrieving stats API key...$(NC)" + @$(COMPOSE) logs stats-service | grep "Token:" | tail -1 + @printf "\n%b\n" "$(YELLOW)Note: Update this key in your .env file and restart MONARC service:$(NC)" + @printf "%b\n" " 1. Edit .env and set STATS_API_KEY=" + @printf "%b\n" " 2. Run: docker compose -f \"$(COMPOSE_FILE)\" restart monarc" + +reset: + @printf "%b\n" "$(RED)WARNING: This will remove all data!$(NC)"; \ + read -p "Are you sure? (yes/no): " confirm; \ + if [ "$$confirm" = "yes" ]; then \ + printf "%b\n" "$(YELLOW)Stopping and removing all containers, volumes, and data...$(NC)"; \ + $(COMPOSE) down -v; \ + printf "%b\n" "$(GREEN)Reset complete. Run 'make start' to start fresh.$(NC)"; \ + else \ + printf "%b\n" "$(GREEN)Reset cancelled.$(NC)"; \ + fi + +status: + @$(COMPOSE) ps diff --git a/README.docker.md b/README.docker.md index 95cab6d..1c5ceac 100644 --- a/README.docker.md +++ b/README.docker.md @@ -11,7 +11,7 @@ This guide explains how to set up a local development environment for MONARC Fro ## Quick Start -### Option 1: Using the Helper Script (Recommended) +### Option 1: Using the Makefile (Recommended) 1. **Clone the repository** (if you haven't already): ```bash @@ -21,7 +21,7 @@ This guide explains how to set up a local development environment for MONARC Fro 2. **Start the development environment**: ```bash - ./docker-dev.sh start + make start ``` This will automatically: @@ -69,7 +69,7 @@ This guide explains how to set up a local development environment for MONARC Fro 4. **Start the development environment**: ```bash - docker-compose -f docker-compose.dev.yml up --build + docker compose -f docker-compose.dev.yml up --build ``` 5. **Access the application**: @@ -80,17 +80,17 @@ This guide explains how to set up a local development environment for MONARC Fro 6. **(Optional) Configure Stats API Key**: The stats service generates an API key on first run. To retrieve it: ```bash - # Using helper script - ./docker-dev.sh stats-key + # Using Makefile + make stats-key # Or manually check logs - docker-compose -f docker-compose.dev.yml logs stats-service | grep "Token:" + docker compose -f docker-compose.dev.yml logs stats-service | grep "Token:" # Or create a new client and get the key docker exec -it monarc-fo-stats poetry run flask client_create --name monarc # Update the .env file with the API key and restart the monarc service - docker-compose -f docker-compose.dev.yml restart monarc + docker compose -f docker-compose.dev.yml restart monarc ``` 7. **Login credentials**: @@ -104,30 +104,31 @@ The development environment includes the following services: | Service | Description | Port | Container Name | |---------|-------------|------|----------------| | monarc | Main FrontOffice application (PHP/Apache) | 5001 | monarc-fo-app | -| db | MariaDB database | 3306 | monarc-fo-db | +| db | MariaDB database | 3307 | monarc-fo-db | | postgres | PostgreSQL database (for stats) | 5432 | monarc-fo-postgres | | stats-service | MONARC Statistics Service | 5005 | monarc-fo-stats | | mailcatcher | Email testing tool | 1080 (web), 1025 (SMTP) | monarc-fo-mailcatcher | ## Development Workflow -### Helper Script Commands +### Makefile Commands -The `docker-dev.sh` script provides convenient commands for managing the development environment: +The Makefile provides convenient commands for managing the development environment. +Use `ENV=` to select `docker compose..yml` (default: `dev`). ```bash -./docker-dev.sh start # Start all services -./docker-dev.sh stop # Stop all services -./docker-dev.sh restart # Restart all services -./docker-dev.sh logs # View logs from all services -./docker-dev.sh logs-app # View logs from MONARC application -./docker-dev.sh logs-stats # View logs from stats service -./docker-dev.sh shell # Open a shell in the MONARC container -./docker-dev.sh shell-stats # Open a shell in the stats service container -./docker-dev.sh db # Open MySQL client -./docker-dev.sh status # Show status of all services -./docker-dev.sh stats-key # Show the stats API key -./docker-dev.sh reset # Reset everything (removes all data) +make start # Start all services +make stop # Stop all services +make restart # Restart all services +make logs # View logs from all services +make logs-app # View logs from MONARC application +make logs-stats # View logs from stats service +make shell # Open a shell in the MONARC container +make shell-stats # Open a shell in the stats service container +make db # Open MySQL client +make status # Show status of all services +make stats-key # Show the stats API key +make reset # Reset everything (removes all data) ``` ### Live Code Editing @@ -144,10 +145,10 @@ The application source code is mounted as a volume, so changes you make on your ### Accessing the Container -Using helper script: +Using Makefile: ```bash -./docker-dev.sh shell # MONARC application -./docker-dev.sh shell-stats # Stats service +make shell # MONARC application +make shell-stats # Stats service ``` Or directly with docker: @@ -158,9 +159,9 @@ docker exec -it monarc-fo-stats bash # Stats service ### Database Access -Using helper script: +Using Makefile: ```bash -./docker-dev.sh db # Connect to MariaDB +make db # Connect to MariaDB ``` Or directly with docker: @@ -174,67 +175,83 @@ docker exec -it monarc-fo-postgres psql -U sqlmonarcuser -d statsservice ### Viewing Logs -Using helper script: +Using Makefile: ```bash -./docker-dev.sh logs # All services -./docker-dev.sh logs-app # MONARC application only -./docker-dev.sh logs-stats # Stats service only +make logs # All services +make logs-app # MONARC application only +make logs-stats # Stats service only ``` Or directly with docker compose: ```bash # View logs for all services -docker-compose -f docker-compose.dev.yml logs -f +docker compose -f docker-compose.dev.yml logs -f # View logs for a specific service -docker-compose -f docker-compose.dev.yml logs -f monarc -docker-compose -f docker-compose.dev.yml logs -f stats-service +docker compose -f docker-compose.dev.yml logs -f monarc +docker compose -f docker-compose.dev.yml logs -f stats-service ``` ### Restarting Services -Using helper script: +Using Makefile: ```bash -./docker-dev.sh restart # Restart all services +make restart # Restart all services ``` Or directly with docker compose: ```bash # Restart all services -docker-compose -f docker-compose.dev.yml restart +docker compose -f docker-compose.dev.yml restart # Restart a specific service -docker-compose -f docker-compose.dev.yml restart monarc +docker compose -f docker-compose.dev.yml restart monarc ``` ### Stopping the Environment -Using helper script: +Using Makefile: ```bash -./docker-dev.sh stop # Stop all services (keeps data) -./docker-dev.sh reset # Stop and remove everything including data +make stop # Stop all services (keeps data) +make reset # Stop and remove everything including data ``` Or directly with docker compose: ```bash # Stop all services (keeps data) -docker-compose -f docker-compose.dev.yml stop +docker compose -f docker-compose.dev.yml stop # Stop and remove containers (keeps volumes/data) -docker-compose -f docker-compose.dev.yml down +docker compose -f docker-compose.dev.yml down # Stop and remove everything including data -docker-compose -f docker-compose.dev.yml down -v +docker compose -f docker-compose.dev.yml down -v ``` ## Common Tasks +### Using BackOffice monarc_common + +To reuse the BackOffice `monarc_common` database: + +1. Set `USE_BO_COMMON=1` in `.env`. +2. Point `DBHOST` to the BackOffice MariaDB host (for example, `monarc-bo-db` on a shared Docker network). +3. Ensure the BackOffice database already has `monarc_common` and grants for `DBUSER_MONARC`. + +### Shared Docker Network + +To connect FrontOffice and BackOffice containers, use a shared external network: + +1. Create the network once: `docker network create monarc-network` +2. Set `MONARC_NETWORK_NAME=monarc-network` in both projects' `.env` files. +3. Ensure the BackOffice compose file also uses the same external network name. + ### Resetting the Database To completely reset the databases: ```bash -docker-compose -f docker-compose.dev.yml down -v -docker-compose -f docker-compose.dev.yml up --build +docker compose -f docker-compose.dev.yml down -v +docker compose -f docker-compose.dev.yml up --build ``` ### Installing New PHP Dependencies @@ -263,7 +280,7 @@ php ./vendor/robmorgan/phinx/bin/phinx migrate -c ./module/Monarc/FrontOffice/mi ```bash docker exec -it monarc-fo-app bash -php ./bin/phinx seed:run -c ./module/Monarc/FrontOffice/migrations/phinx.php +php ./vendor/robmorgan/phinx/bin/phinx seed:run -c ./module/Monarc/FrontOffice/migrations/phinx.php ``` ### Rebuilding Frontend @@ -278,7 +295,12 @@ cd /var/www/html/monarc ### Xdebug Configuration -Xdebug is pre-configured in the development environment. To use it: +Xdebug is enabled by default in the development image. To disable it, set +`XDEBUG_ENABLED=0` in `.env` and rebuild the image (for example, `make start`). +You can also tune the connection behavior via `.env`: +`XDEBUG_START_WITH_REQUEST`, `XDEBUG_CLIENT_HOST`, and `XDEBUG_CLIENT_PORT`. + +When enabled, Xdebug is pre-configured. To use it: 1. Configure your IDE to listen on port 9003 2. Set the IDE key to `IDEKEY` @@ -295,10 +317,10 @@ For PhpStorm: ```bash # Check if all services are running -docker-compose -f docker-compose.dev.yml ps +docker compose -f docker-compose.dev.yml ps # Check specific service health -docker-compose -f docker-compose.dev.yml ps monarc +docker compose -f docker-compose.dev.yml ps monarc ``` ## Troubleshooting @@ -311,6 +333,9 @@ ports: - "5001:80" # Change 5001 to another available port ``` +To change the MariaDB host port without editing the compose file, set +`DBPORT_HOST` in `.env` (default: `3307`). + ### Permission Issues If you encounter permission issues with mounted volumes: @@ -324,24 +349,24 @@ chmod -R 775 /var/www/html/monarc/data Check if the database is healthy: ```bash -docker-compose -f docker-compose.dev.yml ps db +docker compose -f docker-compose.dev.yml ps db ``` If needed, restart the database: ```bash -docker-compose -f docker-compose.dev.yml restart db +docker compose -f docker-compose.dev.yml restart db ``` ### Stats Service Issues Check stats service logs: ```bash -docker-compose -f docker-compose.dev.yml logs stats-service +docker compose -f docker-compose.dev.yml logs stats-service ``` Restart the stats service: ```bash -docker-compose -f docker-compose.dev.yml restart stats-service +docker compose -f docker-compose.dev.yml restart stats-service ``` ### Rebuilding from Scratch @@ -349,13 +374,13 @@ docker-compose -f docker-compose.dev.yml restart stats-service If something goes wrong and you want to start fresh: ```bash # Stop everything -docker-compose -f docker-compose.dev.yml down -v +docker compose -f docker-compose.dev.yml down -v # Remove all related containers, images, and volumes docker system prune -a # Rebuild and start -docker-compose -f docker-compose.dev.yml up --build +docker compose -f docker-compose.dev.yml up --build ``` ## Performance Optimization @@ -388,17 +413,29 @@ All environment variables are defined in the `.env` file: | Variable | Description | Default | |----------|-------------|---------| +| `DBHOST` | MariaDB host for MONARC | `db` | +| `DBPORT_HOST` | MariaDB host port (published) | `3307` | | `DBPASSWORD_ADMIN` | MariaDB root password | `root` | | `DBNAME_COMMON` | Common database name | `monarc_common` | | `DBNAME_CLI` | CLI database name | `monarc_cli` | | `DBUSER_MONARC` | Database user | `sqlmonarcuser` | | `DBPASSWORD_MONARC` | Database password | `sqlmonarcuser` | +| `USE_BO_COMMON` | Use BackOffice `monarc_common` (`1/0`, `true/false`, `yes/no`) | `0` | +| `MONARC_NETWORK_NAME` | Shared Docker network name | `monarc-network` | +| `NODE_MAJOR` | Node.js major version for frontend tools | `16` | | `STATS_HOST` | Stats service host | `0.0.0.0` | | `STATS_PORT` | Stats service port | `5005` | | `STATS_DB_NAME` | Stats database name | `statsservice` | | `STATS_DB_USER` | Stats database user | `sqlmonarcuser` | | `STATS_DB_PASSWORD` | Stats database password | `sqlmonarcuser` | | `STATS_SECRET_KEY` | Stats service secret key | `changeme_generate_random_secret_key_for_production` | +| `XDEBUG_ENABLED` | Enable Xdebug in the build (`1/0`, `true/false`, `yes/no`) | `1` | +| `XDEBUG_MODE` | Xdebug modes (`debug`, `develop`, etc.) | `debug` | +| `XDEBUG_START_WITH_REQUEST` | Start mode (`trigger` or `yes`) | `trigger` | +| `XDEBUG_CLIENT_HOST` | Host IDE address | `host.docker.internal` | +| `XDEBUG_CLIENT_PORT` | IDE port | `9003` | +| `XDEBUG_IDEKEY` | IDE key | `IDEKEY` | +| `XDEBUG_DISCOVER_CLIENT_HOST` | Auto-detect client host (`1/0`) | `0` | ## Security Notes @@ -422,6 +459,6 @@ For production deployments: If you encounter issues: 1. Check the [troubleshooting section](#troubleshooting) -2. Review the logs: `docker-compose -f docker-compose.dev.yml logs` +2. Review the logs: `docker compose -f docker-compose.dev.yml logs` 3. Open an issue on [GitHub](https://github.com/monarc-project/MonarcAppFO/issues) 4. Join the MONARC community discussions diff --git a/README.md b/README.md index ffdbdf6..4e35f9e 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ For local development, you can use either: - **Docker** (recommended): See [README.docker.md](README.docker.md) for instructions ```bash - ./docker-dev.sh start + make start ``` - **Vagrant**: See [vagrant/README.rst](vagrant/README.rst) for instructions diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 0941b81..26c562a 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,6 +1,6 @@ services: # MariaDB database for MONARC - db: + fodb: image: mariadb:10.11 container_name: monarc-fo-db environment: @@ -8,14 +8,15 @@ services: MYSQL_DATABASE: ${DBNAME_COMMON} MYSQL_USER: ${DBUSER_MONARC} MYSQL_PASSWORD: ${DBPASSWORD_MONARC} - command: + command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_general_ci - --bind-address=0.0.0.0 ports: - - "3306:3306" + - "${DBPORT_HOST:-3307}:3306" volumes: - db_data:/var/lib/mysql + - ./docker/db-init:/docker-entrypoint-initdb.d:ro networks: - monarc-network healthcheck: @@ -25,48 +26,48 @@ services: retries: 5 # PostgreSQL database for stats service - postgres: - image: postgres:15 - container_name: monarc-fo-postgres - environment: - POSTGRES_USER: ${STATS_DB_USER} - POSTGRES_PASSWORD: ${STATS_DB_PASSWORD} - POSTGRES_DB: ${STATS_DB_NAME} - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - networks: - - monarc-network - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${STATS_DB_USER}"] - interval: 10s - timeout: 5s - retries: 5 + # postgres: + # image: postgres:15 + # container_name: monarc-fo-postgres + # environment: + # POSTGRES_USER: ${STATS_DB_USER} + # POSTGRES_PASSWORD: ${STATS_DB_PASSWORD} + # POSTGRES_DB: ${STATS_DB_NAME} + # ports: + # - "5432:5432" + # volumes: + # - postgres_data:/var/lib/postgresql/data + # networks: + # - monarc-network + # healthcheck: + # test: ["CMD-SHELL", "pg_isready -U ${STATS_DB_USER}"] + # interval: 10s + # timeout: 5s + # retries: 5 - # Stats service - stats-service: - build: - context: . - dockerfile: Dockerfile.stats - container_name: monarc-fo-stats - environment: - STATS_HOST: ${STATS_HOST} - STATS_PORT: ${STATS_PORT} - STATS_DB_HOST: postgres - STATS_DB_NAME: ${STATS_DB_NAME} - STATS_DB_USER: ${STATS_DB_USER} - STATS_DB_PASSWORD: ${STATS_DB_PASSWORD} - STATS_SECRET_KEY: ${STATS_SECRET_KEY} - ports: - - "5005:5005" - depends_on: - postgres: - condition: service_healthy - networks: - - monarc-network - volumes: - - stats_data:/var/www/stats-service + # # Stats service + # stats-service: + # build: + # context: . + # dockerfile: Dockerfile.stats + # container_name: monarc-fo-stats + # environment: + # STATS_HOST: ${STATS_HOST} + # STATS_PORT: ${STATS_PORT} + # STATS_DB_HOST: postgres + # STATS_DB_NAME: ${STATS_DB_NAME} + # STATS_DB_USER: ${STATS_DB_USER} + # STATS_DB_PASSWORD: ${STATS_DB_PASSWORD} + # STATS_SECRET_KEY: ${STATS_SECRET_KEY} + # ports: + # - "5005:5005" + # depends_on: + # postgres: + # condition: service_healthy + # networks: + # - monarc-network + # volumes: + # - stats_data:/var/www/stats-service # MailCatcher for email testing mailcatcher: @@ -79,27 +80,38 @@ services: - monarc-network # Main MONARC FrontOffice application - monarc: + monarcfoapp: build: context: . dockerfile: Dockerfile + args: + NODE_MAJOR: ${NODE_MAJOR:-16} + XDEBUG_ENABLED: ${XDEBUG_ENABLED:-1} + XDEBUG_MODE: ${XDEBUG_MODE:-debug} + XDEBUG_START_WITH_REQUEST: ${XDEBUG_START_WITH_REQUEST:-trigger} + XDEBUG_CLIENT_HOST: ${XDEBUG_CLIENT_HOST:-host.docker.internal} + XDEBUG_CLIENT_PORT: ${XDEBUG_CLIENT_PORT:-9003} + XDEBUG_IDEKEY: ${XDEBUG_IDEKEY:-IDEKEY} + XDEBUG_DISCOVER_CLIENT_HOST: ${XDEBUG_DISCOVER_CLIENT_HOST:-0} container_name: monarc-fo-app environment: - DBHOST: db + DBHOST: ${DBHOST:-fodb} DBNAME_COMMON: ${DBNAME_COMMON} DBNAME_CLI: ${DBNAME_CLI} DBUSER_MONARC: ${DBUSER_MONARC} DBPASSWORD_MONARC: ${DBPASSWORD_MONARC} + DBPASSWORD_ADMIN: ${DBPASSWORD_ADMIN} + USE_BO_COMMON: ${USE_BO_COMMON:-0} STATS_API_KEY: ${STATS_API_KEY} APP_ENV: development APP_DIR: /var/www/html/monarc ports: - "5001:80" depends_on: - db: + fodb: condition: service_healthy - stats-service: - condition: service_started + # stats-service: + # condition: service_started networks: - monarc-network volumes: @@ -112,10 +124,16 @@ services: networks: monarc-network: - driver: bridge + name: ${MONARC_NETWORK_NAME:-monarc-network} + external: true volumes: db_data: + driver: local + driver_opts: + type: none + device: ./docker/db_data + o: bind postgres_data: stats_data: vendor_data: diff --git a/docker-dev.sh b/docker-dev.sh deleted file mode 100755 index c55b340..0000000 --- a/docker-dev.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash -# Helper script for managing MONARC Docker development environment - -set -e - -COMPOSE_FILE="docker-compose.dev.yml" - -# Colors for output -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -NC='\033[0m' # No Color - -usage() { - echo -e "${GREEN}MONARC Docker Development Environment Manager${NC}" - echo "" - echo "Usage: $0 [command]" - echo "" - echo "Commands:" - echo " start Start all services (builds on first run)" - echo " stop Stop all services" - echo " restart Restart all services" - echo " logs View logs from all services" - echo " logs-app View logs from MONARC application" - echo " logs-stats View logs from stats service" - echo " shell Open a shell in the MONARC container" - echo " shell-stats Open a shell in the stats service container" - echo " db Open MySQL client in the database" - echo " reset Reset everything (removes all data)" - echo " status Show status of all services" - echo " stats-key Show the stats API key" - echo "" -} - -check_env() { - if [ ! -f .env ]; then - echo -e "${YELLOW}No .env file found. Creating from .env.dev...${NC}" - cp .env.dev .env - echo -e "${GREEN}.env file created. You can edit it to customize configuration.${NC}" - fi -} - -case "$1" in - start) - check_env - echo -e "${GREEN}Starting MONARC development environment...${NC}" - docker compose -f "$COMPOSE_FILE" up -d --build - echo -e "${GREEN}Services started!${NC}" - echo -e "MONARC FrontOffice: http://localhost:5001" - echo -e "Stats Service: http://localhost:5005" - echo -e "MailCatcher: http://localhost:1080" - echo -e "\n${YELLOW}To view logs: $0 logs${NC}" - ;; - - stop) - echo -e "${YELLOW}Stopping all services...${NC}" - docker compose -f "$COMPOSE_FILE" stop - echo -e "${GREEN}Services stopped.${NC}" - ;; - - restart) - echo -e "${YELLOW}Restarting all services...${NC}" - docker compose -f "$COMPOSE_FILE" restart - echo -e "${GREEN}Services restarted.${NC}" - ;; - - logs) - docker compose -f "$COMPOSE_FILE" logs -f - ;; - - logs-app) - docker compose -f "$COMPOSE_FILE" logs -f monarc - ;; - - logs-stats) - docker compose -f "$COMPOSE_FILE" logs -f stats-service - ;; - - shell) - echo -e "${GREEN}Opening shell in MONARC container...${NC}" - docker exec -it monarc-fo-app bash - ;; - - shell-stats) - echo -e "${GREEN}Opening shell in stats service container...${NC}" - docker exec -it monarc-fo-stats bash - ;; - - db) - echo -e "${GREEN}Opening MySQL client...${NC}" - docker exec -it monarc-fo-db mysql -usqlmonarcuser -psqlmonarcuser monarc_common - ;; - - reset) - echo -e "${RED}WARNING: This will remove all data!${NC}" - read -p "Are you sure? (yes/no): " confirm - if [ "$confirm" = "yes" ]; then - echo -e "${YELLOW}Stopping and removing all containers, volumes, and data...${NC}" - docker compose -f "$COMPOSE_FILE" down -v - echo -e "${GREEN}Reset complete. Run '$0 start' to start fresh.${NC}" - else - echo -e "${GREEN}Reset cancelled.${NC}" - fi - ;; - - status) - docker compose -f "$COMPOSE_FILE" ps - ;; - - stats-key) - echo -e "${GREEN}Retrieving stats API key...${NC}" - docker compose -f "$COMPOSE_FILE" logs stats-service | grep "Token:" | tail -1 - echo -e "\n${YELLOW}Note: Update this key in your .env file and restart MONARC service:${NC}" - echo -e " 1. Edit .env and set STATS_API_KEY=" - echo -e " 2. Run: docker compose -f \"\$COMPOSE_FILE\" restart monarc" - ;; - - *) - usage - exit 1 - ;; -esac diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index b914616..99acc57 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -11,24 +11,29 @@ echo -e "${GREEN}Starting MONARC FrontOffice setup...${NC}" # Wait for database to be ready echo -e "${YELLOW}Waiting for MariaDB to be ready...${NC}" -while ! mysqladmin ping -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" --silent 2>/dev/null; do +while ! mysqladmin ping -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" --silent 2>/dev/null; do echo "Waiting for MariaDB..." sleep 2 done echo -e "${GREEN}MariaDB is ready!${NC}" +is_true() { + case "$1" in + 1|true|yes|on) return 0 ;; + *) return 1 ;; + esac +} + # Check if this is the first run if [ ! -f "/var/www/html/monarc/.docker-initialized" ]; then echo -e "${GREEN}First run detected, initializing application...${NC}" - + cd /var/www/html/monarc - - # Install composer dependencies - if [ ! -d "vendor" ]; then - echo -e "${YELLOW}Installing Composer dependencies...${NC}" - composer install --ignore-platform-req=php - fi - + + # Install composer dependencies (always, to ensure binaries like Phinx are present) + echo -e "${YELLOW}Installing Composer dependencies...${NC}" + composer install --ignore-platform-req=php --no-interaction + # Create module symlinks echo -e "${YELLOW}Creating module symlinks...${NC}" mkdir -p module/Monarc @@ -36,40 +41,65 @@ if [ ! -f "/var/www/html/monarc/.docker-initialized" ]; then ln -sfn ./../../vendor/monarc/core Core ln -sfn ./../../vendor/monarc/frontoffice FrontOffice cd /var/www/html/monarc - + # Clone frontend repositories echo -e "${YELLOW}Setting up frontend repositories...${NC}" mkdir -p node_modules cd node_modules - + if [ ! -d "ng_client" ]; then git clone --config core.fileMode=false https://github.com/monarc-project/ng-client.git ng_client fi - + if [ ! -d "ng_anr" ]; then git clone --config core.fileMode=false https://github.com/monarc-project/ng-anr.git ng_anr fi - + cd /var/www/html/monarc - - # Check if database exists and create if needed + + # Check if CLI database exists and create databases if needed echo -e "${YELLOW}Setting up databases...${NC}" - DB_EXISTS=$(mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" -e "SHOW DATABASES LIKE '${DBNAME_CLI}';" | grep -c "${DBNAME_CLI}" || true) - + DB_EXISTS=$(mysql -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" -e "SHOW DATABASES LIKE '${DBNAME_CLI}';" | grep -c "${DBNAME_CLI}" || true) + USE_BO_COMMON_ENABLED=0 + if is_true "${USE_BO_COMMON}"; then + USE_BO_COMMON_ENABLED=1 + fi + if [ "$DB_EXISTS" -eq 0 ]; then echo -e "${YELLOW}Creating databases...${NC}" - mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" -e "CREATE DATABASE ${DBNAME_CLI} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" - mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" -e "CREATE DATABASE ${DBNAME_COMMON} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" - - echo -e "${YELLOW}Populating databases...${NC}" - mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" ${DBNAME_COMMON} < db-bootstrap/monarc_structure.sql - mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" -p"${DBPASSWORD_MONARC}" ${DBNAME_COMMON} < db-bootstrap/monarc_data.sql + mysql -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" -e "CREATE DATABASE IF NOT EXISTS ${DBNAME_CLI} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" + + if [ "$USE_BO_COMMON_ENABLED" -eq 0 ]; then + mysql -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" -e "CREATE DATABASE IF NOT EXISTS ${DBNAME_COMMON} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" + + echo -e "${YELLOW}Populating common database...${NC}" + export MYSQL_PWD="${DBPASSWORD_MONARC}" + mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" ${DBNAME_COMMON} < db-bootstrap/monarc_structure.sql + mysql -h"${DBHOST}" -u"${DBUSER_MONARC}" ${DBNAME_COMMON} < db-bootstrap/monarc_data.sql + else + echo -e "${YELLOW}USE_BO_COMMON is enabled; skipping monarc_common creation and bootstrap.${NC}" + fi + fi + + echo -e "${YELLOW}Ensuring privileges for ${DBUSER_MONARC}...${NC}" + mysql -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" -e "GRANT ALL PRIVILEGES ON ${DBNAME_CLI}.* TO '${DBUSER_MONARC}'@'%';" + if [ "$USE_BO_COMMON_ENABLED" -eq 0 ]; then + mysql -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" -e "GRANT ALL PRIVILEGES ON ${DBNAME_COMMON}.* TO '${DBUSER_MONARC}'@'%';" + fi + mysql -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" -e "FLUSH PRIVILEGES;" + + if [ "$USE_BO_COMMON_ENABLED" -eq 1 ]; then + COMMON_EXISTS=$(mysql -h"${DBHOST}" -u"root" -p"${DBPASSWORD_ADMIN}" -e "SHOW DATABASES LIKE '${DBNAME_COMMON}';" | grep -c "${DBNAME_COMMON}" || true) + if [ "$COMMON_EXISTS" -eq 0 ]; then + echo -e "${RED}USE_BO_COMMON is enabled, but ${DBNAME_COMMON} was not found on ${DBHOST}.${NC}" + echo -e "${RED}Ensure the BackOffice database is reachable and contains ${DBNAME_COMMON}.${NC}" + exit 1 + fi fi - - # Generate local config if it doesn't exist - if [ ! -f "config/autoload/local.php" ]; then - echo -e "${YELLOW}Creating local configuration...${NC}" - cat > config/autoload/local.php < config/autoload/local.php < Date: Thu, 12 Feb 2026 16:56:31 +0100 Subject: [PATCH 8/9] Fixed the stats-service and postgrtes containers launch. --- .gitignore | 2 +- Dockerfile.stats | 2 +- README.docker.md | 2 +- composer.json | 3 + docker-compose.dev.yml | 95 +++++++----- docker-stats-entrypoint.sh | 306 ++++++++++++++++++++++++++++++++----- 6 files changed, 324 insertions(+), 86 deletions(-) diff --git a/.gitignore b/.gitignore index 606ef8d..dae9d99 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,4 @@ data/* .env .docker-initialized docker/db_data -.vscode +.vscode \ No newline at end of file diff --git a/Dockerfile.stats b/Dockerfile.stats index a2b9bee..3191564 100644 --- a/Dockerfile.stats +++ b/Dockerfile.stats @@ -4,7 +4,7 @@ ENV DEBIAN_FRONTEND=noninteractive ENV LANGUAGE=en_US.UTF-8 ENV LANG=en_US.UTF-8 ENV LC_ALL=en_US.UTF-8 -ENV FLASK_APP=runserver.py +ENV FLASK_APP=app.py ENV STATS_CONFIG=production.py # Install dependencies diff --git a/README.docker.md b/README.docker.md index 1c5ceac..aa121e3 100644 --- a/README.docker.md +++ b/README.docker.md @@ -461,4 +461,4 @@ If you encounter issues: 1. Check the [troubleshooting section](#troubleshooting) 2. Review the logs: `docker compose -f docker-compose.dev.yml logs` 3. Open an issue on [GitHub](https://github.com/monarc-project/MonarcAppFO/issues) -4. Join the MONARC community discussions +4. Join the community discussions on [GitHub](https://github.com/monarc-project/MonarcAppFO/discussions) diff --git a/composer.json b/composer.json index ee05ad4..658b756 100644 --- a/composer.json +++ b/composer.json @@ -72,6 +72,9 @@ }, "config": { "bin-dir": "bin/", + "platform": { + "php": "8.1.0" + }, "allow-plugins": { "laminas/laminas-dependency-plugin": true } diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 26c562a..b5a1c7b 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -12,6 +12,7 @@ services: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_general_ci - --bind-address=0.0.0.0 + - --sql-mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION ports: - "${DBPORT_HOST:-3307}:3306" volumes: @@ -26,48 +27,48 @@ services: retries: 5 # PostgreSQL database for stats service - # postgres: - # image: postgres:15 - # container_name: monarc-fo-postgres - # environment: - # POSTGRES_USER: ${STATS_DB_USER} - # POSTGRES_PASSWORD: ${STATS_DB_PASSWORD} - # POSTGRES_DB: ${STATS_DB_NAME} - # ports: - # - "5432:5432" - # volumes: - # - postgres_data:/var/lib/postgresql/data - # networks: - # - monarc-network - # healthcheck: - # test: ["CMD-SHELL", "pg_isready -U ${STATS_DB_USER}"] - # interval: 10s - # timeout: 5s - # retries: 5 + postgres: + image: postgres:15 + container_name: monarc-fo-postgres + environment: + POSTGRES_USER: ${STATS_DB_USER} + POSTGRES_PASSWORD: ${STATS_DB_PASSWORD} + POSTGRES_DB: ${STATS_DB_NAME} + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - monarc-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${STATS_DB_USER} -d ${STATS_DB_NAME}"] + interval: 10s + timeout: 5s + retries: 5 - # # Stats service - # stats-service: - # build: - # context: . - # dockerfile: Dockerfile.stats - # container_name: monarc-fo-stats - # environment: - # STATS_HOST: ${STATS_HOST} - # STATS_PORT: ${STATS_PORT} - # STATS_DB_HOST: postgres - # STATS_DB_NAME: ${STATS_DB_NAME} - # STATS_DB_USER: ${STATS_DB_USER} - # STATS_DB_PASSWORD: ${STATS_DB_PASSWORD} - # STATS_SECRET_KEY: ${STATS_SECRET_KEY} - # ports: - # - "5005:5005" - # depends_on: - # postgres: - # condition: service_healthy - # networks: - # - monarc-network - # volumes: - # - stats_data:/var/www/stats-service + # Stats service + stats-service: + build: + context: . + dockerfile: Dockerfile.stats + container_name: monarc-fo-stats + environment: + STATS_HOST: ${STATS_HOST} + STATS_PORT: ${STATS_PORT} + STATS_DB_HOST: postgres + STATS_DB_NAME: ${STATS_DB_NAME} + STATS_DB_USER: ${STATS_DB_USER} + STATS_DB_PASSWORD: ${STATS_DB_PASSWORD} + STATS_SECRET_KEY: ${STATS_SECRET_KEY} + ports: + - "5005:5005" + depends_on: + postgres: + condition: service_healthy + networks: + - monarc-network + volumes: + - stats_data:/var/www/stats-service # MailCatcher for email testing mailcatcher: @@ -75,7 +76,7 @@ services: container_name: monarc-fo-mailcatcher ports: - "1080:1080" # Web interface - - "1025:1025" # SMTP + - "8825:1025" # SMTP networks: - monarc-network @@ -137,4 +138,14 @@ volumes: postgres_data: stats_data: vendor_data: + driver: local + driver_opts: + type: none + device: ./vendor + o: bind node_modules_data: + driver: local + driver_opts: + type: none + device: ./node_modules + o: bind diff --git a/docker-stats-entrypoint.sh b/docker-stats-entrypoint.sh index 7127751..57df8b0 100755 --- a/docker-stats-entrypoint.sh +++ b/docker-stats-entrypoint.sh @@ -7,49 +7,109 @@ NC='\033[0m' echo -e "${GREEN}Starting MONARC Stats Service setup...${NC}" -# Wait for PostgreSQL to be ready -echo -e "${YELLOW}Waiting for PostgreSQL to be ready...${NC}" -until PGPASSWORD=$STATS_DB_PASSWORD psql -h "$STATS_DB_HOST" -U "$STATS_DB_USER" -d postgres -c '\q' 2>/dev/null; do - echo "Waiting for PostgreSQL..." - sleep 2 -done -echo -e "${GREEN}PostgreSQL is ready!${NC}" +write_health_wrapper() { + cat > /var/www/stats-service/monarc_health_app.py <<'PY' +import importlib +import os +import pkgutil +import sys -# Check if this is the first run -if [ ! -f "/var/www/stats-service/.docker-initialized" ]; then - echo -e "${GREEN}First run detected, initializing stats service...${NC}" - - # Clone the stats service repository - if [ ! -d "/var/www/stats-service/.git" ]; then - echo -e "${YELLOW}Cloning stats-service repository...${NC}" - cd /var/www - git clone https://github.com/monarc-project/stats-service stats-service-tmp - cp -r stats-service-tmp/* stats-service/ - cp -r stats-service-tmp/.git stats-service/ - rm -rf stats-service-tmp - cd /var/www/stats-service +from flask.cli import ScriptInfo + +base_app = os.environ.get("STATS_BASE_APP") or "app" + +info = ScriptInfo(app_import_path=base_app) +app = info.load_app() + +try: + import statsservice + for _, modname, _ in pkgutil.walk_packages(statsservice.__path__, statsservice.__name__ + "."): + try: + importlib.import_module(modname) + except Exception: + pass +except Exception: + pass + +@app.get("/health") +def health(): + return {"status": "ok"} +PY +} + +detect_flask_app() { + if [ -f "/var/www/stats-service/app.py" ]; then + echo "app.py" + return 0 fi - - # Install npm dependencies - echo -e "${YELLOW}Installing npm dependencies...${NC}" - npm ci - - # Install Python dependencies with Poetry - echo -e "${YELLOW}Installing Python dependencies with Poetry...${NC}" - poetry install --only=main - - # Create instance directory and configuration + if [ -f "/var/www/stats-service/runserver.py" ]; then + echo "runserver.py" + return 0 + fi + if [ -f "/var/www/stats-service/statsservice/bootstrap.py" ]; then + echo "statsservice.bootstrap" + return 0 + fi + return 1 +} + +ensure_flask_app() { + local detected_app + local flask_app_missing=0 + + if [ -n "${FLASK_APP}" ]; then + if [[ "${FLASK_APP}" == *.py ]]; then + [ -f "/var/www/stats-service/${FLASK_APP}" ] || flask_app_missing=1 + else + local module_path="/var/www/stats-service/${FLASK_APP//.//}.py" + local module_dir="/var/www/stats-service/${FLASK_APP//.//}/__init__.py" + if [ ! -f "${module_path}" ] && [ ! -f "${module_dir}" ]; then + flask_app_missing=1 + fi + fi + fi + + if [ -z "${FLASK_APP}" ] || [ "${flask_app_missing}" -eq 1 ]; then + detected_app=$(detect_flask_app || true) + if [ -z "${detected_app}" ]; then + echo -e "${YELLOW}Could not detect Flask app entrypoint. Check stats-service repo layout.${NC}" + exit 1 + fi + export FLASK_APP="${detected_app}" + echo -e "${GREEN}Using FLASK_APP=${FLASK_APP}${NC}" + fi + + BASE_FLASK_APP="${FLASK_APP}" +} + +ensure_python_deps() { + if ! poetry run python - <<'PY' +import importlib +import sys +try: + importlib.import_module("flask") +except Exception: + sys.exit(1) +PY + then + echo -e "${YELLOW}Installing Python dependencies with Poetry...${NC}" + poetry install --only=main + fi +} + +write_instance_config() { echo -e "${YELLOW}Creating configuration...${NC}" mkdir -p instance + STATS_INSTANCE_URL_VALUE="${STATS_INSTANCE_URL:-http://localhost:${STATS_PORT}}" cat > instance/production.py </dev/null; do + echo "Waiting for PostgreSQL..." + sleep 2 +done +echo -e "${GREEN}PostgreSQL is ready!${NC}" + +# Check if this is the first run +if [ ! -f "/var/www/stats-service/.docker-initialized" ]; then + echo -e "${GREEN}First run detected, initializing stats service...${NC}" + + # Clone the stats service repository + if [ ! -d "/var/www/stats-service/.git" ]; then + echo -e "${YELLOW}Cloning stats-service repository...${NC}" + cd /var/www + git clone https://github.com/monarc-project/stats-service stats-service-tmp + cp -r stats-service-tmp/* stats-service/ + cp -r stats-service-tmp/.git stats-service/ + rm -rf stats-service-tmp + cd /var/www/stats-service + fi + + ensure_flask_app + + flask_has_command() { + local cmd="$1" + poetry run flask --app "${FLASK_APP}" --help 2>/dev/null | grep -qE "^[[:space:]]+${cmd}[[:space:]]" + } + + run_flask() { + poetry run flask --app "${FLASK_APP}" "$@" + } + + run_db_upgrade() { + run_flask db upgrade + } + + run_db_stamp_head() { + run_flask db stamp head + } + + db_has_tables() { + local count + count=$(PGPASSWORD=$STATS_DB_PASSWORD psql -h "$STATS_DB_HOST" -U "$STATS_DB_USER" -d "$STATS_DB_NAME" -tAc "select count(*) from information_schema.tables where table_schema='public';" 2>/dev/null | tr -d '[:space:]') + if [ -z "${count}" ]; then + return 1 + fi + [ "${count}" -gt 0 ] + } + + create_schema_fallback() { + echo -e "${YELLOW}Attempting SQLAlchemy create_all() fallback...${NC}" + poetry run python - <<'PY' +import importlib +import os +import sys +import pkgutil + +from flask.cli import ScriptInfo + +app_path = os.environ.get("FLASK_APP") +if not app_path: + print("FLASK_APP is not set; cannot load app.", file=sys.stderr) + sys.exit(1) + +info = ScriptInfo(app_import_path=app_path) +app = info.load_app() + +with app.app_context(): + try: + import statsservice + for _, modname, _ in pkgutil.walk_packages(statsservice.__path__, statsservice.__name__ + "."): + try: + importlib.import_module(modname) + except Exception: + pass + except Exception: + for mod in ( + "statsservice.models", + "statsservice.model", + "statsservice.api.v1", + "statsservice.api", + ): + try: + importlib.import_module(mod) + except Exception: + pass + + ext = app.extensions.get("sqlalchemy") + db = None + if ext is not None: + db = ext if hasattr(ext, "create_all") else getattr(ext, "db", None) + if db is None: + for mod in ("statsservice.extensions", "statsservice.models", "statsservice"): + try: + candidate = importlib.import_module(mod) + if hasattr(candidate, "db"): + db = candidate.db + break + except Exception: + pass + + if db is None or not hasattr(db, "create_all"): + print("Could not resolve SQLAlchemy db instance.", file=sys.stderr) + sys.exit(1) + + db.create_all() + print("Schema created via SQLAlchemy create_all().") +PY + } + + # Install npm dependencies + echo -e "${YELLOW}Installing npm dependencies...${NC}" + npm ci + + ensure_python_deps + + write_instance_config # Initialize database echo -e "${YELLOW}Initializing database...${NC}" - poetry run flask db_create - poetry run flask db_init + if flask_has_command "db_create"; then + run_flask db_create + fi + + if flask_has_command "db_init"; then + run_flask db_init + fi + + if flask_has_command "db"; then + if ! db_has_tables; then + if create_schema_fallback; then + echo -e "${YELLOW}Empty database detected. Stamping head after create_all...${NC}" + run_db_stamp_head + else + echo -e "${YELLOW}Schema fallback failed on empty database.${NC}" + exit 1 + fi + else + if ! UPGRADE_OUT=$(run_db_upgrade 2>&1); then + if echo "${UPGRADE_OUT}" | grep -q "DuplicateColumn"; then + echo -e "${YELLOW}Migration already applied (duplicate column). Stamping head...${NC}" + run_db_stamp_head + elif create_schema_fallback; then + echo -e "${YELLOW}Schema created. Stamping head to match models...${NC}" + run_db_stamp_head + else + echo -e "${YELLOW}Database upgrade failed and schema fallback failed.${NC}" + exit 1 + fi + fi + fi + elif ! flask_has_command "db_create" && ! flask_has_command "db_init"; then + echo -e "${YELLOW}No database init/create/upgrade command found in Flask CLI.${NC}" + fi # Create admin client echo -e "${YELLOW}Creating admin client...${NC}" - poetry run flask client_create --name ADMIN --role admin - - # Create client for MONARC and capture the API key - echo -e "${YELLOW}Creating MONARC client...${NC}" - poetry run flask client_create --name admin_localhost + if flask_has_command "client_create"; then + run_flask client_create --name ADMIN --role admin + + # Create client for MONARC and capture the API key + echo -e "${YELLOW}Creating MONARC client...${NC}" + run_flask client_create --name admin_localhost + else + echo -e "${YELLOW}No client_create command found in Flask CLI. Skipping client setup.${NC}" + fi # Mark initialization as complete touch /var/www/stats-service/.docker-initialized echo -e "${GREEN}Stats service initialization complete!${NC}" else echo -e "${GREEN}Stats service already initialized, starting...${NC}" + cd /var/www/stats-service + ensure_flask_app + ensure_python_deps + write_instance_config fi # Start the Flask application +write_health_wrapper +export STATS_BASE_APP="${BASE_FLASK_APP}" +export FLASK_APP="monarc_health_app.py" echo -e "${GREEN}Starting Flask application on ${STATS_HOST}:${STATS_PORT}${NC}" -exec poetry run flask run --host=${STATS_HOST} --port=${STATS_PORT} +exec poetry run flask --app "${FLASK_APP}" run --host=${STATS_HOST} --port=${STATS_PORT} From 889a1c0d7a04fcc659dde9f86d99655ea53dc97b Mon Sep 17 00:00:00 2001 From: Ruslan Baidan Date: Thu, 12 Feb 2026 17:00:17 +0100 Subject: [PATCH 9/9] Removed the platform ignore option frome the composer packages update as it is not needed anymore. --- .github/workflows/php.yml | 2 +- .github/workflows/releases.yml | 2 +- composer.lock | 828 ++++++++++++++++----------------- scripts/update-all.sh | 2 +- vagrant/bootstrap.sh | 2 +- 5 files changed, 418 insertions(+), 418 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 78723fa..4be55b1 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -45,7 +45,7 @@ jobs: run: composer validate - name: Install PHP dependencies - run: composer install --prefer-dist --no-progress --no-suggest --ignore-platform-req=php + run: composer install --prefer-dist --no-progress --no-suggest - name: Create synlinks for MONARC PHP modules run: | diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 8f53443..8fe5c4e 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -34,7 +34,7 @@ jobs: run: composer validate - name: Install PHP dependencies - run: composer install --prefer-dist --no-progress --no-suggest --no-dev --ignore-platform-req=php + run: composer install --prefer-dist --no-progress --no-suggest --no-dev - name: Symlink Monarc modules run: | diff --git a/composer.lock b/composer.lock index 4409834..c988834 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1b3a6cbf1c4dfa360fc41fdcae59b1fb", + "content-hash": "1470ca72272464dff4ea4ab7cd06c8d7", "packages": [ { "name": "bacon/bacon-qr-code", @@ -62,25 +62,25 @@ }, { "name": "brick/math", - "version": "0.14.1", + "version": "0.13.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", - "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", "shasum": "" }, "require": { - "php": "^8.2" + "php": "^8.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpstan/phpstan": "2.1.22", - "phpunit/phpunit": "^11.5" + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" }, "type": "library", "autoload": { @@ -110,7 +110,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.1" + "source": "https://github.com/brick/math/tree/0.13.1" }, "funding": [ { @@ -118,7 +118,7 @@ "type": "github" } ], - "time": "2025-11-24T14:40:29+00:00" + "time": "2025-03-29T13:50:30+00:00" }, { "name": "brick/varexporter", @@ -1935,6 +1935,88 @@ }, "time": "2020-11-24T22:02:12+00:00" }, + { + "name": "friendsofphp/proxy-manager-lts", + "version": "v1.0.19", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/proxy-manager-lts.git", + "reference": "c20299aa9f48a622052964a75c5a4cef017398b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/proxy-manager-lts/zipball/c20299aa9f48a622052964a75c5a4cef017398b2", + "reference": "c20299aa9f48a622052964a75c5a4cef017398b2", + "shasum": "" + }, + "require": { + "laminas/laminas-code": "~3.4.1|^4.0", + "php": ">=7.1", + "symfony/filesystem": "^4.4.17|^5.0|^6.0|^7.0|^8.0" + }, + "conflict": { + "laminas/laminas-stdlib": "<3.2.1", + "zendframework/zend-stdlib": "<3.2.1" + }, + "replace": { + "ocramius/proxy-manager": "^2.1" + }, + "require-dev": { + "ext-phar": "*", + "symfony/phpunit-bridge": "^5.4|^6.0|^7.0" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/Ocramius/ProxyManager", + "name": "ocramius/proxy-manager" + } + }, + "autoload": { + "psr-4": { + "ProxyManager\\": "src/ProxyManager" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + } + ], + "description": "Adding support for a wider range of PHP versions to ocramius/proxy-manager", + "homepage": "https://github.com/FriendsOfPHP/proxy-manager-lts", + "keywords": [ + "aop", + "lazy loading", + "proxy", + "proxy pattern", + "service proxies" + ], + "support": { + "issues": "https://github.com/FriendsOfPHP/proxy-manager-lts/issues", + "source": "https://github.com/FriendsOfPHP/proxy-manager-lts/tree/v1.0.19" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ocramius/proxy-manager", + "type": "tidelift" + } + ], + "time": "2025-10-28T10:28:17+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.5.8", @@ -2236,37 +2318,38 @@ }, { "name": "laminas/laminas-authentication", - "version": "2.19.0", + "version": "2.18.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-authentication.git", - "reference": "717b7a26e55f65a7c97325e49fa0b6fa2ea4c79a" + "reference": "c1da3ec75bd4d6e3c63cf3a89f0f1a59a81a82bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-authentication/zipball/717b7a26e55f65a7c97325e49fa0b6fa2ea4c79a", - "reference": "717b7a26e55f65a7c97325e49fa0b6fa2ea4c79a", + "url": "https://api.github.com/repos/laminas/laminas-authentication/zipball/c1da3ec75bd4d6e3c63cf3a89f0f1a59a81a82bd", + "reference": "c1da3ec75bd4d6e3c63cf3a89f0f1a59a81a82bd", "shasum": "" }, "require": { "ext-mbstring": "*", "laminas/laminas-stdlib": "^3.19.0", - "php": "~8.2.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-authentication": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "~3.1.0", + "laminas/laminas-coding-standard": "~2.5.0", "laminas/laminas-db": "^2.20.0", "laminas/laminas-http": "^2.19.0", "laminas/laminas-ldap": "^2.18.1", "laminas/laminas-session": "^2.21.0", "laminas/laminas-uri": "^2.12.0", "laminas/laminas-validator": "^2.64.1", - "phpunit/phpunit": "^11.5.42", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "phpunit/phpunit": "^9.6.20", + "psalm/plugin-phpunit": "^0.19.0", + "squizlabs/php_codesniffer": "^3.10.2", + "vimeo/psalm": "^5.26.0" }, "suggest": { "laminas/laminas-db": "Laminas\\Db component", @@ -2306,7 +2389,7 @@ "type": "community_bridge" } ], - "time": "2025-10-17T15:08:49+00:00" + "time": "2024-10-21T10:45:35+00:00" }, { "name": "laminas/laminas-cache", @@ -2411,25 +2494,25 @@ }, { "name": "laminas/laminas-captcha", - "version": "2.19.0", + "version": "2.18.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-captcha.git", - "reference": "768d2152f9687c27b5dfdb2322bf6001d48cda89" + "reference": "4c0965b31ec310ec95c72acd76a016b5030182fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-captcha/zipball/768d2152f9687c27b5dfdb2322bf6001d48cda89", - "reference": "768d2152f9687c27b5dfdb2322bf6001d48cda89", + "url": "https://api.github.com/repos/laminas/laminas-captcha/zipball/4c0965b31ec310ec95c72acd76a016b5030182fe", + "reference": "4c0965b31ec310ec95c72acd76a016b5030182fe", "shasum": "" }, "require": { "laminas/laminas-recaptcha": "^3.4.0", - "laminas/laminas-session": "^2.25", + "laminas/laminas-session": "^2.12", "laminas/laminas-stdlib": "^3.10.1", - "laminas/laminas-text": "^2.12.1", + "laminas/laminas-text": "^2.9.0", "laminas/laminas-validator": "^2.19.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-captcha": "*" @@ -2439,7 +2522,7 @@ "laminas/laminas-coding-standard": "~2.5.0", "phpunit/phpunit": "^9.5.26", "psalm/plugin-phpunit": "^0.19.0", - "vimeo/psalm": "^6.13" + "vimeo/psalm": "^5.1" }, "suggest": { "laminas/laminas-i18n-resources": "Translations of captcha messages" @@ -2474,31 +2557,31 @@ "type": "community_bridge" } ], - "time": "2025-10-29T17:20:39+00:00" + "time": "2025-01-06T20:04:41+00:00" }, { "name": "laminas/laminas-code", - "version": "4.17.0", + "version": "4.16.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-code.git", - "reference": "40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd" + "reference": "1793e78dad4108b594084d05d1fb818b85b110af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-code/zipball/40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd", - "reference": "40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/1793e78dad4108b594084d05d1fb818b85b110af", + "reference": "1793e78dad4108b594084d05d1fb818b85b110af", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { "doctrine/annotations": "^2.0.1", "ext-phar": "*", "laminas/laminas-coding-standard": "^3.0.0", "laminas/laminas-stdlib": "^3.18.0", - "phpunit/phpunit": "^10.5.58", + "phpunit/phpunit": "^10.5.37", "psalm/plugin-phpunit": "^0.19.0", "vimeo/psalm": "^5.15.0" }, @@ -2537,7 +2620,7 @@ "type": "community_bridge" } ], - "time": "2025-11-01T09:38:14+00:00" + "time": "2024-11-20T13:15:13+00:00" }, { "name": "laminas/laminas-config", @@ -2741,20 +2824,20 @@ }, { "name": "laminas/laminas-diactoros", - "version": "3.8.0", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "60c182916b2749480895601649563970f3f12ec4" + "reference": "b6a3b5bebb1a124f6e4ae22f3571ac83dee4b07d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/60c182916b2749480895601649563970f3f12ec4", - "reference": "60c182916b2749480895601649563970f3f12ec4", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/b6a3b5bebb1a124f6e4ae22f3571ac83dee4b07d", + "reference": "b6a3b5bebb1a124f6e4ae22f3571ac83dee4b07d", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "psr/http-factory": "^1.1", "psr/http-message": "^1.1 || ^2.0" }, @@ -2825,36 +2908,36 @@ "type": "community_bridge" } ], - "time": "2025-10-12T15:31:36+00:00" + "time": "2025-10-11T18:30:50+00:00" }, { "name": "laminas/laminas-escaper", - "version": "2.18.0", + "version": "2.17.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-escaper.git", - "reference": "06f211dfffff18d91844c1f55250d5d13c007e18" + "reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/06f211dfffff18d91844c1f55250d5d13c007e18", - "reference": "06f211dfffff18d91844c1f55250d5d13c007e18", + "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/df1ef9503299a8e3920079a16263b578eaf7c3ba", + "reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba", "shasum": "" }, "require": { "ext-ctype": "*", "ext-mbstring": "*", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-escaper": "*" }, "require-dev": { - "infection/infection": "^0.31.0", - "laminas/laminas-coding-standard": "~3.1.0", - "phpunit/phpunit": "^11.5.42", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "infection/infection": "^0.29.8", + "laminas/laminas-coding-standard": "~3.0.1", + "phpunit/phpunit": "^10.5.45", + "psalm/plugin-phpunit": "^0.19.2", + "vimeo/psalm": "^6.6.2" }, "type": "library", "autoload": { @@ -2886,40 +2969,37 @@ "type": "community_bridge" } ], - "time": "2025-10-14T18:31:13+00:00" + "time": "2025-05-06T19:29:36+00:00" }, { "name": "laminas/laminas-eventmanager", - "version": "3.15.0", + "version": "3.14.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-eventmanager.git", - "reference": "90b4bd33264629af8e39caf5aa83473ac03aa04c" + "reference": "1837cafaaaee74437f6d8ec9ff7da03e6f81d809" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-eventmanager/zipball/90b4bd33264629af8e39caf5aa83473ac03aa04c", - "reference": "90b4bd33264629af8e39caf5aa83473ac03aa04c", + "url": "https://api.github.com/repos/laminas/laminas-eventmanager/zipball/1837cafaaaee74437f6d8ec9ff7da03e6f81d809", + "reference": "1837cafaaaee74437f6d8ec9ff7da03e6f81d809", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "container-interop/container-interop": "<1.2", "zendframework/zend-eventmanager": "*" }, "require-dev": { - "amphp/dns": "^2.2", - "amphp/socket": "^2.3.1", - "laminas/laminas-coding-standard": "~3.1.0", + "laminas/laminas-coding-standard": "~3.0.0", "laminas/laminas-stdlib": "^3.20", "phpbench/phpbench": "^1.3.1", - "phpunit/phpunit": "^10.5.58", + "phpunit/phpunit": "^10.5.38", "psalm/plugin-phpunit": "^0.19.0", "psr/container": "^1.1.2 || ^2.0.2", - "sebastian/recursion-context": "^5.0.1", - "vimeo/psalm": "^6.13" + "vimeo/psalm": "^5.26.1" }, "suggest": { "laminas/laminas-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature", @@ -2957,39 +3037,39 @@ "type": "community_bridge" } ], - "time": "2025-10-31T10:29:01+00:00" + "time": "2024-11-21T11:31:22+00:00" }, { "name": "laminas/laminas-filter", - "version": "2.42.0", + "version": "2.41.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-filter.git", - "reference": "985d27bd42daf51b415ce1ee889e0978cc1e59ed" + "reference": "eaa00111231bf6669826ae84d3abe85b94477585" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-filter/zipball/985d27bd42daf51b415ce1ee889e0978cc1e59ed", - "reference": "985d27bd42daf51b415ce1ee889e0978cc1e59ed", + "url": "https://api.github.com/repos/laminas/laminas-filter/zipball/eaa00111231bf6669826ae84d3abe85b94477585", + "reference": "eaa00111231bf6669826ae84d3abe85b94477585", "shasum": "" }, "require": { "ext-mbstring": "*", "laminas/laminas-servicemanager": "^3.21.0", "laminas/laminas-stdlib": "^3.19.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "laminas/laminas-validator": "<2.10.1", "zendframework/zend-filter": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "^3.1", + "laminas/laminas-coding-standard": "~3.0", "laminas/laminas-crypt": "^3.12", - "laminas/laminas-i18n": "^2.30.0", - "laminas/laminas-uri": "^2.13", - "pear/archive_tar": "^1.6.0", - "phpunit/phpunit": "^10.5.58", + "laminas/laminas-i18n": "^2.28.1", + "laminas/laminas-uri": "^2.12", + "pear/archive_tar": "^1.5.0", + "phpunit/phpunit": "^10.5.36", "psalm/plugin-phpunit": "^0.19.0", "psr/http-factory": "^1.1.0", "vimeo/psalm": "^5.26.1" @@ -3036,33 +3116,27 @@ "type": "community_bridge" } ], - "time": "2025-10-13T15:44:52+00:00" + "time": "2025-05-05T02:02:31+00:00" }, { "name": "laminas/laminas-form", - "version": "3.24.0", + "version": "3.21.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-form.git", - "reference": "f8d04284db03a0cc6cc712e565c2b012179ec196" + "reference": "653c869d10c361027ae6c660c991ec3e3f38ed65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-form/zipball/f8d04284db03a0cc6cc712e565c2b012179ec196", - "reference": "f8d04284db03a0cc6cc712e565c2b012179ec196", + "url": "https://api.github.com/repos/laminas/laminas-form/zipball/653c869d10c361027ae6c660c991ec3e3f38ed65", + "reference": "653c869d10c361027ae6c660c991ec3e3f38ed65", "shasum": "" }, "require": { - "ext-mbstring": "*", - "laminas/laminas-escaper": "^2", - "laminas/laminas-filter": "^2", - "laminas/laminas-hydrator": "^4.16.0", - "laminas/laminas-inputfilter": "^2.32.0", - "laminas/laminas-servicemanager": "^3.22.1", - "laminas/laminas-stdlib": "^3.20.0", - "laminas/laminas-validator": "^2", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "psr/container": "^1.1.2" + "laminas/laminas-hydrator": "^4.13.0", + "laminas/laminas-inputfilter": "^2.24.0", + "laminas/laminas-stdlib": "^3.16.1", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "doctrine/annotations": "<1.14.0", @@ -3074,26 +3148,30 @@ "laminas/laminas-view": "<2.27.0" }, "require-dev": { - "doctrine/annotations": "^1.14.3 || ^2.0.2", - "ext-gd": "*", + "doctrine/annotations": "^1.14.3 || ^2.0.1", "ext-intl": "*", - "laminas/laminas-captcha": "^2.19", - "laminas/laminas-coding-standard": "^3.1.0", - "laminas/laminas-eventmanager": "^3.15.0", - "laminas/laminas-i18n": "^2.31.0", - "laminas/laminas-modulemanager": "^2.19.0", - "laminas/laminas-recaptcha": "^3.8", - "laminas/laminas-session": "^2.25.1", - "laminas/laminas-text": "^2.12.1", - "laminas/laminas-view": "^2.43", - "phpunit/phpunit": "^11.5.43", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "laminas/laminas-captcha": "^2.17", + "laminas/laminas-coding-standard": "^2.5", + "laminas/laminas-db": "^2.20", + "laminas/laminas-escaper": "^2.13", + "laminas/laminas-eventmanager": "^3.13.1", + "laminas/laminas-filter": "^2.36", + "laminas/laminas-i18n": "^2.28.0", + "laminas/laminas-modulemanager": "^2.16.0", + "laminas/laminas-recaptcha": "^3.7", + "laminas/laminas-servicemanager": "^3.22.1", + "laminas/laminas-session": "^2.21", + "laminas/laminas-text": "^2.11.0", + "laminas/laminas-validator": "^2.64.1", + "laminas/laminas-view": "^2.35", + "phpunit/phpunit": "^10.5.29", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.25" }, "suggest": { "doctrine/annotations": "^1.14, required to use laminas-form annotations support", "laminas/laminas-captcha": "^2.16, required for using CAPTCHA form elements", - "laminas/laminas-eventmanager": "^3.10, required for laminas-form annotations support", + "laminas/laminas-eventmanager": "^3.10, reuired for laminas-form annotations support", "laminas/laminas-i18n": "^2.21, required when using laminas-form view helpers", "laminas/laminas-recaptcha": "^3.6, in order to use the ReCaptcha form element", "laminas/laminas-servicemanager": "^3.20, required to use the form factories or provide services", @@ -3135,28 +3213,28 @@ "type": "community_bridge" } ], - "time": "2025-12-15T13:11:28+00:00" + "time": "2024-10-09T08:28:30+00:00" }, { "name": "laminas/laminas-http", - "version": "2.23.0", + "version": "2.22.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-http.git", - "reference": "9462fc84330d25b23383823831380abb33907fdd" + "reference": "5052177fb8176e00b0d4b89108648f557be072b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-http/zipball/9462fc84330d25b23383823831380abb33907fdd", - "reference": "9462fc84330d25b23383823831380abb33907fdd", + "url": "https://api.github.com/repos/laminas/laminas-http/zipball/5052177fb8176e00b0d4b89108648f557be072b7", + "reference": "5052177fb8176e00b0d4b89108648f557be072b7", "shasum": "" }, "require": { "laminas/laminas-loader": "^2.10", "laminas/laminas-stdlib": "^3.6", - "laminas/laminas-uri": "^2.14", + "laminas/laminas-uri": "^2.11", "laminas/laminas-validator": "^2.15 || ^3.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-http": "*" @@ -3200,25 +3278,25 @@ "type": "community_bridge" } ], - "time": "2025-12-05T11:02:08+00:00" + "time": "2025-05-06T08:24:40+00:00" }, { "name": "laminas/laminas-hydrator", - "version": "4.17.0", + "version": "4.16.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-hydrator.git", - "reference": "626c5e446fdfa27865dfe3cd29123108408c2555" + "reference": "a162bd571924968d67ef1f43aed044b8f9c108ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-hydrator/zipball/626c5e446fdfa27865dfe3cd29123108408c2555", - "reference": "626c5e446fdfa27865dfe3cd29123108408c2555", + "url": "https://api.github.com/repos/laminas/laminas-hydrator/zipball/a162bd571924968d67ef1f43aed044b8f9c108ef", + "reference": "a162bd571924968d67ef1f43aed044b8f9c108ef", "shasum": "" }, "require": { "laminas/laminas-stdlib": "^3.20", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "webmozart/assert": "^1.11" }, "conflict": { @@ -3230,11 +3308,11 @@ "laminas/laminas-eventmanager": "^3.13.1", "laminas/laminas-modulemanager": "^2.16.0", "laminas/laminas-serializer": "^2.17.0", - "laminas/laminas-servicemanager": "^3.24.0", + "laminas/laminas-servicemanager": "^3.23.0", "phpbench/phpbench": "^1.3.1", - "phpunit/phpunit": "^11.5.42", + "phpunit/phpunit": "^10.5.38", "psalm/plugin-phpunit": "^0.19.0", - "vimeo/psalm": "^6.13.1" + "vimeo/psalm": "^5.26.1" }, "suggest": { "laminas/laminas-eventmanager": "^3.13, to support aggregate hydrator usage", @@ -3277,31 +3355,28 @@ "type": "community_bridge" } ], - "time": "2025-11-06T11:05:29+00:00" + "time": "2024-11-13T14:04:02+00:00" }, { "name": "laminas/laminas-i18n", - "version": "2.32.1", + "version": "2.30.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-i18n.git", - "reference": "8e71b40318f0df6253329e837188e1d77cf83aea" + "reference": "397907ee061e147939364df9d6c485ac1e0fed87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/8e71b40318f0df6253329e837188e1d77cf83aea", - "reference": "8e71b40318f0df6253329e837188e1d77cf83aea", + "url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/397907ee061e147939364df9d6c485ac1e0fed87", + "reference": "397907ee061e147939364df9d6c485ac1e0fed87", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-intl": "*", - "laminas/laminas-escaper": "^2.0", "laminas/laminas-servicemanager": "^3.21.0", "laminas/laminas-stdlib": "^3.0", "laminas/laminas-translator": "^1.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "psr/container": "^1.0.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "laminas/laminas-view": "<2.20.0", @@ -3311,15 +3386,15 @@ "laminas/laminas-cache": "^3.13.0", "laminas/laminas-cache-storage-adapter-memory": "^2.4.0", "laminas/laminas-cache-storage-deprecated-factory": "^1.3", - "laminas/laminas-coding-standard": "^3.1", + "laminas/laminas-coding-standard": "~2.5.0", "laminas/laminas-config": "^3.10.1", - "laminas/laminas-eventmanager": "^3.15.0", - "laminas/laminas-filter": "^2.42", - "laminas/laminas-validator": "^2.65.0", - "laminas/laminas-view": "^2.44", - "phpunit/phpunit": "^11.5.46", + "laminas/laminas-eventmanager": "^3.14.0", + "laminas/laminas-filter": "^2.40", + "laminas/laminas-validator": "^2.64.2", + "laminas/laminas-view": "^2.36", + "phpunit/phpunit": "^10.5.45", "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.14.2" + "vimeo/psalm": "^6.10.0" }, "suggest": { "laminas/laminas-cache": "You should install this package to cache the translations", @@ -3366,33 +3441,33 @@ "type": "community_bridge" } ], - "time": "2025-12-15T14:23:40+00:00" + "time": "2025-04-15T09:07:02+00:00" }, { "name": "laminas/laminas-i18n-resources", - "version": "2.13.0", + "version": "2.12.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-i18n-resources.git", - "reference": "6709bdccd7d884f9c68fd2d193ad428f1d1ff0f0" + "reference": "4c6148b97fea3e5f6857053fb07b8794f6ff9245" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-i18n-resources/zipball/6709bdccd7d884f9c68fd2d193ad428f1d1ff0f0", - "reference": "6709bdccd7d884f9c68fd2d193ad428f1d1ff0f0", + "url": "https://api.github.com/repos/laminas/laminas-i18n-resources/zipball/4c6148b97fea3e5f6857053fb07b8794f6ff9245", + "reference": "4c6148b97fea3e5f6857053fb07b8794f6ff9245", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-i18n-resources": "*" }, "require-dev": { "laminas/laminas-coding-standard": "~3.1.0", - "phpunit/phpunit": "^11.5.42", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "phpunit/phpunit": "^10.5.38", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.26.1" }, "type": "library", "autoload": { @@ -3425,20 +3500,20 @@ "type": "community_bridge" } ], - "time": "2025-10-15T07:40:55+00:00" + "time": "2025-08-27T12:54:13+00:00" }, { "name": "laminas/laminas-inputfilter", - "version": "2.34.0", + "version": "2.33.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-inputfilter.git", - "reference": "5589fcfa366de04f34a5634b43c6c66e69bd2fe8" + "reference": "f53f4db544a22bb608d11c213bec0740266b34e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-inputfilter/zipball/5589fcfa366de04f34a5634b43c6c66e69bd2fe8", - "reference": "5589fcfa366de04f34a5634b43c6c66e69bd2fe8", + "url": "https://api.github.com/repos/laminas/laminas-inputfilter/zipball/f53f4db544a22bb608d11c213bec0740266b34e9", + "reference": "f53f4db544a22bb608d11c213bec0740266b34e9", "shasum": "" }, "require": { @@ -3446,7 +3521,7 @@ "laminas/laminas-servicemanager": "^3.21.0", "laminas/laminas-stdlib": "^3.19", "laminas/laminas-validator": "^2.60.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "psr/container": "^1.1 || ^2.0" }, "conflict": { @@ -3455,10 +3530,10 @@ "require-dev": { "ext-json": "*", "laminas/laminas-coding-standard": "^3.1.0", - "phpunit/phpunit": "^11.5.42", + "phpunit/phpunit": "^10.5.46", "psalm/plugin-phpunit": "^0.19.5", "psr/http-message": "^2.0", - "vimeo/psalm": "^6.13.1", + "vimeo/psalm": "^6.11.0", "webmozart/assert": "^1.11" }, "suggest": { @@ -3500,7 +3575,7 @@ "type": "community_bridge" } ], - "time": "2025-10-14T19:52:47+00:00" + "time": "2025-10-14T19:29:44+00:00" }, { "name": "laminas/laminas-json", @@ -3566,20 +3641,20 @@ }, { "name": "laminas/laminas-loader", - "version": "2.11.1", + "version": "2.12.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-loader.git", - "reference": "c507d5eccb969f7208434e3980680a1f6c0b1d8d" + "reference": "ec8cee33fb254ee4d9c8e8908c870e5c797e1272" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/c507d5eccb969f7208434e3980680a1f6c0b1d8d", - "reference": "c507d5eccb969f7208434e3980680a1f6c0b1d8d", + "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/ec8cee33fb254ee4d9c8e8908c870e5c797e1272", + "reference": "ec8cee33fb254ee4d9c8e8908c870e5c797e1272", "shasum": "" }, "require": { - "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "^8.0.0" }, "conflict": { "zendframework/zend-loader": "*" @@ -3619,7 +3694,7 @@ } ], "abandoned": true, - "time": "2024-12-05T14:43:32+00:00" + "time": "2025-12-30T11:30:39+00:00" }, { "name": "laminas/laminas-log", @@ -3850,25 +3925,25 @@ }, { "name": "laminas/laminas-modulemanager", - "version": "2.19.0", + "version": "2.18.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-modulemanager.git", - "reference": "ca2438b20ffc0ec3352bd0a583a31f24403320ad" + "reference": "4b14617df01be6c83ac62fdb689427f8ed56d9c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-modulemanager/zipball/ca2438b20ffc0ec3352bd0a583a31f24403320ad", - "reference": "ca2438b20ffc0ec3352bd0a583a31f24403320ad", + "url": "https://api.github.com/repos/laminas/laminas-modulemanager/zipball/4b14617df01be6c83ac62fdb689427f8ed56d9c1", + "reference": "4b14617df01be6c83ac62fdb689427f8ed56d9c1", "shasum": "" }, "require": { - "brick/varexporter": "^0.6", - "laminas/laminas-config": "^3.10.1", - "laminas/laminas-eventmanager": "^3.14.0", - "laminas/laminas-stdlib": "^3.21.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "webimpress/safe-writer": "^2.2.0" + "brick/varexporter": "^0.3.2 || ^0.4 || ^0.5 || ^0.6", + "laminas/laminas-config": "^3.7", + "laminas/laminas-eventmanager": "^3.4", + "laminas/laminas-stdlib": "^3.6", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "webimpress/safe-writer": "^1.0.2 || ^2.1" }, "conflict": { "amphp/amp": "<2.6.4", @@ -3879,9 +3954,9 @@ "amphp/socket": "^1.2.1 || ^2.3.1", "laminas/laminas-coding-standard": "~3.1.0", "laminas/laminas-loader": "^2.11", - "laminas/laminas-mvc": "^3.8.0", + "laminas/laminas-mvc": "^3.7.0", "laminas/laminas-servicemanager": "^3.23.0", - "phpunit/phpunit": "^11.5.42", + "phpunit/phpunit": "^10.5.38", "psalm/plugin-phpunit": "^0.19.5", "vimeo/psalm": "^6.13.1" }, @@ -3921,7 +3996,7 @@ "type": "community_bridge" } ], - "time": "2025-10-17T22:17:10+00:00" + "time": "2025-10-17T18:22:00+00:00" }, { "name": "laminas/laminas-mvc", @@ -4156,22 +4231,22 @@ }, { "name": "laminas/laminas-paginator", - "version": "2.22.0", + "version": "2.20.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-paginator.git", - "reference": "46e62444f467b000a9a0e3959551a29b3223d7e8" + "reference": "235b57db1f7939513465ec49f05b12228fe5391f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-paginator/zipball/46e62444f467b000a9a0e3959551a29b3223d7e8", - "reference": "46e62444f467b000a9a0e3959551a29b3223d7e8", + "url": "https://api.github.com/repos/laminas/laminas-paginator/zipball/235b57db1f7939513465ec49f05b12228fe5391f", + "reference": "235b57db1f7939513465ec49f05b12228fe5391f", "shasum": "" }, "require": { "ext-json": "*", "laminas/laminas-stdlib": "^3.10.1", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-paginator": "*" @@ -4179,12 +4254,12 @@ "require-dev": { "laminas/laminas-cache": "^3.13.0", "laminas/laminas-cache-storage-adapter-memory": "^2.4.0", - "laminas/laminas-coding-standard": "^3.1.0", + "laminas/laminas-coding-standard": "^2.5.0", "laminas/laminas-config": "^3.10.1", - "laminas/laminas-filter": "^2.42", - "laminas/laminas-servicemanager": "^3.24.0", + "laminas/laminas-filter": "^2.41", + "laminas/laminas-servicemanager": "^3.23.1", "laminas/laminas-view": "^2.43", - "phpunit/phpunit": "^11.5.42", + "phpunit/phpunit": "^10.5.58", "psalm/plugin-phpunit": "^0.19.5", "vimeo/psalm": "^6.13.1" }, @@ -4231,36 +4306,33 @@ "type": "community_bridge" } ], - "time": "2025-11-06T17:36:56+00:00" + "time": "2025-10-15T18:30:48+00:00" }, { "name": "laminas/laminas-permissions-rbac", - "version": "3.8.0", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-permissions-rbac.git", - "reference": "1a1c80b5d351f46b2391632bfc87606d8c194bed" + "reference": "0fbde38f0cc2b462856e8a5edeaa26eb97dd23be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-permissions-rbac/zipball/1a1c80b5d351f46b2391632bfc87606d8c194bed", - "reference": "1a1c80b5d351f46b2391632bfc87606d8c194bed", + "url": "https://api.github.com/repos/laminas/laminas-permissions-rbac/zipball/0fbde38f0cc2b462856e8a5edeaa26eb97dd23be", + "reference": "0fbde38f0cc2b462856e8a5edeaa26eb97dd23be", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-permissions-rbac": "*" }, "require-dev": { - "amphp/dns": "^2.4.0", - "amphp/socket": "^2.3.1", - "laminas/laminas-coding-standard": "~3.1.0", - "phpunit/phpunit": "^11.5.42", + "laminas/laminas-coding-standard": "~3.0.0", + "phpunit/phpunit": "^10.5.38", "psalm/plugin-phpunit": "^0.19.0", - "sebastian/recursion-context": "^6.0.3", - "vimeo/psalm": "^6.13.1" + "vimeo/psalm": "^5.26.1" }, "type": "library", "autoload": { @@ -4294,7 +4366,7 @@ "type": "community_bridge" } ], - "time": "2025-11-10T10:14:08+00:00" + "time": "2024-11-21T21:46:24+00:00" }, { "name": "laminas/laminas-psr7bridge", @@ -4358,23 +4430,23 @@ }, { "name": "laminas/laminas-recaptcha", - "version": "3.9.0", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-recaptcha.git", - "reference": "d8c710d6ed90f245db5ee85bd024279b35476f3f" + "reference": "ab4efc2768b1d9e90df9a49301158ec288cd48dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-recaptcha/zipball/d8c710d6ed90f245db5ee85bd024279b35476f3f", - "reference": "d8c710d6ed90f245db5ee85bd024279b35476f3f", + "url": "https://api.github.com/repos/laminas/laminas-recaptcha/zipball/ab4efc2768b1d9e90df9a49301158ec288cd48dd", + "reference": "ab4efc2768b1d9e90df9a49301158ec288cd48dd", "shasum": "" }, "require": { "ext-json": "*", "laminas/laminas-http": "^2.15", "laminas/laminas-stdlib": "^3.10.1", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zendservice-recaptcha": "*" @@ -4383,9 +4455,9 @@ "laminas/laminas-coding-standard": "~2.5.0", "laminas/laminas-config": "^3.9", "laminas/laminas-validator": "^2.30.1", - "phpunit/phpunit": "^11.5", + "phpunit/phpunit": "^9.6.15", "psalm/plugin-phpunit": "^0.19.0", - "vimeo/psalm": "^6.13" + "vimeo/psalm": "^5.19" }, "suggest": { "laminas/laminas-validator": "~2.0, if using ReCaptcha's Mailhide API" @@ -4420,26 +4492,26 @@ "type": "community_bridge" } ], - "time": "2025-12-05T10:07:10+00:00" + "time": "2024-10-24T08:57:20+00:00" }, { "name": "laminas/laminas-router", - "version": "3.16.0", + "version": "3.15.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-router.git", - "reference": "ec4b33834199bcf04c1b90b98c10f53c9e77e046" + "reference": "bce9a5b2b0d7ecdaddbd191ab06b61d73c5e02a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-router/zipball/ec4b33834199bcf04c1b90b98c10f53c9e77e046", - "reference": "ec4b33834199bcf04c1b90b98c10f53c9e77e046", + "url": "https://api.github.com/repos/laminas/laminas-router/zipball/bce9a5b2b0d7ecdaddbd191ab06b61d73c5e02a5", + "reference": "bce9a5b2b0d7ecdaddbd191ab06b61d73c5e02a5", "shasum": "" }, "require": { "laminas/laminas-servicemanager": "^3.14.0", "laminas/laminas-stdlib": "^3.10.1", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-router": "*" @@ -4447,10 +4519,10 @@ "require-dev": { "laminas/laminas-coding-standard": "~3.1.0", "laminas/laminas-http": "^2.22", - "laminas/laminas-i18n": "^2.31.0", - "phpunit/phpunit": "^11.5.43", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "laminas/laminas-i18n": "^2.30.0", + "phpunit/phpunit": "^10.5.58", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.26.1" }, "suggest": { "laminas/laminas-i18n": "^2.15.0 if defining translatable HTTP path segments" @@ -4491,25 +4563,25 @@ "type": "community_bridge" } ], - "time": "2025-11-09T16:54:18+00:00" + "time": "2025-11-09T15:44:07+00:00" }, { "name": "laminas/laminas-servicemanager", - "version": "3.24.0", + "version": "3.23.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-servicemanager.git", - "reference": "b172a0df568bf37ebdfb3658263156eefe3c1e8c" + "reference": "06594db3a644447521eace9b5efdb12dc8446a33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/b172a0df568bf37ebdfb3658263156eefe3c1e8c", - "reference": "b172a0df568bf37ebdfb3658263156eefe3c1e8c", + "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/06594db3a644447521eace9b5efdb12dc8446a33", + "reference": "06594db3a644447521eace9b5efdb12dc8446a33", "shasum": "" }, "require": { "laminas/laminas-stdlib": "^3.19", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "psr/container": "^1.0" }, "conflict": { @@ -4532,7 +4604,7 @@ "laminas/laminas-container-config-test": "^0.8", "mikey179/vfsstream": "^1.6.12", "phpbench/phpbench": "^1.4.1", - "phpunit/phpunit": "^10.5.58", + "phpunit/phpunit": "^10.5.51", "psalm/plugin-phpunit": "^0.18.4", "vimeo/psalm": "^5.26.1" }, @@ -4581,46 +4653,44 @@ "type": "community_bridge" } ], - "time": "2025-10-14T09:03:51+00:00" + "time": "2025-08-12T08:44:02+00:00" }, { "name": "laminas/laminas-session", - "version": "2.26.0", + "version": "2.25.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-session.git", - "reference": "1c4f1a80ccc6403fff85bb13fb928da79dd1636e" + "reference": "17b5fd6aa9889dc8362c26d4c7500c93ff4347cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-session/zipball/1c4f1a80ccc6403fff85bb13fb928da79dd1636e", - "reference": "1c4f1a80ccc6403fff85bb13fb928da79dd1636e", + "url": "https://api.github.com/repos/laminas/laminas-session/zipball/17b5fd6aa9889dc8362c26d4c7500c93ff4347cb", + "reference": "17b5fd6aa9889dc8362c26d4c7500c93ff4347cb", "shasum": "" }, "require": { - "laminas/laminas-eventmanager": "^3.14.0", - "laminas/laminas-servicemanager": "^3.23.1", - "laminas/laminas-stdlib": "^3.20.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "laminas/laminas-eventmanager": "^3.12", + "laminas/laminas-servicemanager": "^3.22", + "laminas/laminas-stdlib": "^3.18", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "amphp/amp": "<2.6.4", "zendframework/zend-session": "*" }, "require-dev": { - "amphp/dns": "^2.4.0", - "amphp/socket": "^2.3.1", "ext-xdebug": "*", - "laminas/laminas-cache": "^3.13.0", - "laminas/laminas-cache-storage-adapter-memory": "^2.4", + "laminas/laminas-cache": "^3.12.2", + "laminas/laminas-cache-storage-adapter-memory": "^2.3", "laminas/laminas-coding-standard": "~3.1.0", "laminas/laminas-db": "^2.20.0", - "laminas/laminas-http": "^2.22", - "laminas/laminas-validator": "^2.64.4", - "mongodb/mongodb": "~2.1.2", - "phpunit/phpunit": "^11.5.42", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "laminas/laminas-http": "^2.20", + "laminas/laminas-validator": "^2.64.1", + "mongodb/mongodb": "~2.1.0", + "phpunit/phpunit": "^10.5.38", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.26.1" }, "suggest": { "laminas/laminas-cache": "Laminas\\Cache component", @@ -4666,34 +4736,34 @@ "type": "community_bridge" } ], - "time": "2025-11-14T12:52:38+00:00" + "time": "2025-10-11T09:26:06+00:00" }, { "name": "laminas/laminas-stdlib", - "version": "3.21.0", + "version": "3.20.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "b1c81514cfe158aadf724c42b34d3d0a8164c096" + "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/b1c81514cfe158aadf724c42b34d3d0a8164c096", - "reference": "b1c81514cfe158aadf724c42b34d3d0a8164c096", + "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/8974a1213be42c3e2f70b2c27b17f910291ab2f4", + "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-stdlib": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "^3.1.0", - "phpbench/phpbench": "^1.4.1", - "phpunit/phpunit": "^11.5.42", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "laminas/laminas-coding-standard": "^3.0", + "phpbench/phpbench": "^1.3.1", + "phpunit/phpunit": "^10.5.38", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.26.1" }, "type": "library", "autoload": { @@ -4725,26 +4795,26 @@ "type": "community_bridge" } ], - "time": "2025-10-11T18:13:12+00:00" + "time": "2024-10-29T13:46:07+00:00" }, { "name": "laminas/laminas-stratigility", - "version": "3.14.0", + "version": "3.13.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stratigility.git", - "reference": "d23d128a22f79a67e1f9682df4c51719e3553c9d" + "reference": "3df57528b5c8e9d958515c51006825a83f76d62b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stratigility/zipball/d23d128a22f79a67e1f9682df4c51719e3553c9d", - "reference": "d23d128a22f79a67e1f9682df4c51719e3553c9d", + "url": "https://api.github.com/repos/laminas/laminas-stratigility/zipball/3df57528b5c8e9d958515c51006825a83f76d62b", + "reference": "3df57528b5c8e9d958515c51006825a83f76d62b", "shasum": "" }, "require": { "fig/http-message-util": "^1.1", "laminas/laminas-escaper": "^2.10.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "psr/http-message": "^1.0 || ^2.0", "psr/http-server-middleware": "^1.0.2" }, @@ -4752,9 +4822,9 @@ "zendframework/zend-stratigility": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "^3.1.0", - "laminas/laminas-diactoros": "^2.25 || ^3.8.0", - "phpunit/phpunit": "^10.5.58", + "laminas/laminas-coding-standard": "~2.5.0", + "laminas/laminas-diactoros": "^2.25 || ^3.5.0", + "phpunit/phpunit": "^10.5.37", "psalm/plugin-phpunit": "^0.19.0", "vimeo/psalm": "^5.26.1" }, @@ -4804,7 +4874,7 @@ "type": "community_bridge" } ], - "time": "2025-11-12T05:23:21+00:00" + "time": "2024-10-28T11:28:41+00:00" }, { "name": "laminas/laminas-text", @@ -4869,24 +4939,24 @@ }, { "name": "laminas/laminas-translator", - "version": "1.2.0", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-translator.git", - "reference": "c4c1637ea56afe812f1af3212656fd6f9c02c551" + "reference": "12897e710e21413c1f93fc38fe9dead6b51c5218" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-translator/zipball/c4c1637ea56afe812f1af3212656fd6f9c02c551", - "reference": "c4c1637ea56afe812f1af3212656fd6f9c02c551", + "url": "https://api.github.com/repos/laminas/laminas-translator/zipball/12897e710e21413c1f93fc38fe9dead6b51c5218", + "reference": "12897e710e21413c1f93fc38fe9dead6b51c5218", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "laminas/laminas-coding-standard": "~3.1.0", - "vimeo/psalm": "^6.13.1" + "laminas/laminas-coding-standard": "~3.0.0", + "vimeo/psalm": "^5.24.0" }, "type": "library", "autoload": { @@ -4918,33 +4988,33 @@ "type": "community_bridge" } ], - "time": "2025-10-14T20:58:42+00:00" + "time": "2024-10-21T15:33:01+00:00" }, { "name": "laminas/laminas-uri", - "version": "2.14.0", + "version": "2.13.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-uri.git", - "reference": "e804288f4540988903dc0ede386ce5eec87198df" + "reference": "de53600ae8153b3605bb6edce8aeeef524eaafba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-uri/zipball/e804288f4540988903dc0ede386ce5eec87198df", - "reference": "e804288f4540988903dc0ede386ce5eec87198df", + "url": "https://api.github.com/repos/laminas/laminas-uri/zipball/de53600ae8153b3605bb6edce8aeeef524eaafba", + "reference": "de53600ae8153b3605bb6edce8aeeef524eaafba", "shasum": "" }, "require": { "laminas/laminas-escaper": "^2.9", "laminas/laminas-validator": "^2.39 || ^3.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-uri": "*" }, "require-dev": { "laminas/laminas-coding-standard": "~2.4.0", - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^9.6.20" }, "type": "library", "autoload": { @@ -4976,26 +5046,26 @@ "type": "community_bridge" } ], - "time": "2025-12-05T10:02:11+00:00" + "time": "2024-12-03T12:27:51+00:00" }, { "name": "laminas/laminas-validator", - "version": "2.65.0", + "version": "2.64.4", "source": { "type": "git", "url": "https://github.com/laminas/laminas-validator.git", - "reference": "f0767ca83e0dd91a6f8ccdd4f0887eb132c0ea49" + "reference": "e2e6631f599a9b0db1e23adb633c09a2f0c68bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/f0767ca83e0dd91a6f8ccdd4f0887eb132c0ea49", - "reference": "f0767ca83e0dd91a6f8ccdd4f0887eb132c0ea49", + "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/e2e6631f599a9b0db1e23adb633c09a2f0c68bed", + "reference": "e2e6631f599a9b0db1e23adb633c09a2f0c68bed", "shasum": "" }, "require": { "laminas/laminas-servicemanager": "^3.21.0", "laminas/laminas-stdlib": "^3.19", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "psr/http-message": "^1.0.1 || ^2.0.0" }, "conflict": { @@ -5004,15 +5074,15 @@ "require-dev": { "laminas/laminas-coding-standard": "^2.5", "laminas/laminas-db": "^2.20", - "laminas/laminas-filter": "^2.41.0", - "laminas/laminas-i18n": "^2.30.0", - "laminas/laminas-session": "^2.25.1", - "laminas/laminas-uri": "^2.13.0", - "phpunit/phpunit": "^10.5.58", + "laminas/laminas-filter": "^2.35.2", + "laminas/laminas-i18n": "^2.26.0", + "laminas/laminas-session": "^2.20", + "laminas/laminas-uri": "^2.11.0", + "phpunit/phpunit": "^10.5.20", "psalm/plugin-phpunit": "^0.19.0", "psr/http-client": "^1.0.3", "psr/http-factory": "^1.1.0", - "vimeo/psalm": "^5.26.1" + "vimeo/psalm": "^5.24.0" }, "suggest": { "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", @@ -5060,7 +5130,7 @@ "type": "community_bridge" } ], - "time": "2025-10-13T14:40:30+00:00" + "time": "2025-06-16T14:38:00+00:00" }, { "name": "laminas/laminas-view", @@ -5166,16 +5236,16 @@ }, { "name": "monarc/core", - "version": "v2.13.3-p1", + "version": "v2.13.4", "source": { "type": "git", "url": "https://github.com/monarc-project/zm-core.git", - "reference": "8ec9b355456746d838d1010aac033e0af9c2e38f" + "reference": "d42c6621fc68c916d010760657b907e27e0ab8d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/monarc-project/zm-core/zipball/8ec9b355456746d838d1010aac033e0af9c2e38f", - "reference": "8ec9b355456746d838d1010aac033e0af9c2e38f", + "url": "https://api.github.com/repos/monarc-project/zm-core/zipball/d42c6621fc68c916d010760657b907e27e0ab8d0", + "reference": "d42c6621fc68c916d010760657b907e27e0ab8d0", "shasum": "" }, "require": { @@ -5183,6 +5253,7 @@ "ext-intl": "*", "ext-json": "*", "ext-openssl": "*", + "friendsofphp/proxy-manager-lts": "^1.0", "laminas/laminas-dependency-plugin": "^2.0", "laminas/laminas-di": "^3.1", "laminas/laminas-filter": "^2.9", @@ -5194,7 +5265,6 @@ "laminas/laminas-mvc": "^3.1", "laminas/laminas-mvc-i18n": "^1.7", "laminas/laminas-mvc-middleware": "^2.2", - "ocramius/proxy-manager": "^2.13", "php": "^8.0", "ramsey/uuid-doctrine": "^1.5", "robmorgan/phinx": "^0.13.4", @@ -5255,9 +5325,9 @@ "description": "Core for monarc/monarc application", "support": { "issues": "https://github.com/monarc-project/zm-core/issues", - "source": "https://github.com/monarc-project/zm-core/tree/v2.13.3-p1" + "source": "https://github.com/monarc-project/zm-core/tree/v2.13.4" }, - "time": "2025-05-20T14:55:52+00:00" + "time": "2026-01-21T10:43:32+00:00" }, { "name": "monarc/frontoffice", @@ -5415,87 +5485,6 @@ }, "time": "2025-12-06T11:56:16+00:00" }, - { - "name": "ocramius/proxy-manager", - "version": "2.14.1", - "source": { - "type": "git", - "url": "https://github.com/Ocramius/ProxyManager.git", - "reference": "3990d60ef79001badbab4927a6a811682274a0d1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/3990d60ef79001badbab4927a6a811682274a0d1", - "reference": "3990d60ef79001badbab4927a6a811682274a0d1", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.1.0", - "laminas/laminas-code": "^4.4.2", - "php": "~8.0.0", - "webimpress/safe-writer": "^2.2.0" - }, - "conflict": { - "thecodingmachine/safe": "<1.3.3" - }, - "require-dev": { - "codelicia/xulieta": "^0.1.6", - "doctrine/coding-standard": "^9.0.0", - "ext-phar": "*", - "phpbench/phpbench": "^1.0.3", - "phpunit/phpunit": "^9.5.6", - "roave/infection-static-analysis-plugin": "^1.8", - "squizlabs/php_codesniffer": "^3.6.0", - "vimeo/psalm": "^4.8.1" - }, - "suggest": { - "laminas/laminas-json": "To have the JsonRpc adapter (Remote Object feature)", - "laminas/laminas-soap": "To have the Soap adapter (Remote Object feature)", - "laminas/laminas-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)", - "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects" - }, - "type": "library", - "autoload": { - "psr-4": { - "ProxyManager\\": "src/ProxyManager" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", - "homepage": "https://github.com/Ocramius/ProxyManager", - "keywords": [ - "aop", - "lazy loading", - "proxy", - "proxy pattern", - "service proxies" - ], - "support": { - "issues": "https://github.com/Ocramius/ProxyManager/issues", - "source": "https://github.com/Ocramius/ProxyManager/tree/2.14.1" - }, - "funding": [ - { - "url": "https://github.com/Ocramius", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ocramius/proxy-manager", - "type": "tidelift" - } - ], - "time": "2022-03-05T18:43:14+00:00" - }, { "name": "phpoffice/phpword", "version": "0.18.3", @@ -6743,25 +6732,25 @@ }, { "name": "symfony/filesystem", - "version": "v7.4.0", + "version": "v6.4.30", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a" + "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/441c6b69f7222aadae7cbf5df588496d5ee37789", + "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^6.4|^7.0|^8.0" + "symfony/process": "^5.4|^6.4|^7.0" }, "type": "library", "autoload": { @@ -6789,7 +6778,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.0" + "source": "https://github.com/symfony/filesystem/tree/v6.4.30" }, "funding": [ { @@ -6809,7 +6798,7 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2025-11-26T14:43:45+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8512,12 +8501,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "e5034c4df32edeafb119b2c1e2b58876d0286ea8" + "reference": "a2b02a3f02794e178258157c73431946c7eb9af3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/e5034c4df32edeafb119b2c1e2b58876d0286ea8", - "reference": "e5034c4df32edeafb119b2c1e2b58876d0286ea8", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/a2b02a3f02794e178258157c73431946c7eb9af3", + "reference": "a2b02a3f02794e178258157c73431946c7eb9af3", "shasum": "" }, "conflict": { @@ -8532,12 +8521,14 @@ "aimeos/ai-cms-grapesjs": ">=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.9|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.10.8|>=2025.04.1,<2025.10.2", "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", + "aimeos/aimeos-laravel": "==2021.10", "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", "airesvsg/acf-to-rest-api": "<=3.1", "akaunting/akaunting": "<2.1.13", "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", - "alextselegidis/easyappointments": "<1.5.2.0-beta1", + "alextselegidis/easyappointments": "<=1.5.2", "alexusmai/laravel-file-manager": "<=3.3.1", + "algolia/algoliasearch-magento-2": "<=3.16.1|>=3.17.0.0-beta1,<=3.17.1", "alt-design/alt-redirect": "<1.6.4", "altcha-org/altcha": "<1.3.1", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", @@ -8570,7 +8561,7 @@ "automad/automad": "<2.0.0.0-alpha5", "automattic/jetpack": "<9.8", "awesome-support/awesome-support": "<=6.0.7", - "aws/aws-sdk-php": "<3.288.1", + "aws/aws-sdk-php": "<3.368", "azuracast/azuracast": "<=0.23.1", "b13/seo_basics": "<0.8.2", "backdrop/backdrop": "<=1.32", @@ -8578,7 +8569,7 @@ "backpack/filemanager": "<2.0.2|>=3,<3.0.9", "bacula-web/bacula-web": "<9.7.1", "badaso/core": "<=2.9.11", - "bagisto/bagisto": "<=2.3.7", + "bagisto/bagisto": "<2.3.10", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", "barryvdh/laravel-translation-manager": "<0.6.8", @@ -8610,7 +8601,8 @@ "bvbmedia/multishop": "<2.0.39", "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cadmium-org/cadmium-cms": "<=0.4.9", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.2.10,<5.2.12|==5.3", "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", "cardgate/magento2": "<2.0.33", "cardgate/woocommerce": "<=3.1.15", @@ -8639,7 +8631,7 @@ "codingms/modules": "<4.3.11|>=5,<5.7.4|>=6,<6.4.2|>=7,<7.5.5", "commerceteam/commerce": ">=0.9.6,<0.9.9", "components/jquery": ">=1.0.3,<3.5", - "composer/composer": "<1.10.27|>=2,<2.2.24|>=2.3,<2.7.7", + "composer/composer": "<1.10.27|>=2,<2.2.26|>=2.3,<2.9.3", "concrete5/concrete5": "<9.4.3", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", @@ -8649,11 +8641,12 @@ "contao/core-bundle": "<4.13.57|>=5,<5.3.42|>=5.4,<5.6.5", "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", "contao/managed-edition": "<=1.5", + "coreshop/core-shop": "<=4.1.7", "corveda/phpsandbox": "<1.3.5", "cosenary/instagram": "<=2.3", "couleurcitron/tarteaucitron-wp": "<0.3", - "craftcms/cms": "<=4.16.5|>=5,<=5.8.6", - "croogo/croogo": "<4", + "craftcms/cms": "<=4.16.16|>=5,<=5.8.20", + "croogo/croogo": "<=4.0.7", "cuyz/valinor": "<0.12", "czim/file-handling": "<1.5|>=2,<2.3", "czproject/git-php": "<4.0.3", @@ -8700,7 +8693,7 @@ "drupal/commerce_alphabank_redirect": "<1.0.3", "drupal/commerce_eurobank_redirect": "<2.1.1", "drupal/config_split": "<1.10|>=2,<2.0.2", - "drupal/core": ">=6,<6.38|>=7,<7.102|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", + "drupal/core": ">=6,<6.38|>=7,<7.103|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", "drupal/core-recommended": ">=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", "drupal/currency": "<3.5", "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", @@ -8764,7 +8757,7 @@ "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", "ezyang/htmlpurifier": "<=4.2", "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", - "facturascripts/facturascripts": "<=2022.08", + "facturascripts/facturascripts": "<=2025.4|==2025.11|==2025.41|==2025.43", "fastly/magento2": "<1.2.26", "feehi/cms": "<=2.1.1", "feehi/feehicms": "<=2.1.1", @@ -8815,7 +8808,7 @@ "geshi/geshi": "<=1.0.9.1", "getformwork/formwork": "<2.2", "getgrav/grav": "<1.11.0.0-beta1", - "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1|>=5,<5.1.4", + "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1|>=5,<=5.2.1", "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", "getkirby/panel": "<2.5.14", "getkirby/starterkit": "<=3.7.0.2", @@ -8905,7 +8898,7 @@ "kelvinmo/simplexrd": "<3.1.1", "kevinpapst/kimai2": "<1.16.7", "khodakhah/nodcms": "<=3", - "kimai/kimai": "<=2.20.1", + "kimai/kimai": "<2.46", "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", "klaviyo/magento2-extension": ">=1,<3", "knplabs/knp-snappy": "<=1.4.2", @@ -8936,11 +8929,12 @@ "leantime/leantime": "<3.3", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", "libreform/libreform": ">=2,<=2.0.8", - "librenms/librenms": "<25.11", + "librenms/librenms": "<25.12", "liftkit/database": "<2.13.2", "lightsaml/lightsaml": "<1.3.5", "limesurvey/limesurvey": "<6.5.12", "livehelperchat/livehelperchat": "<=3.91", + "livewire-filemanager/filemanager": "<=1.0.4", "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.6.4", "livewire/volt": "<1.7", "lms/routes": "<2.1.1", @@ -9044,7 +9038,7 @@ "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", "october/october": "<3.7.5", "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<3.7.5", + "october/system": "<=3.7.12|>=4,<=4.0.11", "oliverklee/phpunit": "<3.5.15", "omeka/omeka-s": "<4.0.3", "onelogin/php-saml": "<2.21.1|>=3,<3.8.1|>=4,<4.3.1", @@ -9071,6 +9065,7 @@ "pagekit/pagekit": "<=1.0.18", "paragonie/ecc": "<2.0.1", "paragonie/random_compat": "<2", + "paragonie/sodium_compat": "<1.24|>=2,<2.5", "passbolt/passbolt_api": "<4.6.2", "paypal/adaptivepayments-sdk-php": "<=3.9.2", "paypal/invoice-sdk-php": "<=3.9", @@ -9107,14 +9102,15 @@ "phpxmlrpc/extras": "<0.6.1", "phpxmlrpc/phpxmlrpc": "<4.9.2", "pi/pi": "<=2.5", - "pimcore/admin-ui-classic-bundle": "<1.7.6", + "pimcore/admin-ui-classic-bundle": "<=1.7.15|>=2.0.0.0-RC1-dev,<=2.2.2", "pimcore/customer-management-framework-bundle": "<4.2.1", "pimcore/data-hub": "<1.2.4", "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", "pimcore/demo": "<10.3", "pimcore/ecommerce-framework-bundle": "<1.0.10", "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<11.5.4", + "pimcore/pimcore": "<=11.5.13|>=12.0.0.0-RC1-dev,<12.3.1", + "pimcore/web2print-tools-bundle": "<=5.2.1|>=6.0.0.0-RC1-dev,<=6.1", "piwik/piwik": "<1.11", "pixelfed/pixelfed": "<0.12.5", "plotly/plotly.js": "<2.25.2", @@ -9138,7 +9134,7 @@ "processwire/processwire": "<=3.0.246", "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", "propel/propel1": ">=1,<=1.7.1", - "pterodactyl/panel": "<=1.11.10", + "pterodactyl/panel": "<1.12", "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", "ptrofimov/beanstalk_console": "<1.7.14", "pubnub/pubnub": "<6.1", @@ -9156,7 +9152,7 @@ "rap2hpoutre/laravel-log-viewer": "<0.13", "react/http": ">=0.7,<1.9", "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<5.20.1", + "redaxo/source": "<=5.20.1", "remdex/livehelperchat": "<4.29", "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", "reportico-web/reportico": "<=8.1", @@ -9178,10 +9174,10 @@ "setasign/fpdi": "<2.6.4", "sfroemken/url_redirect": "<=1.2.1", "sheng/yiicms": "<1.2.1", - "shopware/core": "<6.6.10.9-dev|>=6.7,<6.7.4.1-dev", + "shopware/core": "<6.6.10.9-dev|>=6.7,<6.7.6.1-dev", "shopware/platform": "<6.6.10.7-dev|>=6.7,<6.7.3.1-dev", "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", + "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.6.1-dev", "shopware/storefront": "<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", "shopxo/shopxo": "<=6.4", "showdoc/showdoc": "<2.10.4", @@ -9226,7 +9222,7 @@ "snipe/snipe-it": "<=8.3.4", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", - "solspace/craft-freeform": ">=5,<5.10.16", + "solspace/craft-freeform": "<4.1.29|>=5,<5.10.16", "soosyze/soosyze": "<=2", "spatie/browsershot": "<5.0.5", "spatie/image-optimizer": "<1.7.3", @@ -9315,7 +9311,7 @@ "thelia/thelia": ">=2.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<6.0.8", - "thorsten/phpmyfaq": "<=4.0.13", + "thorsten/phpmyfaq": "<4.0.16|>=4.1.0.0-alpha,<=4.1.0.0-beta2", "tikiwiki/tiki-manager": "<=17.1", "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", "tinymce/tinymce": "<7.2", @@ -9334,10 +9330,10 @@ "twbs/bootstrap": "<3.4.1|>=4,<4.3.1", "twig/twig": "<3.11.2|>=3.12,<3.14.1|>=3.16,<3.19", "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", - "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-belog": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", "typo3/cms-beuser": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-dashboard": ">=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", "typo3/cms-extensionmanager": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", @@ -9349,7 +9345,8 @@ "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8|==13.4.2", "typo3/cms-lowlevel": ">=11,<=11.5.41", "typo3/cms-recordlist": ">=11,<11.5.48", - "typo3/cms-recycler": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-recycler": ">=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-redirects": ">=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", "typo3/cms-scheduler": ">=11,<=11.5.41", "typo3/cms-setup": ">=9,<=9.5.50|>=10,<=10.4.49|>=11,<=11.5.43|>=12,<=12.4.30|>=13,<=13.4.11", @@ -9431,7 +9428,7 @@ "yiisoft/yii2-redis": "<2.0.20", "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", "yoast-seo-for-typo3/yoast_seo": "<7.2.3", - "yourls/yourls": "<=1.8.2", + "yourls/yourls": "<=1.10.2", "yuan1994/tpadmin": "<=1.3.12", "yungifez/skuul": "<=2.6.5", "z-push/z-push-dev": "<2.7.6", @@ -9509,7 +9506,7 @@ "type": "tidelift" } ], - "time": "2025-12-17T21:06:23+00:00" + "time": "2026-01-20T19:24:42+00:00" }, { "name": "sebastian/cli-parser", @@ -10727,6 +10724,9 @@ "ext-bcmath": "*", "ext-openssl": "*" }, - "platform-dev": [], - "plugin-api-version": "2.6.0" + "platform-dev": {}, + "platform-overrides": { + "php": "8.1.0" + }, + "plugin-api-version": "2.9.0" } diff --git a/scripts/update-all.sh b/scripts/update-all.sh index e7a1fab..605b667 100755 --- a/scripts/update-all.sh +++ b/scripts/update-all.sh @@ -64,7 +64,7 @@ if [[ $? -eq 1 ]]; then fi if [[ $isDevEnv -eq 0 ]]; then - composer ins -o --no-dev --no-cache --ignore-platform-req=php + composer ins -o --no-dev --no-cache else composer ins --ignore-platform-req=php fi diff --git a/vagrant/bootstrap.sh b/vagrant/bootstrap.sh index de03324..b98c7aa 100644 --- a/vagrant/bootstrap.sh +++ b/vagrant/bootstrap.sh @@ -145,7 +145,7 @@ cd $PATH_TO_MONARC git config core.fileMode false echo -e "\n--- Installing the dependencies… ---\n" -composer ins --ignore-platform-req=php +composer ins # Make modules symlinks.