Civi\Core\Resolver - Add "global://" support
authorTim Otten <totten@civicrm.org>
Sat, 25 Jul 2015 03:40:14 +0000 (20:40 -0700)
committerTim Otten <totten@civicrm.org>
Sat, 15 Aug 2015 10:25:58 +0000 (03:25 -0700)
Civi/Core/Resolver.php
tests/phpunit/Civi/Core/ResolverTest.php

index d35b512f5db5bc183d8d5ce3e9d5324f10f6f673..d76b5121645c1736eb183628942ac1b3716dc59d 100644 (file)
@@ -19,6 +19,8 @@ namespace Civi\Core;
  *   - 'api3://EntityName/action?first=@1&second=@2' - Call an API method, mapping the
  *     first & second args to named parameters.
  *     (Performance note: Requires parsing/interpolating arguments).
+ *   - 'global://Variable/Key2/Key3?getter' - A dummy which looks up a global variable.
+ *   - 'global://Variable/Key2/Key3?setter' - A dummy which updates a global variable.
  *   - '0' or '1' - A dummy which returns the constant '0' or '1'.
  *
  * Note: To differentiate classes and functions, there is a hard requirement that
@@ -81,6 +83,10 @@ class Resolver {
           // Callback: API.
           return new ResolverApi($url);
 
+        case 'global':
+          // Lookup in a global variable.
+          return new ResolverGlobalCallback($url['query'], $url['host'] . (isset($url['path']) ? rtrim($url['path'], '/') : ''));
+
         default:
           throw new \RuntimeException("Unsupported callback scheme: " . $url['scheme']);
       }
@@ -242,3 +248,37 @@ class ResolverApi {
   }
 
 }
+
+class ResolverGlobalCallback {
+  private $mode, $path;
+
+  /**
+   * Class constructor.
+   *
+   * @param string $mode
+   *   'getter' or 'setter'.
+   * @param string $path
+   */
+  public function __construct($mode, $path) {
+    $this->mode = $mode;
+    $this->path = $path;
+  }
+
+  /**
+   * Invoke function.
+   *
+   * @return mixed
+   */
+  public function __invoke($arg1 = NULL) {
+    if ($this->mode === 'getter') {
+      return \CRM_Utils_Array::pathGet($GLOBALS, explode('/', $this->path));
+    }
+    elseif ($this->mode === 'setter') {
+      \CRM_Utils_Array::pathSet($GLOBALS, explode('/', $this->path), $arg1);
+    }
+    else {
+      throw new \RuntimeException("Resolver failed: global:// must specify getter or setter mode.");
+    }
+  }
+
+}
index de5388fa720c5e155f24caa89e5a939630b89821..2e63dfe04e808294cbd3e51d56848c603972eb4e 100644 (file)
@@ -92,6 +92,25 @@ namespace Civi\Core {
       $this->resolver->get('call://totallyNonexistentService/ping');
     }
 
+    /**
+     * Test callback which returns a global variable.
+     */
+    public function testGlobalGetter() {
+      $_GET['resolverTest'] = 123;
+      $cb = $this->resolver->get('global://_GET/resolverTest?getter');
+      $_GET['resolverTest'] = 456;
+      $this->assertEquals(456, call_user_func($cb, 'side-effect-free'));
+      $this->assertEquals(456, $_GET['resolverTest']);
+      unset($_GET['resolverTest']);
+    }
+
+    public function testGlobalSetter() {
+      $GLOBALS['resolverTest2'] = 78;
+      $cb = $this->resolver->get('global://resolverTest2?setter');
+      call_user_func($cb, 90);
+      $this->assertEquals(90, $GLOBALS['resolverTest2']);
+    }
+
     /**
      * Test object-lookup in the container.
      */