Using SimpleSAMLPHP with Laravel Valet

Open your ~/.valet/Nginx/{site}.dev

Add the following and replace PATH_TO where ever you installed Simple SAML.

location  /simplesaml {
  alias PATH_TO/simplesamlphp/www;
  location ~ \.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.+)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass unix:/Users/YOUR_USERNAME/.valet/valet.sock;
    fastcgi_index index.php;
    include fastcgi_params;
  }
}

Run valet restart

Deploying Sage 9 / Blade Templates to WP Engine using Gitlab CI Pipelines

I was recently working on a project that was hosted on WP Engine. I wanted to use things like Composer or Yarn and after speaking to others they recommended trying out DeployBot as a continuous deployment tool. I found the platform to be quite restrictive and spent a lot of time getting it to work how I’d like.

I had been deploying to staging for months to demo to the client. When I deployed to production the theme I was using did not work. It’s a site powered by Sage 9 that uses Blade as a template engine. These templates are rendered at runtime and cached in the wp-content/uploads directory. WP Engine does not allow the PHP user to write to the system. This makes sense to prevent rogue plugins from having write access but I would expect to have the same configuration between staging and production.

Blade offers a function to compile a template which requires all functions in the templates to be valid or accessible. So any function calls to WordPress would require that WP has been loaded. WP functions will not load unless you have an active database (or at least to my knowledge). I could no longer use DeployBot because they did not support multiple containers.

I switched to Gitlab CI which is very similar to CircleCI or Bitbucket. My Gitlab configuration uses a PHP 7 CLI container that has access to a MySQL service.

I should really create a Docker container that already has all my services preinstalled and also cache Composer / Yarn dependencies to speed up the build but it deploys within a couple of minutes so I am not too bothered about this.

Couple of notes:

  1. Change the cache path to the root of your install ABSPATH . /cache/compiled in app/setup.php
  2. Create a private key that has access to your WPE install and add this as a environment variable in Gitlab CI called PRIVATE_KEY
  3. Create an environment variable in Gitlab for your WPE_INSTALL and THEME_NAME
  4. Create an environment in Gitlab CI called staging and production (case sensitive)
  5. I would suggest adding your WP Engine install as a known host instead of turning off StrictHostKeyChecking

The code is pretty self explanatory but let me know if you have any questions.

if [ "production" != "${CI_ENVIRONMENT_NAME}" ]; then
    FOLDER=/nas/content/staging
else
    FOLDER=/nas/content/live
fi

git config --global user.email "${WPE_INSTALL}@${WPE_INSTALL}.com"
git config --global user.name "${WPE_INSTALL}"
git clone git@git.wpengine.com:${CI_ENVIRONMENT_NAME}/${WPE_INSTALL}.git $FOLDER
rsync -a --exclude='.git/' --exclude='.gitignore' $(pwd)/ $FOLDER
cd $FOLDER
composer install --no-ansi --no-dev --no-interaction --optimize-autoloader --no-progress
cd ./wp-content/themes/${THEME_NAME}
yarn
yarn run build:production
cd ../../../
wp --allow-root core config --dbname=wordpress --dbuser=root --dbpass=wordpress --dbhost=mysql
wp --allow-root core install --url=${WPE_INSTALL}.dev --title=${WPE_INSTALL} --admin_user=wordpress --admin_email=${WPE_INSTALL}@${WPE_INSTALL}.com --skip-email
wp --allow-root theme activate ${THEME_NAME}/resources
wp --allow-root blade compile
rm -rf ./wp-content/themes/${THEME_NAME}/.gitignore
rm -rf .gitignore
mv .gitignoredeploy .gitignore
git add .
git commit -m "Deployment Commit"
git push origin master
image: php:7.0.18-cli

services:
  - mysql:latest

variables:
  MYSQL_DATABASE: wordpress
  MYSQL_ROOT_PASSWORD: wordpress

before_script:
  # Updates
  - curl -sL https://deb.nodesource.com/setup_6.x | bash
  - apt-get update
  - apt-get -y install libpcre3-dev zlib1g-dev libbz2-dev libpng12-dev libjpeg-dev nodejs git zip unzip curl rsync mysql-client
  - docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr
  - docker-php-ext-install zip bz2 gd mysqli pdo pdo_mysql

  # Composer
  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
  - php -r "copy('https://composer.github.io/installer.sig', 'composer-setup.sig');"
  - php -r "if (hash_file('SHA384', 'composer-setup.php') === trim(file_get_contents('composer-setup.sig'))) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
  - php composer-setup.php --install-dir=/usr/local/bin --filename=composer
  - php -r "unlink('composer-setup.php');"
  - php -r "unlink('composer-setup.sig');"

  # Install Node / Yarn
  - npm -g install yarn

  # WP CLI
  - curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
  - chmod +x wp-cli.phar
  - mv wp-cli.phar /usr/local/bin/wp
  - php -d memory_limit=512M /usr/local/bin/wp --allow-root package install git@github.com:schrapel/blade-generate.git

  # SSH
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - eval $(ssh-agent -s)
  - ssh-add <(echo "$SSH_PRIVATE_KEY")
  - mkdir -p ~/.ssh
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

deploy_staging:
  only:
    - develop
  environment:
    name: staging
    url: http://$WPE_INSTALL.staging.wpengine.com
  script: ./bin/deploy

