(dev/drupal#79) Fail more gracefully when attempting to install on PHP 5.x
authorTim Otten <totten@civicrm.org>
Wed, 21 Aug 2019 02:48:41 +0000 (19:48 -0700)
committerTim Otten <totten@civicrm.org>
Wed, 21 Aug 2019 02:48:41 +0000 (19:48 -0700)
Before
------

If an admin stracts the code and navigates to `/sites/all/modules/civicrm/install/index.php`, it displays
a syntax error.

After
-----

If an admin stracts the code and navigates to `/sites/all/modules/civicrm/install/index.php`, it displays
the message:

> __PHP Version Requirement__
> CiviCRM requires PHP 7.0+. The web server is running PHP 5.6.38.

Comments
--------

This is similar to https://github.com/civicrm/civicrm-drupal/pull/583

The canonical representation of the minimum PHP version is in
`$civicrm_root/CRM/Upgrade/Form.php`.  However, setting up the classloader
triggers a syntax error, so we need to read this without having access to
the classloader.

The approach herein has a few effects:

* The minimum PHP can be read from a JSON file.
* That JSON file is also used by `composer`, so you'll also get better errors when downloading that way.
* At some unknown point, the minimum will probably bump up again (7.1 or 7.2 or whatever). When that
  happens, the unit-test will ensure we keep `CRM/Upgrade/Form.php` and `composer.json` in sync.

Note: I was little concerned that the `composer.json` file might not be
available when normal installers run, so I checked the published tarballs
for D7, BD, WP, and J - in all cases, the `composer.json` looks to be
included at the expected location.

composer.json
install/index.php
tests/phpunit/CRM/Upgrade/FormTest.php [new file with mode: 0644]

index 1cfa14b776df4f5c31ba31a76b4a4d66f8aad564..f5dfe176013a6710f60c3d8d15f77ed20ae044f6 100644 (file)
@@ -34,6 +34,7 @@
   },
   "include-path": ["vendor/tecnickcom"],
   "require": {
+    "php": "~7.0",
     "dompdf/dompdf" : "0.8.*",
     "electrolinux/phpquery": "^0.9.6",
     "symfony/config": "^2.8.44 || ~3.0",
index 296f576ad609e5d95f58b281d833b3b01496f03f..585cea24ac0112f1630ee3039f728031395c1451 100644 (file)
@@ -91,6 +91,15 @@ else {
   errorDisplayPage($errorTitle, $errorMsg, FALSE);
 }
 
+$composerJsonPath = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'composer.json';
+if (file_exists($composerJsonPath)) {
+  $composerJson = json_decode(file_get_contents($composerJsonPath), 1);
+  $minPhpVer = preg_replace(';[~^];', '', $composerJson['require']['php']);
+  if (!version_compare(phpversion(), $minPhpVer, '>=')) {
+    errorDisplayPage('PHP Version Requirement', sprintf("CiviCRM requires PHP %s+. The web server is running PHP %s.", $minPhpVer, phpversion()), FALSE);
+  }
+}
+
 $pkgPath = $crmPath . DIRECTORY_SEPARATOR . 'packages';
 
 require_once $crmPath . '/CRM/Core/ClassLoader.php';
diff --git a/tests/phpunit/CRM/Upgrade/FormTest.php b/tests/phpunit/CRM/Upgrade/FormTest.php
new file mode 100644 (file)
index 0000000..a9af358
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * Class CRM_Upgrade_FormTest
+ * @group headless
+ */
+class CRM_Upgrade_FormTest extends CiviUnitTestCase {
+
+  /**
+   * "php" requirement (composer.json) should match MINIMUM_PHP_VERSION (CRM/Upgrade/Form.php).
+   */
+  public function testComposerRequirementMatch() {
+    global $civicrm_root;
+    $composerJsonPath = "{$civicrm_root}/composer.json";
+    $this->assertFileExists($composerJsonPath);
+    $composerJson = json_decode(file_get_contents($composerJsonPath), 1);
+    $composerJsonRequirePhp = preg_replace(';[~^];', '', $composerJson['require']['php']);
+    $actualMajorMinor = preg_replace(';^[\^]*(\d+\.\d+)\..*$;', '\1', $composerJsonRequirePhp);
+    $expectMajorMinor = preg_replace(';^[\^]*(\d+\.\d+)\..*$;', '\1', \CRM_Upgrade_Form::MINIMUM_PHP_VERSION);
+    $this->assertEquals($expectMajorMinor, $actualMajorMinor, "The PHP version requirements in CRM_Upgrade_Form ($expectMajorMinor) and composer.json ($actualMajorMinor) should specify same major+minor versions.");
+  }
+
+}