From af93b0896348ad1a177cbbe3b8ce93295ba954a9 Mon Sep 17 00:00:00 2001
From: Andrew Nicols <andrew@nicols.co.uk>
Date: Wed, 15 Mar 2023 21:55:40 +0800
Subject: [PATCH] Add simple environment-based PHP configuration

This adds a layer of common sense on top of the other changes I've
worked on to allow easy configuration variable setting.

Fixes #166
---
 .github/workflows/test_buildx_and_publish.yml |  2 ++
 README.md                                     | 16 +++++++++
 .../local/bin/moodle-docker-php-entrypoint    |  4 +++
 root/usr/local/bin/moodle-docker-php-ini      | 29 ++++++++++++++++
 tests/fixtures/check-ini.php                  | 34 +++++++++++++++----
 5 files changed, 79 insertions(+), 6 deletions(-)
 create mode 100755 root/usr/local/bin/moodle-docker-php-ini

diff --git a/.github/workflows/test_buildx_and_publish.yml b/.github/workflows/test_buildx_and_publish.yml
index 64c8e14..3cc2059 100644
--- a/.github/workflows/test_buildx_and_publish.yml
+++ b/.github/workflows/test_buildx_and_publish.yml
@@ -27,6 +27,8 @@ jobs:
           docker run --name test0 -d -p 8000:80 \
               -v $PWD/tests/fixtures:/var/www/html \
               -v $PWD/tests/docker-entrypoint.d:/docker-entrypoint.d \
+              -e PHP_INI-memory_limit=256M \
+              -e PHP_INI-apc.enabled=0 \
               moodle-php-apache
           docker exec test0 php /var/www/html/test.php
           docker exec test0 php /var/www/html/check-ini.php
diff --git a/README.md b/README.md
index dba7d9e..b411506 100644
--- a/README.md
+++ b/README.md
@@ -74,6 +74,22 @@ docker run \
 
 These initialization files will be executed in sorted name order as defined by the current locale, which defaults to en_US.utf8.
 
+## PHP Configuration
+
+As a lightweight alternative to a full PHP configuration file, you can specify a set of prefixed environment variables when starting your container with these variables turned into ini-format configuration.
+
+Any environment variable whose name is prefixed with `PHP_INI-` will have the prefix removed, and will be added to a new ini file before the main command starts.
+
+```
+docker run \
+    --name web0 \
+    -p 8080:80 \
+    -v $PWD/moodle:/var/www/html
+    -e PHP_INI-upload_max_filesize=200M \
+    -e PHP_INI-post_max_size=210M \
+    moodle-php-apache:latest
+```
+
 ## See also
 This container is part of a set of containers for Moodle development, see also:
 
diff --git a/root/usr/local/bin/moodle-docker-php-entrypoint b/root/usr/local/bin/moodle-docker-php-entrypoint
index 3abc465..10ee5a4 100755
--- a/root/usr/local/bin/moodle-docker-php-entrypoint
+++ b/root/usr/local/bin/moodle-docker-php-entrypoint
@@ -27,6 +27,10 @@ docker_process_init_files() {
   done
 }
 
+echo "Running PHP Configuration fetcher"
+/usr/local/bin/moodle-docker-php-ini
+echo
+
 echo "Running entrypoint files from /docker-entrypoint.d/*"
 docker_process_init_files /docker-entrypoint.d/*
 echo
diff --git a/root/usr/local/bin/moodle-docker-php-ini b/root/usr/local/bin/moodle-docker-php-ini
new file mode 100755
index 0000000..fa8cef8
--- /dev/null
+++ b/root/usr/local/bin/moodle-docker-php-ini
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+set -e
+
+echo "Checking for php configuration in environment"
+
+localinifile="/usr/local/etc/php/conf.d/10-local.ini"
+
+cat <<'EOF' > $localinifile
+; --
+; Automatically generated php ini configuration for Moodle
+; --
+
+EOF
+
+env | while IFS= read -r line; do
+  value=${line#*=}
+  fullname=${line%%=*}
+  if [[ $fullname = PHP_INI-* ]]; then
+    name=`echo $fullname | sed 's/^PHP_INI-//'`
+    echo "=> Found '${name}' with value '${value}'"
+
+    cat << EOF >> $localinifile
+; $fullname=$value
+$name = $value
+
+EOF
+  fi
+done
diff --git a/tests/fixtures/check-ini.php b/tests/fixtures/check-ini.php
index e556d68..9c2fe40 100644
--- a/tests/fixtures/check-ini.php
+++ b/tests/fixtures/check-ini.php
@@ -1,20 +1,42 @@
 <?php
 
-$uploadsEnabled = ini_get('file_uploads');
+$fileuploads = ini_get('file_uploads');
+$apcenabled = ini_get('apc.enabled');
+$memorylimit = ini_get('memory_limit');
+
+$allokay = true;
+$message = [];
+if (!empty($fileuploads)) {
+    $allokay = false;
+    $message[] = "Uploads are enabled and should be disabled.";
+    $message[] = var_export($fileuploads, true);
+}
+
+if (!empty($apcenabled)) {
+    $allokay = false;
+    $message[] = "apc.enabled is not Off (0): ({$apcenabled})";
+}
+
+if ($memorylimit !== '256M') {
+    $allokay = false;
+    $message[] = "Memory limit not set to 256M: ({$memorylimit})";
+}
 
 if (php_sapi_name() === 'cli') {
-    if (empty($uploadsEnabled)) {
+    if ($allokay) {
         echo "OK\n";
         exit(0);
     }
-    echo "Uploads are enabled and should be disabled.";
-    var_dump($uploadsEnabled);
+
+    echo implode("\n", $message) . "\n";
     exit(1);
 } else {
-    if (empty($uploadsEnabled)) {
+    if ($allokay) {
         header('HTTP/1.1 200 - OK');
         exit(0);
     }
-    header('HTTP/1.1 500 - Uploads are enabled and should be disabled: ' . var_export($uploadsEnabled, true));
+
+    header('HTTP/1.1 500 - ' . implode(", ", $message));
+    echo implode("<br>", $message);
     exit(1);
 }