mirror of https://github.com/adamdruppe/arsd.git
a helper file to integrate PHP components into a web.d site core
This commit is contained in:
parent
edd53e7da7
commit
2f17188201
|
@ -0,0 +1,231 @@
|
||||||
|
<?php
|
||||||
|
// FIXME: this doesn't work on Windows
|
||||||
|
// FIXME: doesn't handle arrays
|
||||||
|
// FIXME: doesn't handle nested function calls
|
||||||
|
// FIXME: no authentication for ApiProvider access is implemented
|
||||||
|
// FIXME: doesn't do ApiObjects nor nested ApiProviders right
|
||||||
|
/**************************************
|
||||||
|
* This file is meant to help integrate web.d apps
|
||||||
|
* with PHP apps that live on the same domain.
|
||||||
|
*
|
||||||
|
* It's useful for things like single sign on with a web.d core.
|
||||||
|
**************************************/
|
||||||
|
|
||||||
|
/// This provides (currently) *read-only* access to the web.d session file.
|
||||||
|
/// It needs access to the session ID cookie, so this has to live on the
|
||||||
|
/// same domain as your D app, and the D app's cookie should be set to
|
||||||
|
/// a path permissive enough to be sent here too.
|
||||||
|
///
|
||||||
|
/// Note this must also be on the same physical server as web.d (or at
|
||||||
|
/// least mount the tmp dirs to the same place), since it reads the session
|
||||||
|
/// data off the local filesystem.
|
||||||
|
///
|
||||||
|
/// TIP: you might want to use this to access your ApiProvider methods in D,
|
||||||
|
/// instead of reading the session alone.
|
||||||
|
class WebDotDSession {
|
||||||
|
/// Access and load the session
|
||||||
|
public function __construct($cookieName = "_sess_id") {
|
||||||
|
if(isset($_COOKIES[$cookieName])) {
|
||||||
|
$token = $_COOKIES[$cookieName];
|
||||||
|
|
||||||
|
$this->sessionId = hash("sha256",
|
||||||
|
$_SERVER["REMOTE_ADDR"] . "\r\n" .
|
||||||
|
$_SERVER["HTTP_USER_AGENT"] . "\r\n" .
|
||||||
|
$token);
|
||||||
|
|
||||||
|
$path = "/tmp/arsd_session_file_" . $this->sessionId;
|
||||||
|
if(file_exists($path))
|
||||||
|
$this->data =
|
||||||
|
json_decode(file_get_contents($path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public $sessionId = "";
|
||||||
|
|
||||||
|
/// The data in the session, as a PHP object. Note that any writes
|
||||||
|
/// to it will be discarded.
|
||||||
|
public $data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This provides a base for exceptions thrown by D
|
||||||
|
class WebDotDException extends Exception {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
If you've used the Javascript generated by web.d, you'll
|
||||||
|
find this very familiar; this is a port of that for the
|
||||||
|
most part.
|
||||||
|
|
||||||
|
The ApiProvider methods don't make a call directly. Instead,
|
||||||
|
they return an object that you can tweak a little, pass
|
||||||
|
to other functions, and retreive the data.
|
||||||
|
|
||||||
|
When getting synchronously, D exceptions are translated to PHP
|
||||||
|
exceptions, and the return value is returned right here. Use
|
||||||
|
the getSync() method to do this.
|
||||||
|
|
||||||
|
NOT IMPLEMENTED IN PHP
|
||||||
|
When getting asynchrously, D exceptions are sent to an onError
|
||||||
|
delegate, and successes are sent to a handler delegate. Use
|
||||||
|
the get() method to do this.
|
||||||
|
DONE WITH NOT IMPLEMENTED
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
// using it anonymously (probably the easiest way)
|
||||||
|
$result = $api->getMyData("hello")->getSync(); // it waits for the
|
||||||
|
// D to respond. Fast if
|
||||||
|
// local, but can be slow if
|
||||||
|
// accessing remote servers.
|
||||||
|
|
||||||
|
// using it with a name
|
||||||
|
$call = $api->getMyData("hello");
|
||||||
|
// you can change the returned format with a method on the object
|
||||||
|
$call->format("html");
|
||||||
|
// and now get it
|
||||||
|
$result = $call.getSync();
|
||||||
|
|
||||||
|
// you can also chain method calls in one line
|
||||||
|
$result = $api->getMyData("hello")->format("html")->getSync();
|
||||||
|
|
||||||
|
|
||||||
|
You can also change the parameters of the request. You shouldn't
|
||||||
|
need this most the time, but sometimes it's useful to have more
|
||||||
|
control.
|
||||||
|
|
||||||
|
$call = $api->getMyData("hello");
|
||||||
|
// add an additional request param
|
||||||
|
$call->setValue("my-request-param", "whatever");
|
||||||
|
$call->setMethod("POST"); // override the default HTTP verb for the call
|
||||||
|
|
||||||
|
$call->getSync(); // execute the request
|
||||||
|
|
||||||
|
|
||||||
|
But, more often than not, you can use the call pretty easily with the
|
||||||
|
anonymous one-liner.
|
||||||
|
*/
|
||||||
|
class WebDotDMethodCall {
|
||||||
|
public function __construct($apiProvider, $method, $url, $params) {
|
||||||
|
$this->apiProvider = $apiProvider;
|
||||||
|
$this->method = $method;
|
||||||
|
$this->url = $url;
|
||||||
|
$this->requestedDataFormat = "json";
|
||||||
|
$num = 0;
|
||||||
|
foreach($params as $arg) {
|
||||||
|
$this->urlargs["positional-arg-" . $num] = $arg;
|
||||||
|
$num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function format($dataFormat) {
|
||||||
|
$this->requestedDataFormat = $dataFormat;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMethod($httpMethod) {
|
||||||
|
$this->method = $httpMethod;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValue($name, $value) {
|
||||||
|
$this->urlargs[$name] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private $apiProvider;
|
||||||
|
private $url;
|
||||||
|
private $urlargs;
|
||||||
|
private $method;
|
||||||
|
private $requestedDataFormat;
|
||||||
|
|
||||||
|
public function getSync() {
|
||||||
|
$args = "";
|
||||||
|
$num = 0;
|
||||||
|
|
||||||
|
$params = $this->urlargs;
|
||||||
|
$params["envelopeFormat"] = "json";
|
||||||
|
$params["format"] = $this->requestedDataFormat;
|
||||||
|
|
||||||
|
$outputted = false;
|
||||||
|
foreach($params as $k => $arg) {
|
||||||
|
if($outputted) {
|
||||||
|
$args .= "&";
|
||||||
|
} else {
|
||||||
|
$outputted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$args .= urlencode($k);
|
||||||
|
$args .= "=";
|
||||||
|
$args .= urlencode($arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = $this->url;
|
||||||
|
|
||||||
|
if($this->method == "GET")
|
||||||
|
$url .= "?" . $args;
|
||||||
|
|
||||||
|
|
||||||
|
$ch = curl_init($url);
|
||||||
|
if($this->method == "POST") {
|
||||||
|
curl_setopt($ch, CURLOPT_POST,1);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
|
||||||
|
}
|
||||||
|
curl_setopt($ch, CURLOPT_HEADER,0);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
|
||||||
|
$data = curl_exec($ch);
|
||||||
|
|
||||||
|
$resultObj = json_decode($data);
|
||||||
|
|
||||||
|
if($resultObj == null) {
|
||||||
|
echo $data;
|
||||||
|
throw new WebDotDException("Got null JSON");
|
||||||
|
}
|
||||||
|
|
||||||
|
if($resultObj->success) {
|
||||||
|
return $resultObj->result;
|
||||||
|
} else {
|
||||||
|
// FIXME: maybe we can use type for better info?
|
||||||
|
$msg = $resultObj->type;
|
||||||
|
if(strlen($msg) > 0)
|
||||||
|
$msg .= ": ";
|
||||||
|
$msg .= $resultObj->errorMessage;
|
||||||
|
throw new WebDotDException($msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert(0); // not reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Base class for accessing web.d ApiProviders.
|
||||||
|
/// It doesn't do authentication, so you should use a subclass of it.
|
||||||
|
/// If you are on the same server as the api you are accessing, you can use
|
||||||
|
/// WebDotDLocalApiProvider, passing it a session object. This works with
|
||||||
|
/// all web.d classes, since the local authentication is built in.
|
||||||
|
///
|
||||||
|
/// Developers: you might use this as a base for your own remote classes,
|
||||||
|
/// if you are making a web service, adding some authentication or
|
||||||
|
/// custom branding. See the protected functions for available hooks.
|
||||||
|
class WebDotDApiProvider {
|
||||||
|
private $endpoint;
|
||||||
|
// The endpoint is a full URL to the base of your web.d program, with trailing slash.
|
||||||
|
// for example: http://mywebsite.com/myapp/
|
||||||
|
public function __construct($endpoint) {
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __call($name, $params = null) {
|
||||||
|
$url = $this->endpoint . $name;
|
||||||
|
|
||||||
|
return new WebDotDMethodCall($this,
|
||||||
|
strpos($name, "get") === 0 ? "GET" : "POST",
|
||||||
|
$url,
|
||||||
|
$params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides access to a *local* D ApiProvider.
|
||||||
|
class LocalWebDotDProvider extends WebDotDApiProvider {
|
||||||
|
/// Takes a WebDotDSession
|
||||||
|
public function __construct($session) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue