Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions lib/Everyman/Neo4j/Bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
namespace Everyman\Neo4j;
use Everyman\Neo4j\Transport as BaseTransport;
//db part of the rest endpoint
DI::register("dbPath", "/db/data");

//register node creation callback
DI::register(
"Node",
function (Client $client, $properties=array()) {
return new Node($client);
}
);

//register relationship creation callback
DI::register(
"Relationship",
function (Client $client, $properties=array()) {
return new Relationship($client);
}
);

//register transport creation callback
DI::register(
"transport",
function($host='localhost', $port=7474) {
if (extension_loaded("curl")) {
return new BaseTransport\Curl($host, $port);
}
return new BaseTransport\Stream($host, $port);
},
true
);


//ensure consistency between the default ssl
//varification with curl and with http stream
DI::register(
"httpStreamOptions",
array("ssl" => array(
"verify_peer" => true,
"allow_self_signed" => false
))
);
27 changes: 22 additions & 5 deletions lib/Everyman/Neo4j/Cache/EntityCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
Everyman\Neo4j\PropertyContainer,
Everyman\Neo4j\Node,
Everyman\Neo4j\Relationship,
Everyman\Neo4j\Cache;
Everyman\Neo4j\Cache,
Everyman\Neo4j\DI;

/**
* Store and retrieve cached entities without hitting the server
Expand Down Expand Up @@ -52,7 +53,7 @@ public function getCachedEntity($id, $type)
throw new Exception('Unknown entity type: '.$type);
}

$entity = $this->getCache()->get("{$type}-{$id}");
$entity = $this->getCache()->get("{$this->resolveCacheKey($type)}-{$id}");
if ($entity) {
$entity->setClient($this->client);
}
Expand Down Expand Up @@ -98,15 +99,31 @@ protected function getCache()
* Determine the cache key used to retrieve the given entity from the cache
*
* @param PropertyContainer $entity
* @return string
* @return string
*/
protected function getEntityCacheKey(PropertyContainer $entity)
{
if ($entity instanceof Node) {
return 'node-'.$entity->getId();
return $this->resolveCacheKey('node') . '-'.$entity->getId();
} else if ($entity instanceof Relationship) {
return 'relationship-'.$entity->getId();
return $this->resolveCacheKey('relationship') . '-'.$entity->getId();
}
throw new Exception('Unknown entity type: '.get_class($entity));
}

/**
* Resolves cache key by given type. Checks if there is registered
* cache prefix for this type and returns it, otherwise it returns
* the type itself as a key
* @param string $type
* @return string
*/
protected function resolveCacheKey($type)
{
if (DI::isRegistered($type . "CachePrefix")) {
return DI::resolve($type . "CachePrefix");
}

return $type;
}
}
24 changes: 7 additions & 17 deletions lib/Everyman/Neo4j/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,18 @@ class Client
*/
public function __construct($transport=null, $port=7474)
{

try {
if ($transport === null) {
$transport = new Transport\Curl();
$transport = DI::resolve("transport");
} elseif (is_string($transport)) {
$transport = new Transport\Curl($transport, $port);
$transport = DI::resolve("transport", array($transport, $port));
}
} catch (Exception $e) {
if ($transport === null) {
$transport = new Transport\Stream();
} elseif (is_string($transport)) {
$transport = new Transport\Stream($transport, $port);
}
throw new Exception("Could not create transport object!");
}

$this->setTransport($transport);
$this->setNodeFactory(function (Client $client, $properties=array()) {
return new Node($client);
});
$this->setRelationshipFactory(function (Client $client, $properties=array()) {
return new Relationship($client);
});
}

