From 9a6ca54b40de4ba5fb9651c2ded9dcd4deafd35c Mon Sep 17 00:00:00 2001 From: Dan Wells Date: Thu, 18 May 2017 16:30:40 -0400 Subject: [PATCH 1/3] Workaround for PHP 7 Compatibility Archon's object composition technique makes heavy use of a PHP feature allowing method calls from an incompatible context. However, this ability was deprecated in PHP 5.6 and removed from PHP 7.0 [1]. Ultimately, it seems like moving over to Traits may be a logical path forward. This patch instead attempts to allow current Archon to run on PHP 7+ with the fewest changes possible. Rather than simply attempt the method call in the wrong context, we instead create a closure in the desired class, then insert our current context into that closure using bindTo. There may, of course, be a simpler way to do this. In particular, it seems messy to need to create an object only to get the closure. I do not claim to be an expert in PHP internals, but this functions, and is decently boiled down. This new technique should be supported for PHP >= 5.4.0, but this is untested. One questionable area would be the use of the getClosure method call on a parenthesized "new" object statement. I believe it is supported syntax on at least 5.6, and would be very easy to work around in any case. That said, it may be better to retain the old technique and branch within the code to suit the running version. [1] http://php.net/manual/en/migration56.deprecated.php#migration56.deprecated.incompatible-context Signed-off-by: Dan Wells --- packages/core/lib/archon.inc.php | 8 ++++++- packages/core/lib/archonobject.inc.php | 30 ++++++++++++-------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/core/lib/archon.inc.php b/packages/core/lib/archon.inc.php index f072f20..cdef6b4 100755 --- a/packages/core/lib/archon.inc.php +++ b/packages/core/lib/archon.inc.php @@ -2673,7 +2673,13 @@ public function initialize() } //$result = call_user_func(array($MixinClass, initialize)); - eval("\$result = {$MixinClass}::initialize();"); + $myMixinClass = "___{$MixinClass}___"; + if (!class_exists($myMixinClass)) { + eval("class $myMixinClass extends $MixinClass {}"); + } + $mixin = new $myMixinClass; + $closure = (new ReflectionMethod($myMixinClass, 'initialize'))->getClosure($mixin); + $result = call_user_func($closure->bindTo($this)); } } diff --git a/packages/core/lib/archonobject.inc.php b/packages/core/lib/archonobject.inc.php index e16ddae..caca4b1 100755 --- a/packages/core/lib/archonobject.inc.php +++ b/packages/core/lib/archonobject.inc.php @@ -10,20 +10,19 @@ public function callOverridden() $args = func_get_args(); $MixinClass = prev($methodInfo->Classes); - $arrStrArgs = array(); - - for($i = 0; $i < count($args); $i++) - { - $arrStrArgs[] = "\$args[{$i}]"; - } - // Simulate mixing after. if($_ARCHON->Mixins[get_class($this)]->Methods[$method]->Parameters[$MixinClass]->MixOrder == MIX_AFTER) { $prevresult = call_user_func_array(array($this, 'callOverridden'), $args); } - eval("\$result = {$MixinClass}::{$method}(" . implode(',', $arrStrArgs) . ");"); + $myMixinClass = "___{$MixinClass}___"; + if (!class_exists($myMixinClass)) { + eval("class $myMixinClass extends $MixinClass {}"); + } + $mixin = new $myMixinClass; + $closure = (new ReflectionMethod($myMixinClass, $method))->getClosure($mixin); + $result = call_user_func_array($closure->bindTo($this), $args); // Simulate mixing before. if($_ARCHON->Mixins[get_class($this)]->Methods[$method]->Parameters[$MixinClass]->MixOrder == MIX_BEFORE) @@ -234,21 +233,20 @@ public function __call($method, $args) $_ARCHON->Callstack[] = $stackmember; $MixinClass = end(end($_ARCHON->Callstack)->Classes); - $arrStrArgs = array(); - - for($i = 0; $i < count($args); $i++) - { - $arrStrArgs[] = "\$args[{$i}]"; - } - // Simulate mixing after. if($_ARCHON->Mixins[get_class($this)]->Methods[$method]->Parameters[$MixinClass]->MixOrder == MIX_AFTER) { $prevresult = call_user_func_array(array($this, 'callOverridden'), $args); } - eval("\$result = {$MixinClass}::{$method}(" . implode(',', $arrStrArgs) . ");"); //$result = call_user_func_array(array(($MixinClass) $this, $method), $args); + $myMixinClass = "___{$MixinClass}___"; + if (!class_exists($myMixinClass)) { + eval("class $myMixinClass extends $MixinClass {}"); + } + $mixin = new $myMixinClass; + $closure = (new ReflectionMethod($myMixinClass, $method))->getClosure($mixin); + $result = call_user_func_array($closure->bindTo($this), $args); // Simulate mixing before. if($_ARCHON->Mixins[get_class($this)]->Methods[$method]->Parameters[$MixinClass]->MixOrder == MIX_BEFORE) From 29f7b2bc94cd2bc6ba776547c7e10f5121167128 Mon Sep 17 00:00:00 2001 From: Dan Wells Date: Thu, 18 May 2017 16:41:42 -0400 Subject: [PATCH 2/3] Fix non-static variable access $OutputQueries is not static, so we need $this here. Older versions of PHP (<7.0) were more lax about this, particular the way we were mixing contexts. Signed-off-by: Dan Wells --- packages/core/lib/querylog.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/lib/querylog.inc.php b/packages/core/lib/querylog.inc.php index 66c8a43..6930086 100755 --- a/packages/core/lib/querylog.inc.php +++ b/packages/core/lib/querylog.inc.php @@ -5,7 +5,7 @@ public function logQuery(&$DB, $Scope, $Message, $IsManip = NULL) { $this->QueryCount++; - if($OutputQueries) + if($this->OutputQueries) { echo("\n\n$Message\n\n"); } From 19842bd6ccd1ffbfd88922cccf057cf7753307dc Mon Sep 17 00:00:00 2001 From: Dan Wells Date: Thu, 18 May 2017 16:50:05 -0400 Subject: [PATCH 3/3] Add proper PHP tag PHP no longer supports " --- packages/collections/pub/eadlist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/collections/pub/eadlist.php b/packages/collections/pub/eadlist.php index 669a5da..04c0d5b 100644 --- a/packages/collections/pub/eadlist.php +++ b/packages/collections/pub/eadlist.php @@ -36,7 +36,7 @@ { ?> &templateset=ead&disabletheme=1&output='>
-