deploy_production:
  only:
    - master
  environment:
    name: production
    url: http://$WPE_INSTALL.wpengine.com
  when:
    manual
  script: ./bin/deploy
# Ignore everything in the root except the "wp-content" & "vendor" directory.
/*
!.git
!.gitignore
!wp-content/
!vendor/

# Ignore specific files for deployment
node_modules

# Plugins
wp-content/*
!wp-content/mu-plugins/
!wp-content/plugins/
!wp-content/themes/

# Uploads
!cache/
cache/*
!cache/compiled/

# Themes
wp-content/themes/*
!wp-content/themes/amblin-theme/

# Mac-specific
.DS_Store

# Dev files
.svn

# known large file types
*.hqx
*.bin
*.exe
*.dll
*.deb
*.dmg
*.iso
*.img
*.msi
*.msp
*.msm
*.mid
*.midi
*.kar
*.mng
*.asx
*.asf
*.wmv
*.zip
*.tar
*.tgz
*.gz
*.mp4

How to modify and patch WordPress core on your live site safely using Composer patches

WordPress.org typically make a major release every 3-4 months. This usually introduces a bunch of useful features but they also fix a lot of bugs and issues people have been experiencing with the previous versions. Most of the time you probably don’t notice these problems as WordPress in general is a stable piece of software.

This can be a problem if there is a bug in WordPress that affects you. Even if the issue has been recently fixed in trunk it will not reach you until the next stable release of WordPress.

This is where Composer patches is extremely useful. It allows you make modifications to WordPress core (or any package you load via Composer) that are only applied after the package has been loaded.

You can safely modify core without forgetting what you have changed or having your changes wiped out after every new release.

A simple guide to modifying WordPress the right way

The first thing you will need to do is install WordPress via Composer. I would recommend using Roots/Bedrock for this. The project is already configured to load WordPress via Composer but also allows you to manage any dependencies (themes/plugins) via Composer too.

To install Bedrock you can open terminal and run the following command.

composer create-project roots/bedrock your-project-folder-name

Navigate to the project you have just created and run the following command to install the composer patches plugin

composer require cweagans/composer-patches

Lets create a folder in the root of our projects to store all of our patches.

mkdir patches

Now we are ready to patch our first bug in WordPress.

There is currently a bug in the Requests library that powers the WP_HTTP class and functions like wp_remote_get(), wp_remote_post(), etc. If you make a request to a resource that uses the referer URL to verify a request then it will not be passed correctly.

To fix this you can comment out line #376 in the /web/wp/wp-includes/Requests/Transport/cURL.php file. It should look like the code snippet below.

curl_setopt($this->handle, CURLOPT_URL, $url);
#curl_setopt($this->handle, CURLOPT_REFERER, $url);
curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']);
if (!empty($headers)) {
  curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers);
}

If you run a git diff command on the install of johnpbloch/wordpress it will show you the changes you have made against the master branch.

diff --git a/wp-includes/Requests/Transport/cURL.php b/wp-includes/Requests/Transport/cURL.php
index 4429edb..4f385a9 100644
--- a/wp-includes/Requests/Transport/cURL.php
+++ b/wp-includes/Requests/Transport/cURL.php
@@ -373,7 +373,7 @@ class Requests_Transport_cURL implements Requests_Transport {
                        curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000));
                }
                curl_setopt($this->handle, CURLOPT_URL, $url);
-               curl_setopt($this->handle, CURLOPT_REFERER, $url);
+               #curl_setopt($this->handle, CURLOPT_REFERER, $url);
                curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']);
                if (!empty($headers)) {
                        curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers);

If you run the command below it will parse the contents of the difference into a patch file that can be applied to our install of WordPress.

I prefer to name my patches with a reference to the ticket id on trac. When a update to WordPress is released I can check to see whether the issue has been resolved and if I can remove the patch.

git diff -p ../patches/37820.patch

The final step is to add the patches section to your composer.json file. This will tell Composer to apply the patch every time WordPress is installed. If Git fails to apply the patch it will fail and throw an error. This will usually happen if this part of the code has changed in a WordPress release.

"extra": {
  "installer-paths": {
    "web/app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
    "web/app/plugins/{$name}/": ["type:wordpress-plugin"],
    "web/app/themes/{$name}/": ["type:wordpress-theme"]
  },
  "wordpress-install-dir": "web/wp",
  "patches": {
    "johnpbloch/wordpress": {
        "wp_remote_get referrer not being sent correctly": "patches/37820.patch"
    }
  }
},

If you try to run a composer update your terminal should produce a similar output to this.

Gathering patches for root package.
Loading composer repositories with package information
Updating dependencies (including require-dev)
Gathering patches for root package.
Gathering patches for dependencies. This might take a minute.
  - Installing johnpbloch/wordpress (4.6.1)
    Loading from cache

  - Applying patches for johnpbloch/wordpress
    patches/37820.patch (wp_remote_get referrer not being sent correctly)

Generating autoload files

Congratulations. You can now safely make changes to WordPress core in a scalable way. Wherever you deploy your code and run composer install it will run the modified version of WordPress. When you are ready to remove the patch just delete the file and remove the lines from your composer.json file.