From ad90531ee9c2d15eb844e4346b83557c1f0f9282 Mon Sep 17 00:00:00 2001 From: Paul van der Meijs Date: Fri, 17 Jan 2020 14:02:21 +0100 Subject: [PATCH] Support Magento v1 and v2, fixes #1011 (#1802) --- .circleci/config.yml | 77 +++++--- .circleci/macos_circle_vm_setup.sh | 7 +- Makefile | 8 +- README.md | 4 +- containers/ddev-webserver/Dockerfile | 7 + .../files/etc/nginx/nginx-site-magento.conf | 42 ++++ .../files/etc/nginx/nginx-site-magento2.conf | 42 ++++ .../files/etc/nginx/nginx_magento.conf | 73 +++++++ .../files/etc/nginx/nginx_magento2.conf | 187 ++++++++++++++++++ docs/users/cli-usage.md | 80 ++++++-- pkg/ddevapp/apptypes.go | 6 + pkg/ddevapp/config.go | 1 + pkg/ddevapp/ddevapp-packr.go | 8 + pkg/ddevapp/ddevapp_test.go | 44 ++++- pkg/ddevapp/magento.go | 181 +++++++++++++++++ pkg/ddevapp/magento_packr_assets/env.php | 75 +++++++ pkg/ddevapp/magento_packr_assets/local.xml | 72 +++++++ pkg/ddevapp/packrd/packed-packr.go | 32 +++ pkg/nodeps/values.go | 2 + pkg/testcommon/testcommon.go | 2 + pkg/version/version.go | 2 +- 21 files changed, 898 insertions(+), 54 deletions(-) create mode 100644 containers/ddev-webserver/files/etc/nginx/nginx-site-magento.conf create mode 100644 containers/ddev-webserver/files/etc/nginx/nginx-site-magento2.conf create mode 100644 containers/ddev-webserver/files/etc/nginx/nginx_magento.conf create mode 100644 containers/ddev-webserver/files/etc/nginx/nginx_magento2.conf create mode 100644 pkg/ddevapp/ddevapp-packr.go create mode 100644 pkg/ddevapp/magento.go create mode 100644 pkg/ddevapp/magento_packr_assets/env.php create mode 100755 pkg/ddevapp/magento_packr_assets/local.xml create mode 100644 pkg/ddevapp/packrd/packed-packr.go diff --git a/.circleci/config.yml b/.circleci/config.yml index be2caa5f23c..119a879d096 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,14 +11,16 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - run: command: ./.circleci/linux_circle_vm_setup.sh name: NORMAL Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache + # Now build using the regular ddev-only technique - this results in a fully clean set of executables. - run: @@ -42,15 +44,16 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 # Run the built-in ddev tests with the executables just built. - run: command: ./.circleci/linux_circle_vm_setup.sh name: Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache # Now build using the regular ddev-only technique - this results in a fully clean set of executables. - run: @@ -73,18 +76,19 @@ jobs: at: ~/ - restore_cache: keys: - - homebrew-macos-v14 + - homebrew-macos-v15 # Run the built-in ddev tests with the executables just built. - run: command: ./.circleci/macos_circle_vm_setup.sh name: macOS Circle VM setup - tools, docker, golang # Now build using the regular ddev-only technique - this results in a fully clean set of executables. - save_cache: - key: homebrew-macos-v14 + key: homebrew-macos-v15 paths: - /usr/local/Homebrew - /usr/local/Cellar - ~/Library/Caches/Homebrew + - ~/.ddev/testcache - run: command: make -s test name: ddev tests @@ -105,7 +109,7 @@ jobs: at: ~/ - restore_cache: keys: - - homebrew-macos-v14 + - homebrew-macos-v15 # Run the built-in ddev tests with the executables just built. - run: command: ./.circleci/macos_circle_vm_setup.sh @@ -118,11 +122,12 @@ jobs: - store_test_results: path: /tmp/testresults - save_cache: - key: homebrew-macos-v14 + key: homebrew-macos-v15 paths: - /usr/local/Homebrew - /usr/local/Cellar - ~/Library/Caches/Homebrew + - ~/.ddev/testcache mac_nfsmount_test: macos: @@ -137,17 +142,18 @@ jobs: at: ~/ - restore_cache: keys: - - homebrew-macos-v14 + - homebrew-macos-v15 # Run the built-in ddev tests with the executables just built. - run: command: ./.circleci/macos_circle_vm_setup.sh name: macOS Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-macos-v14 + key: homebrew-macos-v15 paths: - /usr/local/Homebrew - /usr/local/Cellar - ~/Library/Caches/Homebrew + - ~/.ddev/testcache - run: command: make -s test name: ddev tests @@ -168,16 +174,17 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - attach_workspace: at: ~/ - run: command: ./.circleci/linux_circle_vm_setup.sh name: Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache # Now build using the regular ddev-only technique - this results in a fully clean set of executables. # Run the built-in ddev tests with the executables just built. @@ -201,16 +208,18 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - attach_workspace: at: ~/ - run: command: ./.circleci/linux_circle_vm_setup.sh name: Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache + - run: command: make -s test EXTRA_PATH=/home/linuxbrew/.linuxbrew/bin name: ddev tests @@ -231,16 +240,18 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - attach_workspace: at: ~/ - run: command: ./.circleci/linux_circle_vm_setup.sh name: Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache + # Now build using the regular ddev-only technique - this results in a fully clean set of executables. # Run the built-in ddev tests with the executables just built. - run: @@ -260,14 +271,16 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - run: command: ./.circleci/linux_circle_vm_setup.sh name: Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache + - run: command: source ~/.bashrc && nvm use 10 && make staticrequired EXTRA_PATH=/home/linuxbrew/.linuxbrew/bin name: staticrequired @@ -281,14 +294,16 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - run: command: ./.circleci/linux_circle_vm_setup.sh name: Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache + - run: command: | . ~/.bashrc @@ -310,16 +325,18 @@ jobs: - checkout - restore_cache: keys: - - homebrew-macos-v14 + - homebrew-macos-v15 - run: command: ./.circleci/macos_circle_vm_setup.sh name: macOS Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-macos-v14 + key: homebrew-macos-v15 paths: - /usr/local/Homebrew - /usr/local/Cellar - ~/Library/Caches/Homebrew + - ~/.ddev/testcache + - run: command: | for dir in containers/* @@ -340,7 +357,7 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - attach_workspace: at: ~/ - run: @@ -348,9 +365,11 @@ jobs: name: tar/zip up artifacts and make hashes no_output_timeout: "40m" - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache + - store_artifacts: path: ~/artifacts name: Artifact storage @@ -367,14 +386,15 @@ jobs: - run: sudo mkdir /home/linuxbrew && sudo chown $(id -u) /home/linuxbrew - restore_cache: keys: - - homebrew-linux-v9 + - homebrew-linux-v10 - run: command: ./.circleci/linux_circle_vm_setup.sh name: TAG BUILD Circle VM setup - tools, docker, golang - save_cache: - key: homebrew-linux-v9 + key: homebrew-linux-v10 paths: - /home/linuxbrew + - ~/.ddev/testcache # Now build using the regular ddev-only technique - this results in a fully clean set of executables. - run: @@ -403,16 +423,17 @@ jobs: - checkout - restore_cache: keys: - - homebrew-macos-v14 + - homebrew-macos-v15 - run: command: ./.circleci/macos_circle_vm_setup.sh name: RELEASE BUILD (macOS) Circle VM setup - save_cache: - key: homebrew-macos-v14 + key: homebrew-macos-v15 paths: - /usr/local/Homebrew - /usr/local/Cellar - ~/Library/Caches/Homebrew + - ~/.ddev/testcache - run: command: make -s clean linux windows_install chocolatey diff --git a/.circleci/macos_circle_vm_setup.sh b/.circleci/macos_circle_vm_setup.sh index 26b183c685a..f34c6fa7c93 100755 --- a/.circleci/macos_circle_vm_setup.sh +++ b/.circleci/macos_circle_vm_setup.sh @@ -9,6 +9,7 @@ curl -O -sSL $DOCKER_URL open -W Docker.dmg && cp -r /Volumes/Docker/Docker.app /Applications export HOMEBREW_NO_AUTO_UPDATE=1 +export HOMEBREW_NO_INSTALL_CLEANUP=1 # Get docker in first so we can install it and work on other things brew cask install ngrok @@ -19,12 +20,10 @@ nohup /Applications/Docker.app/Contents/MacOS/Docker --unattended & brew tap drud/ddev brew unlink python@2 || true -brew install mysql-client zip makensis jq expect coreutils golang ddev mkcert osslsigncode ghr gnu-getopt -brew link mysql-client zip makensis jq expect coreutils golang ddev mkcert osslsigncode ghr gnu-getopt +brew install mysql-client zip makensis jq expect coreutils golang ddev mkcert osslsigncode ghr gnu-getopt libgsf glib pcre || true +brew link mysql-client zip makensis jq expect coreutils golang ddev mkcert osslsigncode ghr gnu-getopt libgsf glib pcre brew link --force mysql-client -# These links are required for osslsigncode to work -brew link libgsf glib pcre # Get the Plugins for NSIS curl -fsSL -o /tmp/EnVar-Plugin.zip https://github.com/GsNSIS/EnVar/releases/latest/download/EnVar-Plugin.zip && sudo unzip -o -d /usr/local/share/nsis /tmp/EnVar-Plugin.zip diff --git a/Makefile b/Makefile index f7623613e5d..781a66456f5 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,7 @@ setup: @mkdir -p $(TESTTMP) @mkdir -p $(DOWNLOADTMP) -# packr2 target currently builds packr2 caches in the cmd/ddev/cmd directory only +# packr2 target currently builds packr2 caches in cmd/ddev/cmd and pkg/ddevapp # using the golang-build-container's packr2 command packr2: docker run -t --rm -u $(shell id -u):$(shell id -g) \ @@ -118,6 +118,12 @@ packr2: -e GOCACHE="//workdir/$(GOTMP)/.cache" \ -w //workdir/cmd/ddev/cmd \ $(BUILD_IMAGE) packr2 + docker run -t --rm -u $(shell id -u):$(shell id -g) \ + -v "$(S)$(PWD):/workdir$(DOCKERMOUNTFLAG)" \ + -v "$(S)$(PWD)/$(GOTMP)/bin:$(S)/go/bin" \ + -e GOCACHE="//workdir/$(GOTMP)/.cache" \ + -w //workdir/pkg/ddevapp \ + $(BUILD_IMAGE) packr2 # Required static analysis targets used in circleci - these cause fail if they don't work staticrequired: setup golangci-lint markdownlint mkdocs diff --git a/README.md b/README.md index 7478a9b4209..1ba991ecd67 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ddev -[![CircleCI](https://circleci.com/gh/drud/ddev.svg?style=shield)](https://circleci.com/gh/drud/ddev) [![Go Report Card](https://goreportcard.com/badge/github.com/drud/ddev)](https://goreportcard.com/report/github.com/drud/ddev) ![project is maintained](https://img.shields.io/maintenance/yes/2019.svg) +[![CircleCI](https://circleci.com/gh/drud/ddev.svg?style=shield)](https://circleci.com/gh/drud/ddev) [![Go Report Card](https://goreportcard.com/badge/github.com/drud/ddev)](https://goreportcard.com/report/github.com/drud/ddev) ![project is maintained](https://img.shields.io/maintenance/yes/2020.svg) ![ddev logo](images/ddev_logo.png) @@ -18,6 +18,8 @@ ddev is an open source tool that makes it simple to get local PHP development en * [Drupal 8 Quickstart](https://ddev.readthedocs.io/en/stable/users/cli-usage#drupal-8-quickstart) * [Backdrop Quickstart](https://ddev.readthedocs.io/en/stable/users/cli-usage/#backdrop-quickstart) * [TYPO3 Quickstart](https://ddev.readthedocs.io/en/stable/users/cli-usage#typo3-quickstart) + * [Magento 1 Quickstart](https://ddev.readthedocs.io/en/stable/users/cli-usage#magento-1-quickstart) + * [Magento 2 Quickstart](https://ddev.readthedocs.io/en/stable/users/cli-usage#magento-2-quickstart) Having trouble? See our [support options below](#support). You might have trouble if [another local development tool is already using port 80 or 443](https://ddev.readthedocs.io/en/stable/users/troubleshooting/#unable-listen). diff --git a/containers/ddev-webserver/Dockerfile b/containers/ddev-webserver/Dockerfile index dde5d4be2bf..338696d261b 100644 --- a/containers/ddev-webserver/Dockerfile +++ b/containers/ddev-webserver/Dockerfile @@ -112,8 +112,15 @@ RUN curl -sSL "https://github.com/drush-ops/drush/releases/download/${DRUSH_VERS RUN curl -sSL "https://github.com/drush-ops/drush-launcher/releases/download/${DRUSH_LAUNCHER_VERSION}/drush.phar" -o /usr/local/bin/drush && chmod +x /usr/local/bin/drush RUN curl -sSL "https://github.com/mailhog/MailHog/releases/download/v${MAILHOG_VERSION}/MailHog_linux_amd64" -o /usr/local/bin/mailhog RUN curl -sSL -o /usr/local/bin/wp-cli -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && chmod +x /usr/local/bin/wp-cli && ln -s /usr/local/bin/wp-cli /usr/local/bin/wp + RUN curl -O https://raw.githubusercontent.com/pantheon-systems/terminus-installer/master/builds/installer.phar && php installer.phar install +# magerun and magerun2 for magento +RUN curl -sSL https://files.magerun.net/n98-magerun-latest.phar -o /usr/local/bin/magerun +RUN curl -sSL https://raw.githubusercontent.com/netz98/n98-magerun/${MAGERUN_VERSION}/res/autocompletion/bash/n98-magerun.phar.bash -o /etc/bash_completion.d/magerun +RUN curl -sSL https://files.magerun.net/n98-magerun2-latest.phar -o /usr/local/bin/magerun2 +RUN curl -sSL https://raw.githubusercontent.com/netz98/n98-magerun2/${MAGERUN2_VERSION}/res/autocompletion/bash/n98-magerun2.phar.bash -o /etc/bash_completion.d/magerun2 + RUN curl -sSL "https://drupalconsole.com/installer" -L -o /usr/local/bin/drupal && chmod +x /usr/local/bin/drupal diff --git a/containers/ddev-webserver/files/etc/nginx/nginx-site-magento.conf b/containers/ddev-webserver/files/etc/nginx/nginx-site-magento.conf new file mode 100644 index 00000000000..6207e59fcc2 --- /dev/null +++ b/containers/ddev-webserver/files/etc/nginx/nginx-site-magento.conf @@ -0,0 +1,42 @@ +# ddev default config + +# You can override ddev's configuration by placing an edited copy +# of this config (or one of the other ones) in .ddev/nginx-site.conf +# See https://ddev.readthedocs.io/en/stable/users/extend/customization-extendibility/#providing-custom-nginx-configuration + +# Set https to 'on' if x-forwarded-proto is https +map $http_x_forwarded_proto $fcgi_https { + default off; + https on; +} + +server { + listen 80; + listen [::]:80 default ipv6only=on; + + # The WEBSERVER_DOCROOT variable is substituted with + # its value when the container is started. + root $WEBSERVER_DOCROOT; + + include /etc/nginx/monitoring.conf; + + include /etc/nginx/nginx_magento.conf; + include /mnt/ddev_config/nginx/*.conf; +} + +server { + listen 443 ssl; + listen [::]:443 default ipv6only=on; + + # The WEBSERVER_DOCROOT variable is substituted with + # its value when the container is started. + root $WEBSERVER_DOCROOT; + + ssl_certificate /etc/ssl/certs/master.crt; + ssl_certificate_key /etc/ssl/certs/master.key; + + include /etc/nginx/monitoring.conf; + + include /etc/nginx/nginx_magento.conf; + include /mnt/ddev_config/nginx/*.conf; +} diff --git a/containers/ddev-webserver/files/etc/nginx/nginx-site-magento2.conf b/containers/ddev-webserver/files/etc/nginx/nginx-site-magento2.conf new file mode 100644 index 00000000000..c6bc24fbb08 --- /dev/null +++ b/containers/ddev-webserver/files/etc/nginx/nginx-site-magento2.conf @@ -0,0 +1,42 @@ +# ddev default config + +# You can override ddev's configuration by placing an edited copy +# of this config (or one of the other ones) in .ddev/nginx-site.conf +# See https://ddev.readthedocs.io/en/stable/users/extend/customization-extendibility/#providing-custom-nginx-configuration + +# Set https to 'on' if x-forwarded-proto is https +map $http_x_forwarded_proto $fcgi_https { + default off; + https on; +} + +server { + listen 80; + listen [::]:80 default ipv6only=on; + + # The WEBSERVER_DOCROOT variable is substituted with + # its value when the container is started. + root $WEBSERVER_DOCROOT; + + include /etc/nginx/monitoring.conf; + + include /etc/nginx/nginx_magento2.conf; + include /mnt/ddev_config/nginx/*.conf; +} + +server { + listen 443 ssl; + listen [::]:443 default ipv6only=on; + + # The WEBSERVER_DOCROOT variable is substituted with + # its value when the container is started. + root $WEBSERVER_DOCROOT; + + ssl_certificate /etc/ssl/certs/master.crt; + ssl_certificate_key /etc/ssl/certs/master.key; + + include /etc/nginx/monitoring.conf; + + include /etc/nginx/nginx_magento2.conf; + include /mnt/ddev_config/nginx/*.conf; +} diff --git a/containers/ddev-webserver/files/etc/nginx/nginx_magento.conf b/containers/ddev-webserver/files/etc/nginx/nginx_magento.conf new file mode 100644 index 00000000000..326a47db4b6 --- /dev/null +++ b/containers/ddev-webserver/files/etc/nginx/nginx_magento.conf @@ -0,0 +1,73 @@ + index index.php index.htm index.html; + + # Make site accessible from http://localhost/ + server_name _; + + # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html + sendfile off; + error_log /dev/stdout info; + access_log /var/log/nginx/access.log; + + if ($mage_run_code = '') { + set $mage_run_code ''; + } + + if ($mage_run_type = '') { + set $mage_run_type store; + } + + location / { + absolute_redirect off; + try_files $uri $uri/ /index.php$is_args$args; + } + + location /api { + rewrite ^/api/rest /api.php?type=rest last; + } + + # pass the PHP scripts to FastCGI server listening on socket + location ~ \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:/run/php-fpm.sock; + fastcgi_buffers 16 16k; + fastcgi_buffer_size 32k; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_intercept_errors on; + # fastcgi_read_timeout should match max_execution_time in php.ini + fastcgi_read_timeout 10m; + fastcgi_param SERVER_NAME $host; + fastcgi_param HTTPS $fcgi_https; + fastcgi_param MAGE_RUN_CODE $mage_run_code; + fastcgi_param MAGE_RUN_TYPE $mage_run_type; + } + + # Expire rules for static content + # Feed + location ~* \.(?:rss|atom)$ { + expires 1h; + } + + # Media: images, icons, video, audio, HTC + location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ { + expires 1M; + access_log off; + add_header Cache-Control "public"; + } + + # Prevent clients from accessing hidden files (starting with a dot) + # This is particularly important if you store .htpasswd files in the site hierarchy + # Access to `/.well-known/` is allowed. + # https://www.mnot.net/blog/2010/04/07/well-known + # https://tools.ietf.org/html/rfc5785 + location ~* /\.(?!well-known\/) { + deny all; + } + + # Prevent clients from accessing to backup/config/source files + location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ { + deny all; + } diff --git a/containers/ddev-webserver/files/etc/nginx/nginx_magento2.conf b/containers/ddev-webserver/files/etc/nginx/nginx_magento2.conf new file mode 100644 index 00000000000..d12a8da516e --- /dev/null +++ b/containers/ddev-webserver/files/etc/nginx/nginx_magento2.conf @@ -0,0 +1,187 @@ + index index.php index.htm index.html; + + # Make site accessible from http://localhost/ + server_name _; + + # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html + sendfile off; + error_log /var/log/nginx/error.log info; + access_log /var/log/nginx/access.log; + + if ($mage_run_code = '') { + set $mage_run_code ''; + } + + if ($mage_run_type = '') { + set $mage_run_type store; + } + + # pass the PHP scripts to FastCGI server listening on socket + location ~ \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:/run/php-fpm.sock; + fastcgi_buffers 16 16k; + fastcgi_buffer_size 32k; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_intercept_errors on; + # fastcgi_read_timeout should match max_execution_time in php.ini + fastcgi_read_timeout 10m; + fastcgi_param SERVER_NAME $host; + fastcgi_param HTTPS $fcgi_https; + fastcgi_param MAGE_RUN_CODE $mage_run_code; + fastcgi_param MAGE_RUN_TYPE $mage_run_type; + } + + # Expire rules for static content + # Feed + location ~* \.(?:rss|atom)$ { + expires 1h; + } + + # Media: images, icons, video, audio, HTC + location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ { + expires 1M; + access_log off; + add_header Cache-Control "public"; + } + + # Prevent clients from accessing hidden files (starting with a dot) + # This is particularly important if you store .htpasswd files in the site hierarchy + # Access to `/.well-known/` is allowed. + # https://www.mnot.net/blog/2010/04/07/well-known + # https://tools.ietf.org/html/rfc5785 + location ~* /\.(?!well-known\/) { + deny all; + } + + # Prevent clients from accessing to backup/config/source files + location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ { + deny all; + } + + set $MAGE_ROOT /var/www/html; + + location / { + try_files $uri $uri/ /index.php$is_args$args; + } + + location /pub/ { + location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) { + deny all; + } + alias $MAGE_ROOT/pub/; + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /static/ { + # Uncomment the following line in production mode + # expires max; + + # Remove signature of the static files that is used to overcome the browser cache + location ~ ^/static/version { + rewrite ^/static/(version[^/]+/)?(.*)$ /static/$2 last; + } + + location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|json)$ { + add_header Cache-Control "public"; + add_header X-Frame-Options "SAMEORIGIN"; + expires +1y; + + if (!-f $request_filename) { + rewrite ^/static/?(.*)$ /static.php?resource=$1 last; + } + } + location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { + add_header Cache-Control "no-store"; + add_header X-Frame-Options "SAMEORIGIN"; + expires off; + + if (!-f $request_filename) { + rewrite ^/static/?(.*)$ /static.php?resource=$1 last; + } + } + if (!-f $request_filename) { + rewrite ^/static/?(.*)$ /static.php?resource=$1 last; + } + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /media/ { + try_files $uri $uri/ /get.php$is_args$args; + + location ~ ^/media/theme_customization/.*\.xml { + deny all; + } + + location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ { + add_header Cache-Control "public"; + add_header X-Frame-Options "SAMEORIGIN"; + expires +1y; + try_files $uri $uri/ /get.php$is_args$args; + } + location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { + add_header Cache-Control "no-store"; + add_header X-Frame-Options "SAMEORIGIN"; + expires off; + try_files $uri $uri/ /get.php$is_args$args; + } + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /media/customer/ { + deny all; + } + + location /media/downloadable/ { + deny all; + } + + location /media/import/ { + deny all; + } + + # PHP entry point for main application + location ~ (index|get|static|report|404|503|health_check)\.php$ { + try_files $uri =404; + fastcgi_pass unix:/run/php-fpm.sock; + fastcgi_buffers 1024 4k; + + fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off"; + fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=18000"; + fastcgi_read_timeout 600s; + fastcgi_connect_timeout 600s; + + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + gzip on; + gzip_disable "msie6"; + + gzip_comp_level 6; + gzip_min_length 1100; + gzip_buffers 16 8k; + gzip_proxied any; + gzip_types + text/plain + text/css + text/js + text/xml + text/javascript + application/javascript + application/x-javascript + application/json + application/xml + application/xml+rss + image/svg+xml; + gzip_vary on; + + # Banned locations (only reached if the earlier PHP entry point regexes don't match) + location ~* (\.php$|\.htaccess$|\.git) { + deny all; + } diff --git a/docs/users/cli-usage.md b/docs/users/cli-usage.md index a41936aa1c3..4b5147740b2 100644 --- a/docs/users/cli-usage.md +++ b/docs/users/cli-usage.md @@ -257,6 +257,32 @@ Successfully started example-site Your application can be reached at: http://example-backdrop-site.ddev.site ``` +### Magento 1 Quickstart + +1. Download Magento 1 (not recommended, as it's end-of-life) from [release page](https://github.com/OpenMage/magento-mirror/releases). +2. Make a directory for it, for example `mkdir ~/workspace/magento1` and change directory to the new directory. +3. Extract the download, for example `tar -zxf ~/Downloads/magento-mirror-1.9.4.3.tar.gz --strip-components=1` +4. `ddev config` and accept the defaults. +5. `ddev start` +6. Follow the URL to the base site. + +### Magento 2 Quickstart + +Normal details of a composer build for Magento 2 are on [Magento 2 site](https://devdocs.magento.com/guides/v2.3/install-gde/composer.html) You must have a public and private key to install from Magento's repository; when prompted for "username" and "password" in the composer create it's asking for your public and private keys. + +``` +ddev config --project-type=magento2 --docroot=pub --create-docroot=true +ddev start +ddev composer create --repository= magento/project-community-edition +ddev ssh +bin/magento setup:install --db-host=db --db-name=db --db-user=db --db-password=db --admin-firstname=Magento --admin-lastname=User --admin-email=user@example.com --admin-user=admin --admin-password=admin123 --language=en_US +bin/magento deploy:mode:set developer +``` + +Of course, change the admin name and related information is needed. + +Note that Magento 2 is a huge codebase and using `nfs_mount_enabled: true` is recommended for performance on macOS and Windows, see [docs](performance/#using-nfs-to-mount-the-project-into-the-container). + ### Database Imports Import a database with just one command; We offer support for several file formats, including: **.sql, sql.gz, mysql, mysql.gz, tar, tar.gz, and zip**. @@ -264,7 +290,9 @@ Import a database with just one command; We offer support for several file forma Here's an example of a database import using ddev: ``` + ddev import-db --src=dumpfile.sql.gz + ``` **Note for Backdrop users:** In addition to importing a Backdrop database, you will need to extract a copy of your Backdrop project's configuration into the local `active` directory. The location for this directory can vary depending on the contents of your Backdrop `settings.php` file, but the default location is `[docroot]/files/config_[random letters and numbers]/active`. Please refer to the Backdrop documentation for more information on [moving your Backdrop site](https://backdropcms.org/user-guide/moving-backdrop-site) into the `ddev` environment. @@ -274,11 +302,13 @@ ddev import-db --src=dumpfile.sql.gz Check out the git repository for the project you want to work on. `cd` into the directory, run `ddev config`, and follow the prompts. ``` + mkdir drupal8 cd drupal8 ddev config --project-type php ddev composer create drupal-composer/drupal-project:8.x-dev ddev config --project-type drupal8 + ``` Configuration files have now been created for your project. Take a look at the project's .ddev/config.yaml file. @@ -286,6 +316,7 @@ Configuration files have now been created for your project. Take a look at the p Now that the configuration files have been created, you can start your project with `ddev start` (still from within the project working directory): ``` + ddev start Starting environment for drupal8... @@ -293,7 +324,8 @@ Creating local-drupal8-db Creating local-drupal8-web Waiting for the environment to become ready. This may take a couple of minutes... Successfully started drupal8 -Your project can be reached at: http://drupal8.ddev.site +Your project can be reached at: + ``` And you can now visit your working project. Enjoy! @@ -322,10 +354,12 @@ For **Wordpress**, DDEV settings are written to a DDEV-managed file, wp-config-d How do you know if DDEV manages a settings file? You will see the following comment. Remove the comment and DDEV will not attempt to overwrite it! ``` + /** #ddev-generated: Automatically generated Drupal settings.php file. ddev manages this file and may delete or overwrite the file unless this comment is removed. */ + ``` ## Listing project information @@ -333,41 +367,48 @@ How do you know if DDEV manages a settings file? You will see the following comm To see a list of your projects you can use `ddev list`; `ddev list --active-only` will show only projects currently running or paused. ``` + ➜ ddev list NAME TYPE LOCATION URL(s) STATUS -d8git drupal8 ~/workspace/d8git https://d8git.ddev.local running - http://d8git.ddev.local +d8git drupal8 ~/workspace/d8git running + hobobiker drupal6 ~/workspace/hobobiker.com stopped + ``` ``` + ➜ ddev list --active-only NAME TYPE LOCATION URL(s) STATUS -drupal8 drupal8 ~/workspace/drupal8 http://drupal8.ddev.site running - https://drupal8.ddev.site +drupal8 drupal8 ~/workspace/drupal8 running + + ``` You can also see more detailed information about a project by running `ddev describe` from its working directory. You can also run `ddev describe [project-name]` from any location to see the detailed information for a running project. ``` + NAME TYPE LOCATION URL STATUS -d8composer drupal8 ~/workspace/d8composer https://d8composer.ddev.site running +d8composer drupal8 ~/workspace/d8composer running Project Information ------------------- + PHP version: 7.4 MariaDB version MySQL version 5.7 URLs ---- -http://d8composer.ddev.site -http://127.0.0.1:32811 -https://d8composer.ddev.site -https://127.0.0.1:32810 + + + + MySQL/MariaDB Credentials ------------------------- + Username: "db", Password: "db", Default database: "db" or use root credentials when needed: Username: "root", Password: "root" @@ -381,11 +422,13 @@ mysql --host=127.0.0.1 --port=32809 --user=db --password=db --database=db Other Services -------------- -MailHog: http://d8composer.ddev.site:8025 -phpMyAdmin: http://d8composer.ddev.site:8036 + +MailHog: +phpMyAdmin: DDEV ROUTER STATUS: healthy ssh-auth status: healthy + ``` ## Removing projects from your collection known to ddev @@ -411,12 +454,14 @@ An important aspect of local web development is the ability to have a precise re The `ddev import-db` command is provided for importing the MySQL database for a project. Running this command will provide a prompt for you to specify the location of your database import. ``` + ➜ ddev import-db Provide the path to the database you wish to import. Import path: ~/Downloads/db.sql Importing database... Successfully imported database for drupal8 + ```

