diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000000..3e71214f8c8db --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,70 @@ +# Start from the official PHP 8.2 image with Apache +FROM php:8.2-apache-bookworm + +# Install system dependencies, Node.js, Composer, and Cypress dependencies +RUN apt-get update && apt-get install -y \ + # System tools and git + git \ + unzip \ + curl \ + sudo \ + # PHP extensions dependencies + libpng-dev \ + libonig-dev \ + libxml2-dev \ + libzip-dev \ + # MySQL client AND server + default-mysql-client \ + default-mysql-server \ + # Cypress dependencies + xvfb \ + libgtk2.0-0 \ + libgtk-3-0 \ + libgbm-dev \ + libnotify-dev \ + libnss3 \ + libxss1 \ + libasound2 \ + libxtst6 \ + xauth \ + libldap2-dev \ + libgd-dev \ + && \ + # Install the required PHP extensions for Zip and MySQL + docker-php-ext-install zip mysqli gd ldap && \ + # Install Node.js (LTS version) + curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \ + apt-get install -y nodejs && \ + # Install Composer globally + curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ + # Install Xdebug + pecl install xdebug && \ + # Clean up apt cache to reduce image size + apt-get clean && rm -rf /var/lib/apt/lists/* + +# After installing everything +RUN sed -i 's|/var/www/html|/workspaces/joomla-cms|g' /etc/apache2/sites-available/000-default.conf \ + && sed -i 's|/var/www/html|/workspaces/joomla-cms|g' /etc/apache2/apache2.conf + +# Enable Apache's rewrite module and set the ServerName to prevent warnings +RUN a2enmod rewrite \ + && echo "ServerName localhost" >> /etc/apache2/apache2.conf + +RUN apt-get update && apt-get install -y ssl-cert && \ + a2enmod ssl && \ + a2ensite 000-default && \ + a2ensite default-ssl && \ + sed -i 's|/var/www/html|/workspaces/joomla-cms|g' /etc/apache2/sites-available/default-ssl.conf && \ + echo '\n Options Indexes FollowSymLinks\n AllowOverride All\n Require all granted\n' >> /etc/apache2/sites-available/default-ssl.conf + +# Create a custom PHP configuration file to enable file uploads and a log directory +RUN mkdir -p /var/log/ && \ + touch /var/log/php_errors.log && \ + chown -R www-data:www-data /var/log/ && \ + chmod 766 /var/log/php_errors.log && \ + echo "upload_tmp_dir = /tmp" > /usr/local/etc/php/conf.d/custom-php.ini && \ + echo "post_max_size = 64M" >> /usr/local/etc/php/conf.d/custom-php.ini && \ + echo "upload_max_filesize = 64M" >> /usr/local/etc/php/conf.d/custom-php.ini && \ + echo "log_errors = On" >> /usr/local/etc/php/conf.d/custom-php.ini && \ + echo "error_log = /var/log/php_errors.log" >> /usr/local/etc/php/conf.d/custom-php.ini && \ + echo "error_reporting = E_ALL" >> /usr/local/etc/php/conf.d/custom-php.ini diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000000..9a93f372e6177 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,44 @@ +{ + "name": "Joomla Dev Environment", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspaces/joomla-cms", + "features": { + "ghcr.io/devcontainers/features/desktop-lite:1": {} + }, + "portsAttributes": { + "443" : { + "label": "Web Server (Joomla & phpmyadmin)", + "onAutoForward": "silent" + }, + "6080": { + "label": "Cypress GUI", + "onAutoForward": "silent" + } + }, + "postCreateCommand": "bash ./.devcontainer/post-create.sh", + "customizations": { + "vscode": { + "extensions": [ + "xdebug.php-debug", + "bmewburn.vscode-intelephense-client", + "esbenp.prettier-vscode" + ], + "settings": { + "launch": { + "version": "0.2.0", + "configurations": [ + { + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9003, + "log": false + } + ] + } + } + } + }, + "remoteUser": "root" +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 0000000000000..0d47fdd66174a --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,29 @@ +services: + app: + build: + context: . + dockerfile: Dockerfile + volumes: + - ..:/workspaces/joomla-cms:cached + - ./xdebug.ini:/usr/local/etc/php/conf.d/99-xdebug.ini + ports: + - "80:80" + - "443:443" + - "3306:3306" + - "6080:6080" + command: sleep infinity + + mysql: + image: mysql:8.0 + command: --default-authentication-plugin=mysql_native_password + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: test_joomla + MYSQL_USER: joomla_ut + MYSQL_PASSWORD: joomla_ut + volumes: + - "mysql-data:/var/lib/mysql" + +volumes: + mysql-data: diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100644 index 0000000000000..804916075b835 --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,158 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status. +set -e + +echo "--- Starting Joomla Core Post-Creation Setup ---" + +# Configuration variables +DB_NAME="test_joomla" +DB_USER="joomla_ut" +DB_PASS="joomla_ut" +ADMIN_USER="ci-admin" +ADMIN_REAL_NAME="jane doe" +ADMIN_PASS="joomla-17082005" +ADMIN_EMAIL="admin@example.com" +JOOMLA_ROOT="/workspaces/joomla-cms" + +# Allow git commands to run safely in the container +git config --global --add safe.directory $JOOMLA_ROOT + +# --- 1. Wait for MariaDB Service --- +echo "--> Waiting for MariaDB to become available..." +while ! mysqladmin ping -h"mysql" --silent; do + sleep 1 +done +echo "✅ MariaDB is ready." + +# --- 2. Install Core Dependencies --- +echo "--> Installing Composer and NPM dependencies..." +composer install +npm install +echo "✅ Dependencies installed." + +# --- 3. Install Joomla from Repository Source --- +echo "--> Installing Joomla using the local repository source..." +rm -f configuration.php +php installation/joomla.php install \ + --site-name="Joomla CMS Test" \ + --admin-user="$ADMIN_REAL_NAME" \ + --admin-username="$ADMIN_USER" \ + --admin-password="$ADMIN_PASS" \ + --admin-email="$ADMIN_EMAIL" \ + --db-type="mysqli" \ + --db-host="mysql" \ + --db-name="$DB_NAME" \ + --db-user="$DB_USER" \ + --db-pass="$DB_PASS" \ + --db-prefix="jos_" \ + --db-encryption="0" \ + --public-folder="" +echo "✅ Joomla installed." + +# --- 4. Configure Joomla for Development --- +echo "--> Applying development settings..." +# Enable debug mode and maximum error reporting for easier troubleshooting. +php cli/joomla.php config:set error_reporting=maximum +echo "✅ Development settings applied." + +# --- 5. Install and Configure phpMyAdmin --- +PMA_ROOT="${JOOMLA_ROOT}/phpmyadmin" +echo "--> Downloading phpMyAdmin into $PMA_ROOT..." +PMA_VERSION=5.2.2 +mkdir -p $PMA_ROOT +curl -o /tmp/phpmyadmin.tar.gz https://files.phpmyadmin.net/phpMyAdmin/${PMA_VERSION}/phpMyAdmin-${PMA_VERSION}-all-languages.tar.gz +tar xf /tmp/phpmyadmin.tar.gz --strip-components=1 -C $PMA_ROOT +rm /tmp/phpmyadmin.tar.gz +cp $PMA_ROOT/config.sample.inc.php $PMA_ROOT/config.inc.php +sed -i "/\['AllowNoPassword'\] = false/a \$cfg['Servers'][\$i]['host'] = 'mysql';" $PMA_ROOT/config.inc.php + +# --- 6. Apply Codespaces Host Fix --- +# This ensures Joomla generates correct URLs when accessed through the forwarded port. +echo "--> Applying Codespaces URL fix..." +cat > "${JOOMLA_ROOT}/fix.php" << 'EOF' + Ignoring local changes..." +# For TRACKED files, tell Git to stop watching them for changes +git update-index --assume-unchanged "index.php" +git update-index --assume-unchanged "administrator/index.php" +git update-index --assume-unchanged "package-lock.json" +git update-index --assume-unchanged "tests/System/integration/install/Installation.cy.js" +git update-index --assume-unchanged "tests/System/support/commands/config.mjs" + +# For NEW UNTRACKED files, add them to the local exclude file +echo "cypress.config.js" >> ".git/info/exclude" +echo "fix.php" >> ".git/info/exclude" +echo "phpmyadmin" >> ".git/info/exclude" +echo "codespace-details.txt" >> ".git/info/exclude" + +# --- 7. Finalize Permissions and Testing Tools --- +echo "--> Setting up file permissions and Cypress..." +sed -i \ + -e "/\/\/ If exists, delete PHP configuration file to force a new installation/d" \ + -e "/cy.task('deleteRelativePath', 'configuration.php');/d" \ + -e "/cy.installJoomla(config);/d" \ + tests/System/integration/install/Installation.cy.js +sed -i "s/return cy.task('writeRelativeFile', { path: 'configuration.php', content });/return cy.task('writeRelativeFile', { path: 'configuration.php', content, mode: 0o775 });/" tests/System/support/commands/config.mjs + +# Ensure Cypress is executable and owned by the web server user +chmod +x ./node_modules/.bin/cypress +cp cypress.config.dist.mjs cypress.config.js +npx cypress install +sed -i -e "s|baseUrl:.*|baseUrl: 'https://localhost',|" -e "s/db_host: 'localhost'/db_host: 'mysql'/g" -e "s/db_user: 'root'/db_user: 'joomla_ut'/g" -e "s/db_password: ''/db_password: 'joomla_ut'/g" cypress.config.js + +# Restart Apache to apply all changes +echo ' + AllowOverride All + Require all granted +' | sudo tee -a /etc/apache2/apache2.conf +service apache2 restart + +# Set the group to www-data and enforce group permissions +echo "--> Applying final group ownership and permissions..." +chgrp -R www-data $JOOMLA_ROOT +chmod -R g+rws $JOOMLA_ROOT + +echo "✅ Environment finalized." + +# --- 8. Display Setup Details --- +# Save the details to a file for easy reference. +DETAILS_FILE="${JOOMLA_ROOT}/codespace-details.txt" +{ + echo "" + echo "---" + echo "🚀 Joomla Core development environment is ready! 🚀" + echo "" + echo "This information has been saved to codespace-details.txt" + echo "" + echo "Joomla Admin Login:" + echo " URL: Open the 'Ports' tab, find the 'Web Server' (443), and click the Globe icon. Then add /administrator" + echo " Username: $ADMIN_USER" + echo " Password: $ADMIN_PASS" + echo "" + echo "phpMyAdmin Login:" + echo " URL: Open the 'Web Server' port and add /phpmyadmin" + echo " Username: $DB_USER" + echo " Password: $DB_PASS" + echo "" + echo "Cypress E2E Testing:" + echo " Run interactive tests: npx cypress open" + echo " Run headless tests: npx cypress run" + echo "" + echo "Xdebug for PHP Debugging:" + echo " Xdebug is pre-configured on port 9003. Use the 'Run and Debug' panel in VS Code and select 'Listen for Xdebug'." + echo "---" +} | tee "$DETAILS_FILE" diff --git a/.devcontainer/xdebug.ini b/.devcontainer/xdebug.ini new file mode 100644 index 0000000000000..61b89fca18d38 --- /dev/null +++ b/.devcontainer/xdebug.ini @@ -0,0 +1,7 @@ +[xdebug] +zend_extension=xdebug +xdebug.mode=debug +xdebug.log_level = 0 +xdebug.start_with_request=yes +xdebug.client_port=9003 +xdebug.client_host=localhost