diff --git a/lib/Everyman/Neo4j/Bootstrap.php b/lib/Everyman/Neo4j/Bootstrap.php new file mode 100644 index 0000000..267e1ac --- /dev/null +++ b/lib/Everyman/Neo4j/Bootstrap.php @@ -0,0 +1,44 @@ + array( + "verify_peer" => true, + "allow_self_signed" => false + )) +); \ No newline at end of file diff --git a/lib/Everyman/Neo4j/Cache/EntityCache.php b/lib/Everyman/Neo4j/Cache/EntityCache.php index 59390cc..40cf0ff 100644 --- a/lib/Everyman/Neo4j/Cache/EntityCache.php +++ b/lib/Everyman/Neo4j/Cache/EntityCache.php @@ -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 @@ -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); } @@ -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; + } } diff --git a/lib/Everyman/Neo4j/Client.php b/lib/Everyman/Neo4j/Client.php index a24230c..d6e33d5 100644 --- a/lib/Everyman/Neo4j/Client.php +++ b/lib/Everyman/Neo4j/Client.php @@ -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); - }); } /** @@ -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.'); } @@ -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.'); } diff --git a/lib/Everyman/Neo4j/Command/ExecuteCypherQuery.php b/lib/Everyman/Neo4j/Command/ExecuteCypherQuery.php index 5d6e30e..40aa4a2 100644 --- a/lib/Everyman/Neo4j/Command/ExecuteCypherQuery.php +++ b/lib/Everyman/Neo4j/Command/ExecuteCypherQuery.php @@ -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 @@ -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); } /** diff --git a/lib/Everyman/Neo4j/DI.php b/lib/Everyman/Neo4j/DI.php new file mode 100644 index 0000000..895dba1 --- /dev/null +++ b/lib/Everyman/Neo4j/DI.php @@ -0,0 +1,103 @@ +host = $host; $this->port = $port; + if (DI::isRegistered("dbPath")) { + $this->path = DI::resolve("dbPath"); + } } /** @@ -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) diff --git a/lib/Everyman/Neo4j/Transport/Curl.php b/lib/Everyman/Neo4j/Transport/Curl.php index b1eea09..a334750 100644 --- a/lib/Everyman/Neo4j/Transport/Curl.php +++ b/lib/Everyman/Neo4j/Transport/Curl.php @@ -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); diff --git a/lib/Everyman/Neo4j/Transport/Stream.php b/lib/Everyman/Neo4j/Transport/Stream.php index c295ea3..3b21688 100644 --- a/lib/Everyman/Neo4j/Transport/Stream.php +++ b/lib/Everyman/Neo4j/Transport/Stream.php @@ -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'=> @@ -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 diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 09ac34d..77be24b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -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"; \ No newline at end of file diff --git a/tests/unit/lib/Everyman/Neo4j/ClientTest.php b/tests/unit/lib/Everyman/Neo4j/ClientTest.php index d5c8b1c..b430829 100644 --- a/tests/unit/lib/Everyman/Neo4j/ClientTest.php +++ b/tests/unit/lib/Everyman/Neo4j/ClientTest.php @@ -969,7 +969,7 @@ public function testGetReferenceNode_Found_ReturnsNode() public function testNodeFactory_SetNodeFactory_ReturnsNodeFromFactory() { - $this->client->setNodeFactory(function (Client $client, $properties=array()) { + DI::register("Node", function (Client $client, $properties=array()) { return new NodeFactoryTestClass_ClientTest($client); }); @@ -977,15 +977,9 @@ public function testNodeFactory_SetNodeFactory_ReturnsNodeFromFactory() $this->assertInstanceOf('Everyman\Neo4j\NodeFactoryTestClass_ClientTest', $node); } - public function testNodeFactory_SetNodeFactory_NotCallable_ThrowsException() - { - $this->setExpectedException('Everyman\Neo4j\Exception'); - $this->client->setNodeFactory('bar'); - } - public function testNodeFactory_NodeFactoryReturnsNotNode_ThrowsException() { - $this->client->setNodeFactory(function (Client $client, $properties=array()) { + DI::register("Node", function (Client $client, $properties=array()) { return new \stdClass(); }); @@ -995,7 +989,7 @@ public function testNodeFactory_NodeFactoryReturnsNotNode_ThrowsException() public function testRelationshipFactory_SetRelationshipFactory_ReturnsRelationshipFromFactory() { - $this->client->setRelationshipFactory(function (Client $client, $properties=array()) { + DI::register("Relationship", function (Client $client, $properties=array()) { return new RelFactoryTestClass_ClientTest($client); }); @@ -1003,21 +997,44 @@ public function testRelationshipFactory_SetRelationshipFactory_ReturnsRelationsh $this->assertInstanceOf('Everyman\Neo4j\RelFactoryTestClass_ClientTest', $rel); } - public function testRelationshipFactory_SetRelationshipFactory_NotCallable_ThrowsException() - { - $this->setExpectedException('Everyman\Neo4j\Exception'); - $this->client->setRelationshipFactory('bar'); - } - public function testRelationshipFactory_RelationshipFactoryReturnsNotRelationship_ThrowsException() { - $this->client->setRelationshipFactory(function (Client $client, $properties=array()) { + DI::register("Relationship", function (Client $client, $properties=array()) { return new \stdClass(); }); $this->setExpectedException('Everyman\Neo4j\Exception'); $rel = $this->client->makeRelationship(); } + + public function tearDown() + { + DI::register( + "Node", + function (Client $client, $properties=array()) { + return new Node($client); + } + ); + + DI::register( + "Relationship", + function (Client $client, $properties=array()) { + return new Relationship($client); + } + ); + + DI::unregister("transport"); + DI::register( + "transport", + function($host='localhost', $port=7474) { + if (extension_loaded("curl")) { + return new \Everyman\Neo4j\Transport\Curl($host, $port); + } + return new \Everyman\Neo4j\Transport\Stream($host, $port); + }, + true + ); + } } class NodeFactoryTestClass_ClientTest extends Node {} diff --git a/tests/unit/lib/Everyman/Neo4j/DITest.php b/tests/unit/lib/Everyman/Neo4j/DITest.php new file mode 100644 index 0000000..34b49aa --- /dev/null +++ b/tests/unit/lib/Everyman/Neo4j/DITest.php @@ -0,0 +1,64 @@ +assertEquals(DI::resolve("testScalar"), 42); + DI::unregister("testScalar"); + } + + public function testRegisterClosure() + { + DI::register("testClosure", function() { + return 42; + }); + + $this->assertEquals(DI::resolve("testClosure"), 42); + DI::unregister("testClosure"); + + DI::register("testClosureWithParams", function ($a, $b) { + return $a+$b; + }); + + $this->assertEquals(DI::resolve("testClosureWithParams", array(2,40)), 42); + DI::unregister("testClosureWithParams"); + } + + public function testSingleton() + { + DI::register("testSingleton", function() {return new \StdClass();}, true); + + $singleton1 = DI::resolve("testSingleton"); + $singleton1->test = 42; + + $singleton2 = DI::resolve("testSingleton"); + $this->assertEquals($singleton2->test, 42); + + $singleton2->test++; + $this->assertEquals($singleton1->test, 43); + + DI::unregister("testSingleton"); + } + + public function testUnregister() + { + DI::register("testScalar", 42); + $this->assertTrue(DI::isRegistered("testScalar")); + + DI::unregister("testScalar"); + $this->assertFalse(DI::isRegistered("testScalar")); + + } + + public function testExceptionForUnexistingEntry() + { + $this->setExpectedException('Everyman\Neo4j\Exception'); + DI::resolve("unexistingEntry"); + } + +} \ No newline at end of file