/**
Expand Down Expand Up @@ -431,8 +422,8 @@ public function loadRelationship(Relationship $rel)
*/
public function makeNode($properties=array())
{
$nodeFactory = $this->nodeFactory;
$node = $nodeFactory($this, $properties);

$node = DI::resolve("Node", array($this, $properties));
if (!($node instanceof Node)) {
throw new Exception('Node factory did not return a Node object.');
}
Expand All @@ -447,8 +438,7 @@ public function makeNode($properties=array())
*/
public function makeRelationship($properties=array())
{
$relFactory = $this->relFactory;
$rel = $relFactory($this, $properties);
$rel = DI::resolve("Relationship", array($this, $properties));
if (!($rel instanceof Relationship)) {
throw new Exception('Relationship factory did not return a Relationship object.');
}
Expand Down
5 changes: 3 additions & 2 deletions lib/Everyman/Neo4j/Command/ExecuteCypherQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
Everyman\Neo4j\Command,
Everyman\Neo4j\Client,
Everyman\Neo4j\Cypher\Query,
Everyman\Neo4j\Query\ResultSet;
Everyman\Neo4j\Query\ResultSet,
Everyman\Neo4j\DI;

/**
* Perform a query using the Cypher query language and return the results
Expand Down Expand Up @@ -68,7 +69,7 @@ protected function getPath()
throw new Exception('Cypher unavailable');
}

return preg_replace('/^.+\/db\/data/', '', $url);
return preg_replace('/^.+' . preg_quote(DI::resolve("dbPath"), "/") .'/', '', $url);
}

/**
Expand Down
103 changes: 103 additions & 0 deletions lib/Everyman/Neo4j/DI.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
namespace Everyman\Neo4j;

/**
* A dependency injector
*/
class DI
{
/**
* Stores the registereditems
* @var array
*/
private static $register = array();

/**
* Stores resolved singletons
* @var array
*/
private static $singletons = array();

/**
*
* Register new entry for resolution
* @param string $id - resolution entry identifier
* @param mixed $value - resolution entry value
* @param bool $singleton=false - flag indicating whether the entry is singleton
*/
public static function register ($id, $value, $singleton = false)
{

static::$register[$id]['resolver'] = $value;
static::$register[$id]['singleton'] = (bool)$singleton;
}

/**
*
* Resolves registered entry and returns the resolved result
* @param string $id - the identifier of the entity to be resolved
* @param array $args - arguments if the entry to be resolved is a closure
* that expects parameters
* @throws \Exception
* @return resolved entry
*/
public static function resolve ($id, array $args = array())
{
if (!array_key_exists($id, static::$register)
&& !array_key_exists($id, static::$singletons)
) {
throw new Exception("No registry for key {$id}!");
}

//return singleton
if (array_key_exists($id, static::$singletons)) {
return static::$singletons[$id];
}


if (static::$register[$id]['resolver'] instanceof \Closure) {

//if the resolver is registered as singleton create an
//instance and keep it instead of the resolver function
if (static::$register[$id]['singleton']) {

static::$singletons[$id] = call_user_func_array(
static::$register[$id]['resolver'],
$args
);
unset(static::$register[$id]);

return static::$singletons[$id];
}

return call_user_func_array(
static::$register[$id]['resolver'],
$args
);
}

return static::$register[$id]['resolver'];
}

/**
*
* Checks if there is entry registered under a given key
* @param string $id
*/
public static function isRegistered ($id)
{
return array_key_exists($id, static::$register)
|| array_key_exists($id, static::$singletons);
}

/**
*
* Delete entry from the register
* @param string $id
*/
public static function unregister ($id)
{
unset(static::$register[$id]);
unset(static::$singletons[$id]);
}
}
6 changes: 5 additions & 1 deletion lib/Everyman/Neo4j/Transport.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public function __construct($host='localhost', $port=7474)
{
$this->host = $host;
$this->port = $port;
if (DI::isRegistered("dbPath")) {
$this->path = DI::resolve("dbPath");
}
}

/**
Expand Down Expand Up @@ -147,11 +150,12 @@ public function setAuth($username=null, $password=null)
}

/**
* Turn HTTPS on or off
* Turn HTTPS on or off and adds ssl specific options
*
* Returns this Trnasport object
*
* @param boolean $useHttps
* @param array $options
* @return Transport
*/
public function useHttps($useHttps=true)
Expand Down
9 changes: 9 additions & 0 deletions lib/Everyman/Neo4j/Transport/Curl.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ public function makeRequest($method, $path, $data=array())
break;
}

//additional curl options
if (\Everyman\Neo4j\DI::isRegistered("curlOptions")) {
$additionalOptions = \Everyman\Neo4j\DI::resolve("curlOptions");
if (is_array($additionalOptions)) {
$options = array_replace($options, $additionalOptions);
}
unset($additionalOptions);
}

$ch = $this->getHandle();
curl_setopt_array($ch, $options);

Expand Down
17 changes: 13 additions & 4 deletions lib/Everyman/Neo4j/Transport/Stream.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function makeRequest($method, $path, $data=array())
$url = $this->getEndpoint().$path;

$context_options = array (
$this->scheme => array (
'http' => array (
'method' => 'GET',
'ignore_errors' => true,
'header'=>
Expand All @@ -38,12 +38,21 @@ public function makeRequest($method, $path, $data=array())
case self::POST :
case self::PUT :
$dataString = $this->encodeData($data);
$context_options[$this->scheme]['method'] = $method;
$context_options[$this->scheme]['content'] = $dataString;
$context_options[$this->scheme]['header'] .= 'Context-Length: ' . strlen($dataString) . "\r\n";
$context_options['http']['method'] = $method;
$context_options['http']['content'] = $dataString;
$context_options['http']['header'] .= 'Context-Length: ' . strlen($dataString) . "\r\n";
break;
}

//add options for the ssl connection
if (\Everyman\Neo4j\DI::isRegistered("httpStreamOptions")) {
$streamOptions = \Everyman\Neo4j\DI::resolve("httpStreamOptions");
if (is_array($streamOptions)) {
$context_options = array_replace_recursive($context_options, $streamOptions);
}
unset($streamOptions);
}

$context = stream_context_create($context_options);
$response = file_get_contents($url, false, $context);
// $http_response_header is set by file_get_contents with the http:// wrapper
Expand Down
3 changes: 3 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ function loaderTestAutoloader($sClass)
spl_autoload_register('loaderTestAutoloader');
error_reporting(-1);
ini_set('display_errors', 1);


include __DIR__ . "/../lib/Everyman/Neo4j/Bootstrap.php";
Loading