Supported file types

@@ -432,6 +477,7 @@ Database import supports the following file types: If a Tarball Archive or Zip Archive is provided for the import, you will be provided an additional prompt, allowing you to specify a path within the archive to use for the import asset. The specified path should provide a Raw SQL Dump (.sql). In the following example, the database we want to import is named data.sql and resides at the top-level of the archive: ``` + ➜ ddev import-db Provide the path to the database you wish to import. Import path: @@ -443,6 +489,7 @@ Importing database... A settings file already exists for your application, so ddev did not generate one. Run 'ddev describe' to find the database credentials for this application. Successfully imported database for drupal8 + ```

Non-interactive usage

@@ -450,9 +497,11 @@ Successfully imported database for drupal8 If you want to use import-db without answering prompts, you can use the `--src` flag to provide the path to the import asset. If you are importing an archive, and wish to specify the path within the archive to extract, you can use the `--extract-path` flag in conjunction with the `--src` flag. Examples: ``` + ddev import-db --src=/tmp/mydb.sql.gz gzip -dc /tmp/mydb.sql.gz | ddev import-db ddev import-db Database import notes @@ -465,9 +514,11 @@ ddev import-db /tmp/db.sql.gz ddev export-db --gzip=false >/tmp/db.sql + ``` ### Importing static file assets @@ -480,11 +531,13 @@ To import static file assets for a project, such as uploaded images and document * For Backdrop projects, this is the `files` directory ``` + ➜ ddev import-files Provide the path to the directory or archive you wish to import. Please note, if the destination directory exists, it will be replaced with the import assets specified here. Import path: ~/Downloads/files.tar.gz Successfully imported files for drupal8 + ```

Supported file types

@@ -498,6 +551,7 @@ Static asset import supports the following file types: If a Tarball Archive or Zip Archive is provided for the import, you will be provided an additional prompt, allowing you to specify a path within the archive to use for the import asset. In the following example, the assets we want to import reside at "web/sites/default/files": ``` + ➜ ddev import-files Provide the path to the directory or archive you wish to import. Please note, if the destination directory exists, it will be replaced with the import assets specified here. Import path: @@ -506,6 +560,7 @@ You provided an archive. Do you want to extract from a specific path in your arc Archive extraction path: web/sites/default/files Successfully imported files for drupal8 + ```

Non-interactive usage

@@ -518,6 +573,7 @@ If you want to use import-files without answering prompts, you can use the `--sr The project database is stored in a docker volume, but can be snapshotted (and later restored) with the `ddev snapshot` command. A snapshot is automatically taken when you do a `ddev stop --remove-data`. For example: ``` + $ ddev snapshot Creating database snapshot d8git_20180801132403 Created database snapshot d8git_20180801132403 in /Users/rfay/workspace/d8git/.ddev/db_snapshots/d8git_20180801132403 diff --git a/pkg/ddevapp/apptypes.go b/pkg/ddevapp/apptypes.go index 3fdb078e22d..7763891f81b 100644 --- a/pkg/ddevapp/apptypes.go +++ b/pkg/ddevapp/apptypes.go @@ -83,6 +83,12 @@ func init() { nodeps.AppTypeBackdrop: { settingsCreator: createBackdropSettingsFile, uploadDir: getBackdropUploadDir, hookDefaultComments: getBackdropHooks, apptypeSettingsPaths: setBackdropSiteSettingsPaths, appTypeDetect: isBackdropApp, postImportDBAction: backdropPostImportDBAction, configOverrideAction: nil, postConfigAction: nil, postStartAction: backdropPostStartAction, importFilesAction: backdropImportFilesAction, defaultWorkingDirMap: docrootWorkingDir, }, + nodeps.AppTypeMagento: { + settingsCreator: createMagentoSettingsFile, uploadDir: getMagentoUploadDir, hookDefaultComments: nil, apptypeSettingsPaths: setMagentoSiteSettingsPaths, appTypeDetect: isMagentoApp, postImportDBAction: nil, configOverrideAction: magentoConfigOverrideAction, postConfigAction: nil, postStartAction: nil, importFilesAction: magentoImportFilesAction, defaultWorkingDirMap: nil, + }, + nodeps.AppTypeMagento2: { + settingsCreator: createMagento2SettingsFile, uploadDir: getMagento2UploadDir, hookDefaultComments: nil, apptypeSettingsPaths: setMagento2SiteSettingsPaths, appTypeDetect: isMagento2App, postImportDBAction: nil, configOverrideAction: magento2ConfigOverrideAction, postConfigAction: nil, postStartAction: nil, importFilesAction: magentoImportFilesAction, defaultWorkingDirMap: nil, + }, } } diff --git a/pkg/ddevapp/config.go b/pkg/ddevapp/config.go index ac62e539ad7..d80d453d754 100644 --- a/pkg/ddevapp/config.go +++ b/pkg/ddevapp/config.go @@ -762,6 +762,7 @@ func AvailableDocrootLocations() []string { "htdocs", "_www", "public", + "pub", } } diff --git a/pkg/ddevapp/ddevapp-packr.go b/pkg/ddevapp/ddevapp-packr.go new file mode 100644 index 00000000000..8cbd1da3ebe --- /dev/null +++ b/pkg/ddevapp/ddevapp-packr.go @@ -0,0 +1,8 @@ +// +build !skippackr +// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. + +// You can use the "packr clean" command to clean up this, +// and any other packr generated files. +package ddevapp + +import _ "github.com/drud/ddev/pkg/ddevapp/packrd" diff --git a/pkg/ddevapp/ddevapp_test.go b/pkg/ddevapp/ddevapp_test.go index ed487824ee7..f4627ec9c74 100644 --- a/pkg/ddevapp/ddevapp_test.go +++ b/pkg/ddevapp/ddevapp_test.go @@ -119,7 +119,35 @@ var ( DynamicURI: testcommon.URIWithExpect{URI: "/index.php?id=65", Expect: "Boxed Content"}, FilesImageURI: "/fileadmin/introduction/images/streets/nikita-maru-70928.jpg", }, + { + Name: "testpkgmagento", + SourceURL: "https://github.com/OpenMage/magento-mirror/archive/1.9.4.3.tar.gz", + ArchiveInternalExtractionPath: "magento-mirror-1.9.4.3/", + DBTarURL: "https://github.com/drud/ddev_test_tarballs/releases/download/v1.1/TestPkgMagento_db_secure_url.tar.gz", + FilesTarballURL: "https://github.com/drud/ddev_test_tarballs/releases/download/v1.1/magento_upload_files.tgz", + FullSiteTarballURL: "", + Docroot: "", + Type: nodeps.AppTypeMagento, + Safe200URIWithExpectation: testcommon.URIWithExpect{URI: "/LICENSE.txt", Expect: `Open Software License ("OSL")`}, + DynamicURI: testcommon.URIWithExpect{URI: "/", Expect: "This is a demo store"}, + FilesImageURI: "/media/wrapping/Chrysanthemum.jpg", + }, + // Note that testpkgmagento2 code is enormous and makes this really, really slow. + { + Name: "testpkgmagento2", + SourceURL: "https://github.com/drud/ddev_test_tarballs/releases/download/v1.1/magento2_code_no_dev_with_media.tgz", + ArchiveInternalExtractionPath: "", + DBTarURL: "https://github.com/drud/ddev_test_tarballs/releases/download/v1.1/magento2_db.tgz", + FilesTarballURL: "https://github.com/drud/ddev_test_tarballs/releases/download/v1.1/magento2_files.tgz", + FullSiteTarballURL: "", + Docroot: "pub", + Type: nodeps.AppTypeMagento2, + Safe200URIWithExpectation: testcommon.URIWithExpect{URI: "/junk.txt", Expect: `This is a junk`}, + DynamicURI: testcommon.URIWithExpect{URI: "/index.php/junk-product.html", Expect: "junk product"}, + FilesImageURI: "/media/catalog/product/r/a/randy_4th_of_july_unicycle.jpg", + }, } + FullTestSites = TestSites ) @@ -1000,7 +1028,7 @@ func TestDdevFullSiteSetup(t *testing.T) { // Test static content. _, _ = testcommon.EnsureLocalHTTPContent(t, app.GetHTTPSURL()+site.Safe200URIWithExpectation.URI, site.Safe200URIWithExpectation.Expect) // Test dynamic php + database content. - rawurl := app.GetHTTPURL() + site.DynamicURI.URI + rawurl := app.GetHTTPSURL() + site.DynamicURI.URI body, resp, err := testcommon.GetLocalHTTPResponse(t, rawurl, 60) assert.NoError(err, "GetLocalHTTPResponse returned err on project=%s rawurl %s, resp=%v: %v", site.Name, rawurl, resp, err) if err != nil && strings.Contains(err.Error(), "container ") { @@ -1012,7 +1040,7 @@ func TestDdevFullSiteSetup(t *testing.T) { // Load an image from the files section if site.FilesImageURI != "" { - _, resp, err := testcommon.GetLocalHTTPResponse(t, app.GetHTTPURL()+site.FilesImageURI) + _, resp, err := testcommon.GetLocalHTTPResponse(t, app.GetHTTPSURL()+site.FilesImageURI) assert.NoError(err, "failed ImageURI response on project %s: %v", site.Name, err) assert.Equal("image/jpeg", resp.Header["Content-Type"][0]) } @@ -1076,7 +1104,7 @@ func TestDdevRestoreSnapshot(t *testing.T) { err = app.StartAndWait(2) require.NoError(t, err, "app.Start() failed on site %s, err=%v", site.Name, err) - resp, ensureErr := testcommon.EnsureLocalHTTPContent(t, app.GetHTTPURL(), "d7 tester test 1 has 1 node", 45) + resp, ensureErr := testcommon.EnsureLocalHTTPContent(t, app.GetHTTPSURL(), "d7 tester test 1 has 1 node", 45) assert.NoError(ensureErr) if ensureErr != nil && strings.Contains(ensureErr.Error(), "container failed") { logs, err := ddevapp.GetErrLogsFromApp(app, ensureErr) @@ -1107,7 +1135,7 @@ func TestDdevRestoreSnapshot(t *testing.T) { err = app.ImportDB(d7testerTest2Dump, "", false) assert.NoError(err, "Failed to app.ImportDB path: %s err: %v", d7testerTest2Dump, err) - _, _ = testcommon.EnsureLocalHTTPContent(t, app.GetHTTPURL(), "d7 tester test 2 has 2 nodes", 45) + _, _ = testcommon.EnsureLocalHTTPContent(t, app.GetHTTPSURL(), "d7 tester test 2 has 2 nodes", 45) snapshotName, err = app.Snapshot("d7testerTest2") assert.NoError(err) @@ -1126,12 +1154,12 @@ func TestDdevRestoreSnapshot(t *testing.T) { err = os.Remove("hello-post-restore-snapshot-" + app.Name) assert.NoError(err) - _, _ = testcommon.EnsureLocalHTTPContent(t, app.GetHTTPURL(), "d7 tester test 1 has 1 node", 45) + _, _ = testcommon.EnsureLocalHTTPContent(t, app.GetHTTPSURL(), "d7 tester test 1 has 1 node", 45) err = app.RestoreSnapshot("d7testerTest2") assert.NoError(err) - body, resp, err := testcommon.GetLocalHTTPResponse(t, app.GetHTTPURL(), 45) - assert.NoError(err, "GetLocalHTTPResponse returned err on rawurl %s: %v", app.GetHTTPURL(), err) + body, resp, err := testcommon.GetLocalHTTPResponse(t, app.GetHTTPSURL(), 45) + assert.NoError(err, "GetLocalHTTPResponse returned err on rawurl %s: %v", app.GetHTTPSURL(), err) assert.Contains(body, "d7 tester test 2 has 2 nodes") if err != nil { t.Logf("resp after timeout: %v", resp) @@ -1281,6 +1309,7 @@ func TestDdevImportFilesDir(t *testing.T) { for _, site := range TestSites { switchDir := site.Chdir() runTime := util.TimeTrack(time.Now(), fmt.Sprintf("%s %s", site.Name, t.Name())) + t.Logf("=== BEGIN TestDdevImportFilesDir for %s\n", site.Name) testcommon.ClearDockerEnv() err = app.Init(site.Dir) @@ -1363,6 +1392,7 @@ func TestDdevImportFilesCustomUploadDir(t *testing.T) { for _, site := range TestSites { switchDir := site.Chdir() runTime := util.TimeTrack(time.Now(), fmt.Sprintf("%s %s", site.Name, t.Name())) + t.Logf("=== BEGIN TestDdevImportFilesCustomUploadDir for %s\n", site.Name) testcommon.ClearDockerEnv() err := app.Init(site.Dir) diff --git a/pkg/ddevapp/magento.go b/pkg/ddevapp/magento.go new file mode 100644 index 00000000000..23c4ce86cfc --- /dev/null +++ b/pkg/ddevapp/magento.go @@ -0,0 +1,181 @@ +package ddevapp + +import ( + "fmt" + "github.com/drud/ddev/pkg/archive" + "github.com/drud/ddev/pkg/fileutil" + "github.com/drud/ddev/pkg/nodeps" + "github.com/drud/ddev/pkg/output" + "github.com/drud/ddev/pkg/util" + "github.com/gobuffalo/packr/v2" + "io/ioutil" + "os" + "path/filepath" +) + +// isMagentoApp returns true if the app is of type magento +func isMagentoApp(app *DdevApp) bool { + if _, err := os.Stat(filepath.Join(app.AppRoot, "get.php")); err == nil { + return true + } + return false +} + +// isMagento2App returns true if the app is of type magento2 +func isMagento2App(app *DdevApp) bool { + if _, err := os.Stat(filepath.Join(app.AppRoot, "pub", "static.php")); err == nil { + return true + } + return false +} + +// createMagentoSettingsFile manages creation and modification of local.xml. +func createMagentoSettingsFile(app *DdevApp) (string, error) { + + if fileutil.FileExists(app.SiteSettingsPath) { + // Check if the file is managed by ddev. + signatureFound, err := fileutil.FgrepStringInFile(app.SiteSettingsPath, DdevFileSignature) + if err != nil { + return "", err + } + + // If the signature wasn't found, warn the user and return. + if !signatureFound { + util.Warning("%s already exists and is managed by the user.", app.SiteSettingsPath) + return "", nil + } + } else { + output.UserOut.Printf("No %s file exists, creating one", app.SiteSettingsPath) + + box := packr.New("magento_packr_assets", "./magento_packr_assets") + content, err := box.Find("local.xml") + if err != nil { + return "", err + } + err = ioutil.WriteFile(app.SiteSettingsPath, content, 0644) + if err != nil { + return "", err + } + } + + return app.SiteDdevSettingsFile, nil +} + +// setMagentoSiteSettingsPaths sets the paths to settings.php for templating. +func setMagentoSiteSettingsPaths(app *DdevApp) { + settingsFileBasePath := app.AppRoot + app.SiteSettingsPath = filepath.Join(settingsFileBasePath, "app", "etc", "local.xml") +} + +// magentoImportFilesAction defines the magento workflow for importing project files. +func magentoImportFilesAction(app *DdevApp, importPath, extPath string) error { + destPath := filepath.Join(app.GetAppRoot(), app.GetDocroot(), app.GetUploadDir()) + + // parent of destination dir should exist + if !fileutil.FileExists(filepath.Dir(destPath)) { + return fmt.Errorf("unable to import to %s: parent directory does not exist", destPath) + } + + // parent of destination dir should be writable. + if err := os.Chmod(filepath.Dir(destPath), 0755); err != nil { + return err + } + + // If the destination path exists, remove it as was warned + if fileutil.FileExists(destPath) { + if err := os.RemoveAll(destPath); err != nil { + return fmt.Errorf("failed to cleanup %s before import: %v", destPath, err) + } + } + + if isTar(importPath) { + if err := archive.Untar(importPath, destPath, extPath); err != nil { + return fmt.Errorf("failed to extract provided archive: %v", err) + } + + return nil + } + + if isZip(importPath) { + if err := archive.Unzip(importPath, destPath, extPath); err != nil { + return fmt.Errorf("failed to extract provided archive: %v", err) + } + + return nil + } + + if err := fileutil.CopyDir(importPath, destPath); err != nil { + return err + } + + return nil +} + +// getMagentoUploadDir will return a custom upload dir if defined, returning a default path if not. +func getMagentoUploadDir(app *DdevApp) string { + if app.UploadDir == "" { + return "media" + } + + return app.UploadDir +} + +// getMagento2UploadDir will return a custom upload dir if defined, returning a default path if not. +func getMagento2UploadDir(app *DdevApp) string { + if app.UploadDir == "" { + return "media" + } + + return app.UploadDir +} + +// createMagento2SettingsFile manages creation and modification of app/etc/env.php. +func createMagento2SettingsFile(app *DdevApp) (string, error) { + + if fileutil.FileExists(app.SiteSettingsPath) { + // Check if the file is managed by ddev. + signatureFound, err := fileutil.FgrepStringInFile(app.SiteSettingsPath, DdevFileSignature) + if err != nil { + return "", err + } + + // If the signature wasn't found, warn the user and return. + if !signatureFound { + util.Warning("%s already exists and is managed by the user.", app.SiteSettingsPath) + return "", nil + } + } else { + output.UserOut.Printf("No %s file exists, creating one", app.SiteSettingsPath) + + box := packr.New("magento_packr_assets", "./magento_packr_assets") + content, err := box.Find("env.php") + if err != nil { + return "", err + } + err = ioutil.WriteFile(app.SiteSettingsPath, content, 0644) + if err != nil { + return "", err + } + } + + return app.SiteDdevSettingsFile, nil +} + +// setMagento2SiteSettingsPaths sets the paths to settings.php for templating. +func setMagento2SiteSettingsPaths(app *DdevApp) { + app.SiteSettingsPath = filepath.Join(app.AppRoot, "app", "etc", "env.php") +} + +// magento2ConfigOverrideAction overrides php_version for magento2, since it is incompatible +// with php7.3+ +func magento2ConfigOverrideAction(app *DdevApp) error { + app.PHPVersion = nodeps.PHP72 + return nil +} + +// magentoConfigOverrideAction overrides php_version for magento2, since it is incompatible +// with php7.3+ +func magentoConfigOverrideAction(app *DdevApp) error { + app.PHPVersion = nodeps.PHP56 + return nil +} diff --git a/pkg/ddevapp/magento_packr_assets/env.php b/pkg/ddevapp/magento_packr_assets/env.php new file mode 100644 index 00000000000..2d1bfdf0e7e --- /dev/null +++ b/pkg/ddevapp/magento_packr_assets/env.php @@ -0,0 +1,75 @@ + [ + 'frontName' => 'admin_y312l0' + ], + 'crypt' => [ + 'key' => '753f0833c2388eea8cb061a47ecf9686' + ], + 'db' => [ + 'table_prefix' => '', + 'connection' => [ + 'default' => [ + 'host' => 'db', + 'dbname' => 'db', + 'username' => 'db', + 'password' => 'db', + 'model' => 'mysql4', + 'engine' => 'innodb', + 'initStatements' => 'SET NAMES utf8;', + 'active' => '1' + ] + ] + ], + 'resource' => [ + 'default_setup' => [ + 'connection' => 'default' + ] + ], + 'x-frame-options' => 'SAMEORIGIN', + 'MAGE_MODE' => 'default', + 'session' => [ + 'save' => 'files' + ], + 'cache' => [ + 'frontend' => [ + 'default' => [ + 'id_prefix' => '40d_' + ], + 'page_cache' => [ + 'id_prefix' => '40d_' + ] + ] + ], + 'lock' => [ + 'provider' => 'db', + 'config' => [ + 'prefix' => NULL + ] + ], + 'cache_types' => [ + 'config' => 1, + 'layout' => 1, + 'block_html' => 1, + 'collections' => 1, + 'reflection' => 1, + 'db_ddl' => 1, + 'compiled_config' => 1, + 'eav' => 1, + 'customer_notification' => 1, + 'config_integration' => 1, + 'config_integration_api' => 1, + 'full_page' => 1, + 'config_webservice' => 1, + 'translate' => 1, + 'vertex' => 1 + ], + 'install' => [ + 'date' => 'Sun, 12 Jan 2020 22:21:37 +0000' + ] +]; diff --git a/pkg/ddevapp/magento_packr_assets/local.xml b/pkg/ddevapp/magento_packr_assets/local.xml new file mode 100755 index 00000000000..9caf08cdc16 --- /dev/null +++ b/pkg/ddevapp/magento_packr_assets/local.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + false + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + diff --git a/pkg/ddevapp/packrd/packed-packr.go b/pkg/ddevapp/packrd/packed-packr.go new file mode 100644 index 00000000000..c5c2a7bd836 --- /dev/null +++ b/pkg/ddevapp/packrd/packed-packr.go @@ -0,0 +1,32 @@ +// +build !skippackr +// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. + +// You can use the "packr2 clean" command to clean up this, +// and any other packr generated files. +package packrd + +import ( + "github.com/gobuffalo/packr/v2" + "github.com/gobuffalo/packr/v2/file/resolver" +) + +var _ = func() error { + const gk = "fbcc54b4eacd7cae19bd5ba35303b441" + g := packr.New(gk, "") + hgr, err := resolver.NewHexGzip(map[string]string{ + "e14a768e24211de4ac2dc7685905f65f": "1f8b08000000000000ff8c554d6fdb3810bdfb574cbb97b65b4b729c6f68dd18ae0378e1a440e23d1585418b23895b8ad492232bde5fbf2065c55fcaa2395933f3de3cce3c32f1979742c21a8d155afdf17e1044efbf8c7af1bb7ebff71be7b8ee67a8d030427e0be38a74c148244cca0dbc26c0d581d40993c14b217b4f58e83502e508522804b6729fda00e5c2429d6b8990e8a240452052d8e80a6aa6a8e7694883c89436d854a7422230c5416902836d4f1014f4fafd51af511a7efad4834ff0c03254a47be0bf1ebf2d6693297cbb87f96c327d7c9e6ee30bc76b7565126ce8dd67b5fa1b1372dd9dec71c2381622817b83087391a0b2081fc6f7731806d147c7423923875c558a4be4500bca1bc9254b7eb20c4128cfe55b6c152cc7f7f3805e28700c338f67d26a606b26245b497768a3ab2cf7c85a1bc9fbb5e0d8af71058c1afebf9ee6b70e9f1395b761a84b54cd69026db25036626dc852d91f065150e6a5efd60c9a8b7694098a35028344971bd0e9765dcd49ddc09941a85423ca8d14f48a985020e87f447e865222b308161d85022c98907e5eba65bf2b9a3505892ec06aa81112a61a8493b895248a02b9608472136c37f775f63c998f670fd3a736a0fd61900b72fe629c371b6c8dd3ba4bd8dc25aa32338c63eb13175258a37154db1b605fd75651653068e7d6522495255d887f7724a936aec29328446edb11184cd138cc7651755d07fb4777c0c2195da8541b77afb46a4f7a9730c24c9b0d00f84e3ed83aab0d2e27da3419373123b29c0060f2fafb43f211cea2e8b27f160d6e5ac19f61a692003e74abf2debe6b7de0fe7edd66f00bf726f4b7364eb44a4536eab9067126f58ac9e6c30784b2c4e45ec44739231cc5efbe4fbe8e17e3ef8bbcfa0cd10dfcc9149c4567110cae6f8757b717e7f07b1445d18f1fa338f4881d6d78c21b276653d2519f9fb8d9b5195ee0c5259e5f5f9e5d0e30ba1aa44376c16e86787ec3a3ab9beb0bdfc721f6da1c91c65c58778d96fe855c169a5712ed2865d2621c7627776083cdd4edf1345687011f244f551a4cc5cbee0c5ee341ea902a3ce68a39a6ac92b4b44855d9d127d14a61e20c7b9af405b9b6b413c0575e820f76d757168d62059e605e13ddb892595b6bc34f70af896e1c5f7576db86bb3142097a2646e8fe71d91df679ba80c7f1c3f4192a4aaf3dcf5169375fa139ca1d4db1b1ffc8730f6f32dd28da947bba4bae971ed8ecd8e5de1814d78b036433a56db41bc312126b1c0de270fbebd408e15b4e88c3373c14871d8e8e2d5af7fa2e2d5bef69746fb8f5420ff2cdab11ee3f1b31e38550fbd7465784e6f8d2f8aa9c8a8ee1c6cc646f6d2a355ad1e381613c9397b64b768ce794340e3b44c4e181de6dcda8e7e7eb1fcaff020000ffff90b2e114a7090000", + "f9ddd85cf91b505b1cd81fc628d986c1": "1f8b08000000000000ff94555f6fe238107fcfa718e91ef270b40da1d772edfd11d2a1aaa742a5b2fbb4aaa2893d01ab8e9db527d07cfb5508b09084ddee1bf8f7673c9edf287ffd5bac8a20b8ba82dfa4a4f5c5920c396492773029d9e6c84aa0d6151c00a879a0ad407df99eeb5afa42b95d13f08a402b438069fdd73ae095f2b059594d206c9e9361501954b6840d1aaea55b33b6a096c63a6a0499d204682418cbe0685f19145f0681232e9d812f01004098a278232343f8fb9fddd1f63873d6f01c73da0221ca5c99a41a0d631d855bd6eba0d10b5715dc56bf51d5e86eff1865d1783412f1683c26c2b148a39b215edf92c8febc19df9c7ac9b46dc4986a4a0a47997a6f1cc3c17754586348b0b2a6a56bdc28c352b7ef768057d637585d76d0c5656a0eedf7334a4fee679c02bddf58277fc4c9ad24dd10f2ca7fd5d77d24324b6576a59431b6df4a19c50b46a63a29be612fa69f603e994d17507236beef93a160b5de990fc313fc3538fdb59f95236f4b27a83db1ddab279eb82cfac6d21ada614c67eabc5f640e73bab0452dd9b734994d9f5f1e1f1ee7bb6ec2d9e4619acc9eff9b9e9aee504fde7753127adc375d2f8c6f051bc5aad3dd762dbaeb021fc89b922739be8e64d27ae9d3c184052e29e9bbc52f589e79546dc55bbbb5c2d9b592e47a925acf2c53cbbea68feacf3f3f3d9da9b7ed22e1aa20df2e7b643d3caaa8b1b225778ed3fae6c98a73dd8184d5bac995ef608e327d94b96348a689947d6e79a134c9e4ccfd08d75d4de9d9e6e4126359654a606fc1c630518669e93e4a49b0501d5a566a9dd4293967b0a1d4935b2bd165b043e33572175993636a263a3c19a2329e51ebcec2ef4dc2456906308ce17f3410477104717c170fef46b7f07b1445fbef46f07a1f7c0b0000ffff2a27880834070000", + }) + if err != nil { + panic(err) + } + g.DefaultResolver = hgr + + func() { + b := packr.New("magento_packr_assets", "./magento_packr_assets") + b.SetResolver("env.php", packr.Pointer{ForwardBox: gk, ForwardPath: "f9ddd85cf91b505b1cd81fc628d986c1"}) + b.SetResolver("local.xml", packr.Pointer{ForwardBox: gk, ForwardPath: "e14a768e24211de4ac2dc7685905f65f"}) + }() + + return nil +}() diff --git a/pkg/nodeps/values.go b/pkg/nodeps/values.go index 60a93c475b8..c97ffb28b6d 100644 --- a/pkg/nodeps/values.go +++ b/pkg/nodeps/values.go @@ -126,6 +126,8 @@ const ( AppTypePHP = "php" AppTypeTYPO3 = "typo3" AppTypeWordPress = "wordpress" + AppTypeMagento = "magento" + AppTypeMagento2 = "magento2" ) // Ports and other defaults diff --git a/pkg/testcommon/testcommon.go b/pkg/testcommon/testcommon.go index 356aa66df3e..8c0ea901ed1 100644 --- a/pkg/testcommon/testcommon.go +++ b/pkg/testcommon/testcommon.go @@ -90,11 +90,13 @@ func (site *TestSite) Prepare() error { err = os.Remove(site.Dir) util.CheckErr(err) + output.UserOut.Printf("Copying directory %s to %s\n", cachedSrcDir, site.Dir) err = fileutil.CopyDir(cachedSrcDir, site.Dir) if err != nil { site.Cleanup() return fmt.Errorf("Failed to CopyDir from %s to %s, err=%v", cachedSrcDir, site.Dir, err) } + output.UserOut.Println("Copying complete") // Create an app. Err is ignored as we may not have // a config file to read in from a test site. diff --git a/pkg/version/version.go b/pkg/version/version.go index 3aeb3b53559..ea33cd5b8fa 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -49,7 +49,7 @@ var DockerComposeFileFormatVersion = "3.6" var WebImg = "drud/ddev-webserver" // WebTag defines the default web image tag for drud dev -var WebTag = "20191126_carstendietrich_enable_xdebug" // Note that this can be overridden by make +var WebTag = "20190827_magento" // Note that this can be overridden by make // DBImg defines the default db image used for applications. var DBImg = "drud/ddev-dbserver"