Repository: jadell/neo4jphp Branch: master Commit: 6021d88dfa70 Files: 135 Total size: 416.3 KB Directory structure: gitextract_0kzioh7m/ ├── .gitignore ├── .travis.yml ├── LICENSE ├── Neo4jPhpVersionTask.php ├── README.md ├── build.xml ├── composer.json ├── docblox.dist.xml ├── examples/ │ ├── bacon.php │ ├── batch_benchmarks.php │ ├── cypher.php │ ├── directions.php │ ├── example_bootstrap.php │ ├── gremlin.php │ ├── indexing.php │ └── widgets.php ├── lib/ │ └── Everyman/ │ └── Neo4j/ │ ├── Batch/ │ │ ├── AddTo.php │ │ ├── Delete.php │ │ ├── Operation.php │ │ ├── RemoveFrom.php │ │ └── Save.php │ ├── Batch.php │ ├── Cache/ │ │ ├── EntityCache.php │ │ ├── Memcache.php │ │ ├── Memcached.php │ │ ├── None.php │ │ └── Variable.php │ ├── Cache.php │ ├── Client.php │ ├── Command/ │ │ ├── AddLabels.php │ │ ├── AddStatementsToTransaction.php │ │ ├── AddToIndex.php │ │ ├── Batch/ │ │ │ ├── AddToIndex.php │ │ │ ├── Command.php │ │ │ ├── Commit.php │ │ │ ├── CreateNode.php │ │ │ ├── CreateRelationship.php │ │ │ ├── DeleteNode.php │ │ │ ├── DeleteRelationship.php │ │ │ ├── RemoveFromIndex.php │ │ │ ├── UpdateNode.php │ │ │ └── UpdateRelationship.php │ │ ├── CreateNode.php │ │ ├── CreateRelationship.php │ │ ├── DeleteIndex.php │ │ ├── DeleteNode.php │ │ ├── DeleteRelationship.php │ │ ├── ExecuteCypherQuery.php │ │ ├── ExecuteGremlinQuery.php │ │ ├── ExecutePagedTraversal.php │ │ ├── ExecuteTraversal.php │ │ ├── GetIndexes.php │ │ ├── GetLabels.php │ │ ├── GetNode.php │ │ ├── GetNodeRelationships.php │ │ ├── GetNodesForLabel.php │ │ ├── GetPaths.php │ │ ├── GetRelationship.php │ │ ├── GetRelationshipTypes.php │ │ ├── GetServerInfo.php │ │ ├── QueryIndex.php │ │ ├── RemoveFromIndex.php │ │ ├── RemoveLabels.php │ │ ├── RollbackTransaction.php │ │ ├── SaveIndex.php │ │ ├── SearchIndex.php │ │ ├── SetLabels.php │ │ ├── UpdateNode.php │ │ └── UpdateRelationship.php │ ├── Command.php │ ├── Cypher/ │ │ └── Query.php │ ├── EntityMapper.php │ ├── Exception.php │ ├── Geoff/ │ │ ├── Exporter.php │ │ └── Importer.php │ ├── Geoff.php │ ├── Gremlin/ │ │ └── Query.php │ ├── Index/ │ │ ├── NodeFulltextIndex.php │ │ ├── NodeIndex.php │ │ └── RelationshipIndex.php │ ├── Index.php │ ├── Label.php │ ├── Node.php │ ├── Pager.php │ ├── Path.php │ ├── PathFinder.php │ ├── PropertyContainer.php │ ├── Query/ │ │ ├── ResultSet.php │ │ └── Row.php │ ├── Query.php │ ├── Relationship.php │ ├── Transaction.php │ ├── Transport/ │ │ ├── Curl.php │ │ └── Stream.php │ ├── Transport.php │ ├── Traversal.php │ └── Version.php ├── phpconfig.ini ├── stub.php └── tests/ ├── cs/ │ └── ruleset.xml ├── phpunit.xml └── unit/ └── lib/ └── Everyman/ └── Neo4j/ ├── BatchTest.php ├── Cache/ │ ├── MemcacheTest.php │ ├── MemcachedTest.php │ ├── NoneTest.php │ └── VariableTest.php ├── ClientTest.php ├── Client_Batch_IndexTest.php ├── Client_Batch_NodeTest.php ├── Client_Batch_RelationshipTest.php ├── Client_CacheTest.php ├── Client_CypherTest.php ├── Client_GremlinTest.php ├── Client_IndexTest.php ├── Client_LabelTest.php ├── Client_PathTest.php ├── Client_TransactionTest.php ├── Client_TraversalTest.php ├── Cypher/ │ └── QueryTest.php ├── EntityMapperTest.php ├── GeoffTest.php ├── Gremlin/ │ └── QueryTest.php ├── IndexTest.php ├── LabelTest.php ├── NodeTest.php ├── PagerTest.php ├── PathFinderTest.php ├── PathTest.php ├── PropertyContainerTest.php ├── Query/ │ ├── ResultSetTest.php │ └── RowTest.php ├── RelationshipTest.php ├── TransactionTest.php ├── TransportTest.php └── TraversalTest.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ neo4jphp.phar build docs vendor/ /.idea/ composer.lock ================================================ FILE: .travis.yml ================================================ language: php php: - 5.3 - 5.4 - 5.5 before_script: - pecl install -f memcached-2.1.0 - phpenv config-add phpconfig.ini - composer install --dev script: ./vendor/bin/phing ci ================================================ FILE: LICENSE ================================================ All project code is licensed under the MIT License http://www.opensource.org/licenses/mit-license.php Copyright (c) 2011 Josh Adell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Neo4jPhpVersionTask.php ================================================ property = $name; } public function main() { $version = \Everyman\Neo4j\Version::CURRENT; $this->log("neo4jphp version: $version"); $this->project->setProperty($this->property, $version); } } ================================================ FILE: README.md ================================================ Neo4jPHP ======== Author: Josh Adell Copyright (c) 2011-2012 PHP Wrapper for the Neo4j graph database REST interface In-depth documentation and examples: http://github.com/jadell/neo4jphp/wiki API documentation: http://jadell.github.com/neo4jphp [![Build Status](https://secure.travis-ci.org/jadell/neo4jphp.png?branch=master)](http://travis-ci.org/jadell/neo4jphp) Install ------- ### Using Composer 1. From the command line `composer require "everyman/neo4jphp" "dev-master"` 1. In your PHP script `require("vendor/autoload.php");` Connection Test --------------- Create a script named `neo4jphp_connect_test.php`: ```php getServerInfo()); ``` Change `localhost` or `7474` to the host name and port of your Neo4j instance. Execute the script: > php neo4jphp_connect_test.php If you see your server's information, then you have successfully connected! Get Started ----------- Full documentation on all the features of Neo4jPHP is available on the wiki: https://github.com/jadell/neo4jphp/wiki Contributions ------------- http://github.com/jadell/neo4jphp/graphs/contributors All contributions are welcome! If you wish to contribute, please read the following guidelines: * Before implementing new features, [open an issue](https://github.com/jadell/neo4jphp/issues) describing the feature. * Include unit tests for any bug fixes or new features. * Include only one bug fix or new feature per pull request. * Make sure all unit tests run before submitting a pull request. * Follow the coding style of the existing code: tabs for indentation, class/method braces on newlines, spaces after commas, etc. * Contributing code means that you agree that any contributed code, documentation, or other artifacts may be released under the same license as the rest of the library. ### Quick Contributor Setup Install the developer tools: > composer install --dev After making your changes, run the unit tests and code style checker: > vendor/bin/phing ci Run only unit tests: > vendor/bin/phing test Run only style checker: > vendor/bin/phing cs Pull requests will not be accepted unless all tests pass and all code meets the existing style guidelines. ### Special Thanks * Jacob Hansson - Cypher query support * Nigel Small - GEOFF import/export * [http://py2neo.org/](http://py2neo.org/) Changes ------- 0.1.0 * Cypher and Gremlin results handle nested arrays of nodes/relationships * Batch request with no operations succeeds * Delete index where index does not exist succeeds 0.0.7-beta * Retrieve reference node in one operation * Find and return only the first matching relationship * Optionally use HTTPS and basic authentication * Keep index configuration when retrieved from server * Add Memcache caching plugin * Do not allow use if cUrl is not detected * PHAR is uncompressed by default 0.0.6-beta * Create full-text indexes; easier instantiation of common index types * Client can be initialized with a string and port instead of a Transport object * Setting a `null` property has the same effect as removing the property * Handle scalar values from Gremlin scripts properly * Cypher and Gremlin queries can take an array of named parameters * Cypher no longer uses positional parameters * Use server info to determine Cypher plugin endpoint 0.0.5-beta * Open a batch on the client to apply to all subsequent data manipulation calls * Batch operations correctly set and update locally cached entities * Method chaining on node and relationship save, load and delete * Instantiate new nodes and relationships from the client * Change to cache initialization; new EntityCache object 0.0.4-beta * Client::getServerInfo() retrieves server information and connection test * Add to index brought up to Neo4j server 1.5 specification * Return paths from Cypher queries * Properly encode URL entities * Connection and transport errors throw exceptions * Fix "unable to connect" bug from returning false positive ================================================ FILE: build.xml ================================================ ================================================ FILE: composer.json ================================================ { "name": "everyman/neo4jphp", "type": "library", "description": "Wrapper for the Neo4j graph database REST interface", "keywords": ["neo4j","graph","database"], "homepage": "http://github.com/jadell/neo4jphp/wiki", "license": "MIT", "authors": [ {"name": "Josh Adell", "email": "josh.adell@gmail.com", "homepage": "http://joshadell.com"} ], "require": { "php": ">=5.3.0", "ext-curl": "*" }, "require-dev": { "phing/phing": "2.6.*", "phpunit/phpunit": "3.7.*", "squizlabs/php_codesniffer": "1.5.*" }, "autoload": { "psr-0": {"Everyman\\Neo4j":"lib/"} } } ================================================ FILE: docblox.dist.xml ================================================ lib docs docs ================================================ FILE: examples/bacon.php ================================================ #!/usr/bin/env php Find a path from one actor to another. HELP; exit(0); } $client = new Client(); $actors = new NodeIndex($client, 'actors'); // Initialize the data if ($cmd == 'init') { $keanu = $client->makeNode()->setProperty('name', 'Keanu Reeves')->save(); $laurence = $client->makeNode()->setProperty('name', 'Laurence Fishburne')->save(); $jennifer = $client->makeNode()->setProperty('name', 'Jennifer Connelly')->save(); $kevin = $client->makeNode()->setProperty('name', 'Kevin Bacon')->save(); $actors->add($keanu, 'name', $keanu->getProperty('name')); $actors->add($laurence, 'name', $laurence->getProperty('name')); $actors->add($jennifer, 'name', $jennifer->getProperty('name')); $actors->add($kevin, 'name', $kevin->getProperty('name')); $matrix = $client->makeNode()->setProperty('title', 'The Matrix')->save(); $higherLearning = $client->makeNode()->setProperty('title', 'Higher Learning')->save(); $mysticRiver = $client->makeNode()->setProperty('title', 'Mystic River')->save(); $keanu->relateTo($matrix, 'IN')->save(); $laurence->relateTo($matrix, 'IN')->save(); $laurence->relateTo($higherLearning, 'IN')->save(); $jennifer->relateTo($higherLearning, 'IN')->save(); $laurence->relateTo($mysticRiver, 'IN')->save(); $kevin->relateTo($mysticRiver, 'IN')->save(); // Find a path } else if ($cmd == 'path' && !empty($argv[2]) && !empty($argv[3])) { $from = $argv[2]; $to = $argv[3]; $fromNode = $actors->findOne('name', $from); if (!$fromNode) { echo "$from not found\n"; exit(1); } $toNode = $actors->findOne('name', $to); if (!$toNode) { echo "$to not found\n"; exit(1); } // Each degree is an actor and movie node $maxDegrees = 6; $depth = $maxDegrees * 2; $path = $fromNode->findPathsTo($toNode) ->setmaxDepth($depth) ->getSinglePath(); if ($path) { foreach ($path as $i => $node) { if ($i % 2 == 0) { $degree = $i/2; echo str_repeat("\t", $degree); echo $degree . ': ' .$node->getProperty('name'); if ($i+1 != count($path)) { echo " was in "; } } else { echo $node->getProperty('title') . " with\n"; } } echo "\n"; } } ================================================ FILE: examples/batch_benchmarks.php ================================================ #!/usr/bin/env php benchmark($series, $runs); } //////////////////////////////////////////////////////////////////////////////// // Benchmark trials /////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// abstract class Benchmark { protected $client = null; protected $title = 'unknown'; abstract protected function batch($size); abstract protected function sequential($size); public function __construct(Client $client) { $this->client = $client; } public function benchmark($series, $runs) { echo "Benchmark: {$this->title}\n"; foreach ($series as $size) { $batchTotal = 0; $seqTotal = 0; for ($i=0; $i<$runs; $i++) { echo "{$size}\t{$i}\t"; $batchTotal += $batchTime = $this->batch($size); echo "{$batchTime}\t"; $seqTotal += $seqTime = $this->sequential($size); echo "{$seqTime}\n"; } $batchAvg = round($batchTotal/$runs,2); $seqAvg = round($seqTotal/$runs,2); echo "\t\t$batchAvg\t$seqAvg\n\n"; } } } class CreateNode extends Benchmark { protected $title = 'Create nodes'; protected function batch($size) { $start = time(); $this->client->startBatch(); foreach(range(1, $size) as $id) { $this->client->makeNode()->setProperty('stop_id', $id)->save(); } $this->client->commitBatch(); $end = time(); return $end - $start; } protected function sequential($size) { $start = time(); foreach(range(1, $size) as $id) { $this->client->makeNode()->setProperty('stop_id', $id)->save(); } $end = time(); return $end - $start; } } class CreateRelationship extends Benchmark { protected $title = 'Create relationships'; protected function batch($size) { $nodeA = $this->client->makeNode()->save(); $nodeB = $this->client->makeNode()->save(); $start = time(); $this->client->startBatch(); foreach(range(1, $size) as $id) { $nodeA->relateTo($nodeB, 'TEST')->setProperty('stop_id', $id)->save(); } $this->client->commitBatch(); $end = time(); return $end - $start; } protected function sequential($size) { $nodeA = $this->client->makeNode()->save(); $nodeB = $this->client->makeNode()->save(); $start = time(); foreach(range(1, $size) as $id) { $nodeA->relateTo($nodeB, 'TEST')->setProperty('stop_id', $id)->save(); } $end = time(); return $end - $start; } } class CreateFullRelationship extends Benchmark { protected $title = 'Create full relationships (start node, end node, relationship)'; protected function batch($size) { $start = time(); $this->client->startBatch(); foreach(range(1, $size) as $id) { $nodeA = $this->client->makeNode()->save(); $nodeB = $this->client->makeNode()->save(); $nodeA->relateTo($nodeB, 'TEST')->setProperty('stop_id', $id)->save(); } $this->client->commitBatch(); $end = time(); return $end - $start; } protected function sequential($size) { $start = time(); foreach(range(1, $size) as $id) { $nodeA = $this->client->makeNode()->save(); $nodeB = $this->client->makeNode()->save(); $nodeA->relateTo($nodeB, 'TEST')->setProperty('stop_id', $id)->save(); } $end = time(); return $end - $start; } } ================================================ FILE: examples/cypher.php ================================================ #!/usr/bin/env php Get a list of all actors in the movie. HELP; exit(0); } $client = new Client(); $actors = new NodeIndex($client, 'actors'); // Initialize the data if ($cmd == 'init') { $keanu = $client->makeNode()->setProperty('name', 'Keanu Reeves')->save(); $laurence = $client->makeNode()->setProperty('name', 'Laurence Fishburne')->save(); $jennifer = $client->makeNode()->setProperty('name', 'Jennifer Connelly')->save(); $kevin = $client->makeNode()->setProperty('name', 'Kevin Bacon')->save(); $actors->add($keanu, 'name', $keanu->getProperty('name')); $actors->add($laurence, 'name', $laurence->getProperty('name')); $actors->add($jennifer, 'name', $jennifer->getProperty('name')); $actors->add($kevin, 'name', $kevin->getProperty('name')); $matrix = $client->makeNode()->setProperty('title', 'The Matrix')->save(); $higherLearning = $client->makeNode()->setProperty('title', 'Higher Learning')->save(); $mysticRiver = $client->makeNode()->setProperty('title', 'Mystic River')->save(); $keanu->relateTo($matrix, 'IN')->save(); $laurence->relateTo($matrix, 'IN')->save(); $laurence->relateTo($higherLearning, 'IN')->save(); $jennifer->relateTo($higherLearning, 'IN')->save(); $laurence->relateTo($mysticRiver, 'IN')->save(); $kevin->relateTo($mysticRiver, 'IN')->save(); // Find all actors in a movie } else if ($cmd == 'actors') { if(!empty($argv[2])) { $movie = implode(" ", array_slice($argv,2)); } else { $movie = "The Matrix"; } $queryTemplate = "START actor=node:actors('name:*') ". "MATCH (actor) -[:IN]- (movie)". "WHERE movie.title = {title}". "RETURN actor"; $query = new Cypher\Query($client, $queryTemplate, array('title'=>$movie)); $result = $query->getResultSet(); echo "Found ".count($result)." actors:\n"; foreach($result as $row) { echo " ".$row['actor']->getProperty('name')."\n"; } } ================================================ FILE: examples/directions.php ================================================ #!/usr/bin/env php [] Find a path from one node to another. algorithm is optional, and can be one of: optimal: Find the shortest paths by distance. Default. simple: Find the shortest paths by number of nodes. all: Find all paths, regardless of length. HELP; exit(0); } $client = new Client(); $intersections = new NodeIndex($client, 'intersections1'); $inters = array( 'A'=>null, 'B'=>null, 'C'=>null, 'D'=>null, 'E'=>null, 'F'=>null, ); $streets = array( // name, start, end, direction, travel time array('A', 'B', array('direction'=>'east', 'distance'=>2.1, 'name'=>'AB')), array('A', 'D', array('direction'=>'south', 'distance'=>2.1, 'name'=>'AD')), array('A', 'E', array('direction'=>'south', 'distance'=>3.1, 'name'=>'AE')), array('B', 'A', array('direction'=>'west', 'distance'=>2.1, 'name'=>'AB')), array('B', 'C', array('direction'=>'east', 'distance'=>2.1, 'name'=>'BC')), array('B', 'E', array('direction'=>'south', 'distance'=>2.1, 'name'=>'BE')), array('C', 'B', array('direction'=>'west', 'distance'=>2.1, 'name'=>'BC')), array('C', 'F', array('direction'=>'south', 'distance'=>1.1, 'name'=>'CF')), array('D', 'A', array('direction'=>'north', 'distance'=>2.1, 'name'=>'AD')), array('D', 'E', array('direction'=>'east', 'distance'=>2.1, 'name'=>'DE')), array('E', 'D', array('direction'=>'west', 'distance'=>2.1, 'name'=>'DE')), array('E', 'B', array('direction'=>'north', 'distance'=>2.1, 'name'=>'BE')), array('F', 'C', array('direction'=>'north', 'distance'=>1.1, 'name'=>'CF')), array('F', 'E', array('direction'=>'west', 'distance'=>2.1, 'name'=>'FE')), ); $turns = array( 'east' => array( 'north' => 'left', 'south' => 'right', 'west' => 'u-turn', ), 'west' => array( 'north' => 'right', 'south' => 'left', 'east' => 'u-turn', ), 'north' => array( 'east' => 'right', 'west' => 'left', 'south' => 'u-turn', ), 'south' => array( 'east' => 'left', 'west' => 'right', 'north' => 'u-turn', ), ); // Initialize the data if ($cmd == 'init') { echo "Initializing data.\n"; foreach ($inters as $inter => $temp) { $node = $client->makeNode()->setProperty('name', $inter)->save(); $intersections->add($node, 'name', $node->getProperty('name')); $inters[$inter] = $node; } foreach ($streets as $info) { $start = $inters[$info[0]]; $end = $inters[$info[1]]; $properties = $info[2]; $street = $start->relateTo($end, 'CONNECTS')->setProperties($properties); $street->save(); } // Find a path } else if ($cmd == 'path' && !empty($argv[2]) && !empty($argv[3])) { $from = $argv[2]; $to = $argv[3]; $algorithm = null; $all = !empty($argv[4]) && $argv[4] == 'all'; $fromNode = $intersections->findOne('name', $from); $toNode = $intersections->findOne('name', $to); $finder = $fromNode->findPathsTo($toNode, 'CONNECTS', Relationship::DirectionOut) ->setMaxDepth(5); $algorithm = !empty($argv[4]) ? $argv[4] : null; // Find all paths regardless of complexity or distance if ($algorithm == 'all') { $finder->setAlgorithm(PathFinder::AlgoAllSimple); // Find paths with the smallest number of instructions } else if ($algorithm == 'simple') { $finder->setAlgorithm(PathFinder::AlgoShortest); // Find the most optimal paths } else { $finder->setAlgorithm(PathFinder::AlgoDijkstra) ->setCostProperty('distance'); } $paths = $finder->getPaths(); } echo << B <-2-> C ^\ ^ ^ | \ | | | \ | | | \ | | 2 3\ 2 1 | \ | | | \| | V V V D <-2-> E <-2-- F MAP; echo "\n\n"; foreach ($paths as $i => $path) { $path->setContext(Path::ContextRelationship); $prevDirection = null; $totalDistance = 0; echo "Path " . ($i+1) .":\n"; foreach ($path as $j => $rel) { $direction = $rel->getProperty('direction'); $distance = $rel->getProperty('distance'); $name = $rel->getProperty('name'); if (!$prevDirection) { $action = 'Head'; } else if ($prevDirection == $direction) { $action = 'Continue'; } else { $turn = $turns[$prevDirection][$direction]; $action = "Turn $turn, and continue"; } $prevDirection = $direction; $step = $j+1; $totalDistance += $distance; echo "\t{$step}: {$action} {$direction} on {$name} for {$distance} miles.\n"; } echo "\tTravel distance: {$totalDistance}\n\n"; } ================================================ FILE: examples/example_bootstrap.php ================================================ makeNode()->setProperty('name', 'Keanu Reeves')->save(); $laurence = $client->makeNode()->setProperty('name', 'Laurence Fishburne')->save(); $jennifer = $client->makeNode()->setProperty('name', 'Jennifer Connelly')->save(); $kevin = $client->makeNode()->setProperty('name', 'Kevin Bacon')->save(); $actors->add($keanu, 'name', $keanu->getProperty('name')); $actors->add($laurence, 'name', $laurence->getProperty('name')); $actors->add($jennifer, 'name', $jennifer->getProperty('name')); $actors->add($kevin, 'name', $kevin->getProperty('name')); $matrix = $client->makeNode()->setProperty('title', 'The Matrix')->save(); $higherLearning = $client->makeNode()->setProperty('title', 'Higher Learning')->save(); $mysticRiver = $client->makeNode()->setProperty('title', 'Mystic River')->save(); $keanu->relateTo($matrix, 'IN')->save(); $laurence->relateTo($matrix, 'IN')->save(); $laurence->relateTo($higherLearning, 'IN')->save(); $jennifer->relateTo($higherLearning, 'IN')->save(); $laurence->relateTo($mysticRiver, 'IN')->save(); $kevin->relateTo($mysticRiver, 'IN')->save(); // Find all actors in a movie } else if ($cmd == 'actors') { $queryTemplate = "g.V.in(type).dedup.sort{it.name}.toList()"; $params = array('type' => 'IN'); $query = new Gremlin\Query($client, $queryTemplate, $params); $result = $query->getResultSet(); foreach ($result as $row) { echo "* " . $row[0]->getProperty('name')."\n"; } } ================================================ FILE: examples/indexing.php ================================================ #!/usr/bin/env php save(); $leslie = $client->makeNode() ->setProperty('name', 'Leslie Nielsen') ->save(); $airplane = $client->makeNode() ->setProperty('title', 'Airplane') ->save(); $rumack = $leslie->relateTo($airplane, 'PLAYED') ->setProperty('character', 'Dr. Rumack') ->save(); $actorIndex->add($leslie, 'name', $leslie->getProperty('name')); $roleIndex->add($rumack, 'character', $rumack->getProperty('character')); $plotIndex->add($airplane, 'synopsis', 'An airplane crew takes ill. Surely the only person capable of landing the plane is an ex-pilot afraid to fly. But don\'t call him Shirley.'); echo $actorIndex->queryOne('name:Leslie*')->getProperty('name') . "\n"; echo $roleIndex->queryOne('character:*u*')->getProperty('character') . "\n"; echo $plotIndex->queryOne('synopsis:lend~0.2')->getProperty('title') . "\n"; ================================================ FILE: examples/widgets.php ================================================ #!/usr/bin/env php [] Find all the stores where the given part was sold. Language can be one of: traverse: use the javascript traversal. Default. cypher: use a cypher query HELP; exit(0); } $client = new Client(); $partsIndex = new NodeIndex($client, 'parts3'); $parts = array('widget','gadget','gizmo'); $stores = array("Bob's Old Houseware","Mainstreet Hardware","Nutz N' Boltz", "Doodad Emporium"); // Store, part list $orders = array( array(0, array(0,1)), array(0, array(1)), array(1, array(1,2)), array(1, array(0,2)), array(2, array(0,1,2)), array(3, array(2)), array(3, array(0)), ); // Initialize the data if ($cmd == 'init') { echo "Initializing data.\n"; $p = array(); $s = array(); foreach ($parts as $part) { $node = $client->makeNode()->setProperty('name', $part)->save(); $partsIndex->add($node, 'name', $node->getProperty('name')); $p[] = $node; } foreach ($stores as $store) { $node = $client->makeNode()->setProperty('name', $store)->save(); $s[] = $node; } foreach ($orders as $order) { $node = $client->makeNode()->save(); $s[$order[0]]->relateTo($node, 'SOLD')->save(); foreach ($order[1] as $pi) { $node->relateTo($p[$pi], 'CONTAINS')->save(); } } // List parts } else if ($cmd == 'parts') { $partsList = $partsIndex->query('name:*'); foreach ($partsList as $part) { echo "* {$part->getProperty('name')}\n"; } // Find stores where the part was sold } else if ($cmd == 'stores' && !empty($argv[2])) { $partName = $argv[2]; // Use the Cypher query language if (!empty($argv[3]) && $argv[3] == 'cypher') { $queryTemplate = "START part=node:parts3('name:{$partName}') ". "MATCH (store)-[:SOLD]->()-[:CONTAINS]->(part) ". // Use the count(*) to force distinct values until Cypher gets DISTINCT keyword support "RETURN store, count(*)"; $query = new Cypher\Query($client, $queryTemplate); $result = $query->getResultSet(); echo "Found ".count($result)." stores:\n"; foreach($result as $row) { echo "* ".$row['store']->getProperty('name')."\n"; } // Use javascript traversal } else { $part = $partsIndex->findOne('name', $partName); if (!$part) { die("{$partName} not found.\n"); } $traversal = new Traversal($client); $traversal->addRelationship('CONTAINS', Relationship::DirectionIn) ->addRelationship('SOLD', Relationship::DirectionIn) ->setMaxDepth(4) ->setReturnFilter('javascript', '(position.length() > 0 && position.lastRelationship().getType() == "SOLD");'); $stores = $traversal->getResults($part, Traversal::ReturnTypeNode); echo "Found ".count($stores)." stores:\n"; foreach ($stores as $store) { echo "* {$store->getProperty('name')}\n"; } } } ================================================ FILE: lib/Everyman/Neo4j/Batch/AddTo.php ================================================ index = $index; $this->key = $key; $this->value = $value; } /** * Get the command that represents this operation * * @return Batch\Command */ public function getCommand() { if (!$this->command) { $this->command = new Command\AddToIndex( $this->batch->getClient(), $this->index, $this->entity, $this->key, $this->value, $this->opId, $this->batch ); } return $this->command; } /** * Get the index * * @return Index */ public function getIndex() { return $this->index; } /** * Get the key being indexed * * @return string */ public function getKey() { return $this->key; } /** * Get the value being indexed * * @return mixed */ public function getValue() { return $this->value; } /** * Based on this operations parameters, generate a consistent id * * @return mixed */ public function matchId() { return parent::matchId() . spl_object_hash($this->index) . $this->key . $this->value; } } ================================================ FILE: lib/Everyman/Neo4j/Batch/Delete.php ================================================ command) { $entity = $this->entity; $command = null; if ($entity instanceof Node) { $command = new Command\DeleteNode($this->batch->getClient(), $entity, $this->opId); } else if ($entity instanceof Relationship) { $command = new Command\DeleteRelationship($this->batch->getClient(), $entity, $this->opId); } $this->command = $command; } return $this->command; } } ================================================ FILE: lib/Everyman/Neo4j/Batch/Operation.php ================================================ batch = $batch; $this->operation = $operation; $this->entity = $entity; $this->opId = $opId; } /** * Get the underlying batch command for this operation * * @return Batch\Command */ abstract public function getCommand(); /** * Return the associated entity * * @return PropertyContainer */ public function getEntity() { return $this->entity; } /** * Get the operation id * * @return integer */ public function getId() { return $this->opId; } /** * Based on this operations parameters, generate a consistent id * * @return mixed */ public function matchId() { return $this->operation . spl_object_hash($this->entity); } /** * Reserve this operation to prevent it from being double-committed * Once an operation has been reserved, future reserve calls will * return false, indicating it has already been reserved. * This is mostly useful during commit to prevent an operation being * sent twice * * @return boolean true if reservation succeeded */ public function reserve() { if (!$this->reserved) { $this->reserved = true; return true; } return false; } } ================================================ FILE: lib/Everyman/Neo4j/Batch/RemoveFrom.php ================================================ index = $index; $this->key = $key; $this->value = $value; } /** * Get the command that represents this operation * * @return Batch\Command */ public function getCommand() { if (!$this->command) { $this->command = new Command\RemoveFromIndex( $this->batch->getClient(), $this->index, $this->entity, $this->key, $this->value, $this->opId ); } return $this->command; } /** * Based on this operations parameters, generate a consistent id * * @return mixed */ public function matchId() { return parent::matchId() . spl_object_hash($this->index) . $this->key . $this->value; } } ================================================ FILE: lib/Everyman/Neo4j/Batch/Save.php ================================================ command) { $entity = $this->entity; $command = null; if (!$entity->hasId()) { if ($entity instanceof Node) { $command = new Command\CreateNode($this->batch->getClient(), $entity, $this->opId); } else if ($entity instanceof Relationship) { $command = new Command\CreateRelationship($this->batch->getClient(), $entity, $this->opId, $this->batch); } } else { if ($entity instanceof Node) { $command = new Command\UpdateNode($this->batch->getClient(), $entity, $this->opId); } else if ($entity instanceof Relationship) { $command = new Command\UpdateRelationship($this->batch->getClient(), $entity, $this->opId); } } $this->command = $command; } return $this->command; } } ================================================ FILE: lib/Everyman/Neo4j/Batch.php ================================================ client = $client; } /** * Add the given entity to the given index with the given key/value * * @param Index $index * @param PropertyContainer $entity * @param string $key * @param string $value * @return integer */ public function addToIndex(Index $index, PropertyContainer $entity, $key, $value) { return $this->addOperation(new Batch\AddTo($this, $index, $entity, $key, $value, $this->nextId())); } /** * Commit the batch to the server * * @return boolean */ public function commit() { if ($this->committed) { throw new Exception('Cannot commit the same batch more than once.'); } $this->committed = true; return $this->client->commitBatch($this); } /** * Add an entity to the batch to delete * * @param PropertyContainer $entity * @return integer */ public function delete(PropertyContainer $entity) { return $this->addOperation(new Batch\Delete($this, $entity, $this->nextId())); } /** * Get the batch's client * * @return Client */ public function getClient() { return $this->client; } /** * Return the list of operations in this batch * * @return array */ public function getOperations() { return $this->operations; } /** * Remove the given entity from the given index with the given key/value * * @param Index $index * @param PropertyContainer $entity * @param string $key * @param string $value * @return integer */ public function removeFromIndex(Index $index, PropertyContainer $entity, $key=null, $value=null) { return $this->addOperation(new Batch\RemoveFrom($this, $index, $entity, $key, $value, $this->nextId())); } /** * Reserve an operation to prevent it from being double-committed * Once an operation has been reserved, future reserve calls will * return false, indicating it has already been reserved. * This is mostly useful during commit to prevent an operation being * sent twice * * @param integer $opId * @return mixed array operation if not yet reserved, false otherwise */ public function reserve($opId) { if (isset($this->operations[$opId]) && $this->operations[$opId]->reserve()) { return $this->operations[$opId]; } return false; } /** * Add an entity to the batch to save * * @param PropertyContainer $entity * @return integer */ public function save(PropertyContainer $entity) { return $this->addOperation(new Batch\Save($this, $entity, $this->nextId())); } /** * Add an operation to the batch * * @param Batch\Operation $operation * @return integer operation index */ protected function addOperation(Batch\Operation $operation) { $opId = $operation->getId(); $matchId = $operation->matchId(); if (isset($this->matches[$matchId])) { return $this->matches[$matchId]->getId(); } $this->operations[$opId] = $operation; $this->matches[$matchId] = $operation; return $opId; } /** * Get the next unused id * * @return integer */ protected function nextId() { return count($this->operations); } } ================================================ FILE: lib/Everyman/Neo4j/Cache/EntityCache.php ================================================ client = $client; $this->setCache($cache, $cacheTimeout); } /** * Delete an entity from the cache * * @param PropertyContainer $entity */ public function deleteCachedEntity(PropertyContainer $entity) { $this->getCache()->delete($this->getEntityCacheKey($entity)); } /** * Get an entity from the cache * * @param integer $id * @param string $type */ public function getCachedEntity($id, $type) { if ($type != 'node' && $type != 'relationship') { throw new Exception('Unknown entity type: '.$type); } $entity = $this->getCache()->get("{$type}-{$id}"); if ($entity) { $entity->setClient($this->client); } return $entity; } /** * Set the cache to use * * @param Cache $cache * @param integer $cacheTimeout */ public function setCache(Cache $cache=null, $cacheTimeout=null) { $this->cache = $cache; $this->cacheTimeout = (int)$cacheTimeout; } /** * Set an entity in the cache * * @param PropertyContainer $entity */ public function setCachedEntity(PropertyContainer $entity) { $this->getCache()->set($this->getEntityCacheKey($entity), $entity, $this->cacheTimeout); } /** * Get the cache plugin * * @return Cache */ protected function getCache() { if ($this->cache === null) { $this->setCache(new Cache\None(), $this->cacheTimeout); } return $this->cache; } /** * Determine the cache key used to retrieve the given entity from the cache * * @param PropertyContainer $entity * @return string */ protected function getEntityCacheKey(PropertyContainer $entity) { if ($entity instanceof Node) { return 'node-'.$entity->getId(); } else if ($entity instanceof Relationship) { return 'relationship-'.$entity->getId(); } throw new Exception('Unknown entity type: '.get_class($entity)); } } ================================================ FILE: lib/Everyman/Neo4j/Cache/Memcache.php ================================================ memcache = $memcache; } /** * Delete a value from the cache * * @param string $key * @return boolean true on success */ public function delete($key) { return $this->memcache->delete($key); } /** * Retrieve a value * Returns false if the key does not * exist, or the value is false * * @param string $key * @return mixed */ public function get($key) { return $this->memcache->get($key); } /** * Store a value in the cache * $expire is specified as an integer: * - less than or equal to 2592000 (the number of seconds in 30 days) * will be considered an expire time of that many seconds from the * current timestamp * - Greater than that amount will be considered as literal Unix * timestamp values * - 0 means "never expire." * * @param string $key * @param mixed $value * @param integer $expire * @return boolean true on success */ public function set($key, $value, $expire=0) { return $this->memcache->set($key, $value, 0, $expire); } } ================================================ FILE: lib/Everyman/Neo4j/Cache/Memcached.php ================================================ memcached = $memcached; } /** * Delete a value from the cache * * @param string $key * @return boolean true on success */ public function delete($key) { return $this->memcached->delete($key); } /** * Retrieve a value * Returns false if the key does not * exist, or the value is false * * @param string $key * @return mixed */ public function get($key) { return $this->memcached->get($key); } /** * Store a value in the cache * $expire is specified as an integer: * - less than or equal to 2592000 (the number of seconds in 30 days) * will be considered an expire time of that many seconds from the * current timestamp * - Greater than that amount will be considered as literal Unix * timestamp values * - 0 means "never expire." * * @param string $key * @param mixed $value * @param integer $expire * @return boolean true on success */ public function set($key, $value, $expire=0) { return $this->memcached->set($key, $value, $expire); } } ================================================ FILE: lib/Everyman/Neo4j/Cache/None.php ================================================ items[$key]); return true; } /** * Retrieve a value * Returns false if the key does not * exist, or the value is false * * @param string $key * @return mixed */ public function get($key) { $value = false; if (isset($this->items[$key])) { if ($this->items[$key]['expire'] >= time()) { $value = $this->items[$key]['value']; } else { $this->delete($key); } } return $value; } /** * Store a value in the cache * $expire is specified as an integer: * - less than or equal to 2592000 (the number of seconds in 30 days) * will be considered an expire time of that many seconds from the * current timestamp * - Greater than that amount will be considered as literal Unix * timestamp values * - 0 means "never expire." * * @param string $key * @param mixed $value * @param integer $expire * @return boolean true on success */ public function set($key, $value, $expire=0) { $expire = $this->calculateExpiration($expire); $this->items[$key] = array( 'value' => $value, 'expire' => $expire, ); return true; } /** * Determine the expiration timestamp * * @param integer $expire * @return integer */ protected function calculateExpiration($expire) { if (!$expire) { $expire = PHP_INT_MAX; } else if ($expire <= 2592000) { $expire = time() + $expire; } return $expire; } } ================================================ FILE: lib/Everyman/Neo4j/Cache.php ================================================ setTransport($transport); $this->setNodeFactory(function (Client $client, $properties=array()) { return new Node($client); }); $this->setRelationshipFactory(function (Client $client, $properties=array()) { return new Relationship($client); }); $this->labelCache = new Cache\Variable(); } /** * Add a set of labels to a node * * @param Node $node * @param Label[] $labels list of Label objects to add * @return Label[] of Label objects; the entire list of labels on the given node * including the ones just added */ public function addLabels(Node $node, $labels) { $command = new Command\AddLabels($this, $node, $labels); return $this->runCommand($command); } /** * Add statements to a transaction, and optionally commit the transaction * * @param Transaction $transaction * @param array $statements an array of Cypher\Query objects * @param boolean $commit should this transaction be committed on this request? * @return Query\ResultSet */ public function addStatementsToTransaction(Transaction $transaction, $statements=array(), $commit=false) { $command = new Command\AddStatementsToTransaction($this, $transaction, $statements, $commit); return $this->runCommand($command); } /** * Add an entity to an index * * @param Index $index * @param PropertyContainer $entity * @param string $key * @param string $value * @return boolean */ public function addToIndex(Index $index, PropertyContainer $entity, $key, $value) { if ($this->openBatch) { $this->openBatch->addToIndex($index, $entity, $key, $value); return true; } return $this->runCommand(new Command\AddToIndex($this, $index, $entity, $key, $value)); } /** * Begin a Cypher transaction * * @return Transaction */ public function beginTransaction() { return new Transaction($this); } /** * Commit a batch of operations * * @param Batch $batch * @throws Exception * @return boolean true on success */ public function commitBatch(Batch $batch=null) { if (!$batch) { if (!$this->openBatch) { throw new Exception('No open batch to commit.'); } $batch = $this->openBatch; } if ($batch === $this->openBatch) { $this->endBatch(); } if (count($batch->getOperations()) < 1) { return true; } return $this->runCommand(new Command\Batch\Commit($this, $batch)); } /** * Delete the given index * * @param Index $index * @return boolean */ public function deleteIndex(Index $index) { return $this->runCommand(new Command\DeleteIndex($this, $index)); } /** * Delete the given node * * @param Node $node * @return boolean */ public function deleteNode(Node $node) { if ($this->openBatch) { $this->openBatch->delete($node); return true; } return $this->runCommand(new Command\DeleteNode($this, $node)); } /** * Delete the given relationship * * @param Relationship $relationship * @return boolean */ public function deleteRelationship(Relationship $relationship) { if ($this->openBatch) { $this->openBatch->delete($relationship); return true; } return $this->runCommand(new Command\DeleteRelationship($this, $relationship)); } /** * Detach the current open batch. * * The batch can still be committed via the batch returned * by Client::startBatch() * * @return Client */ public function endBatch() { $this->openBatch = null; return $this; } /** * Execute the given Cypher query and return the result * * @param Cypher\Query $query A Cypher query, or a query template. * @return Query\ResultSet */ public function executeCypherQuery(Cypher\Query $query) { $command = new Command\ExecuteCypherQuery($this, $query); return $this->runCommand($command); } /** * Execute the given Gremlin query and return the result * * @param Gremlin\Query $query * @return Query\ResultSet */ public function executeGremlinQuery(Gremlin\Query $query) { $command = new Command\ExecuteGremlinQuery($this, $query); return $this->runCommand($command); } /** * Execute a paged traversal and return the result * * @param Pager $pager * @return array */ public function executePagedTraversal(Pager $pager) { $command = new Command\ExecutePagedTraversal($this, $pager); return $this->runCommand($command); } /** * Execute the given traversal and return the result * * @param Traversal $traversal * @param Node $startNode * @param string $returnType * @return array */ public function executeTraversal(Traversal $traversal, Node $startNode, $returnType) { $command = new Command\ExecuteTraversal($this, $traversal, $startNode, $returnType); return $this->runCommand($command); } /** * Get the cache * * @return Cache\EntityCache */ public function getEntityCache() { if ($this->entityCache === null) { $this->setEntityCache(new Cache\EntityCache($this)); } return $this->entityCache; } /** * Get the entity mapper * * @return EntityMapper */ public function getEntityMapper() { if ($this->entityMapper === null) { $this->setEntityMapper(new EntityMapper($this)); } return $this->entityMapper; } /** * Get all indexes of the given type * * @param string $type * @return mixed false on error, else an array of Index objects */ public function getIndexes($type) { $command = new Command\GetIndexes($this, $type); return $this->runCommand($command); } /** * List the labels already saved on the server * * If a $node is given, only return labels for * that node. * * @param Node $node * @return array */ public function getLabels(Node $node=null) { $command = new Command\GetLabels($this, $node); return $this->runCommand($command); } /** * Get the requested node * Using the $force option disables the check * of whether or not the node exists and will * return a Node with the given id even if it * does not. * * @param integer $id * @param boolean $force * @throws Exception * @return Node */ public function getNode($id, $force=false) { $cached = $this->getEntityCache()->getCachedEntity($id, 'node'); if ($cached) { return $cached; } $node = $this->makeNode(); $node->setId($id); if ($force) { return $node; } try { $this->loadNode($node); } catch (Exception $e) { if ($e->getCode() == self::ErrorNotFound) { return null; } else { throw $e; } } return $node; } /** * Get all relationships on a node matching the criteria * * @param Node $node * @param mixed $types a string or array of strings * @param string $dir * @return mixed false on error, else an array of Relationship objects */ public function getNodeRelationships(Node $node, $types=array(), $dir=null) { $command = new Command\GetNodeRelationships($this, $node, $types, $dir); return $this->runCommand($command); } /** * Get the nodes matching the given label * * If a property and value are given, only return * nodes where the given property equals the value * * @param Label $label * @param string $propertyName * @param mixed $propertyValue * @return Query\Row */ public function getNodesForLabel(Label $label, $propertyName=null, $propertyValue=null) { $command = new Command\GetNodesForLabel($this, $label, $propertyName, $propertyValue); return $this->runCommand($command); } /** * Get an array of paths matching the finder's criteria * * @param PathFinder $finder * @return array */ public function getPaths(PathFinder $finder) { $command = new Command\GetPaths($this, $finder); return $this->runCommand($command); } /** * Retrieve the reference node (id: 0) from the server * * @return Node */ public function getReferenceNode() { return $this->getNode(self::RefNodeId); } /** * Get the requested relationship * Using the $force option disables the check * of whether or not the relationship exists and will * return a Relationship with the given id even if it * does not. * * @param integer $id * @param boolean $force * @throws Exception * @return Relationship */ public function getRelationship($id, $force=false) { $cached = $this->getEntityCache()->getCachedEntity($id, 'relationship'); if ($cached) { return $cached; } $rel = $this->makeRelationship(); $rel->setId($id); if ($force) { return $rel; } try { $this->loadRelationship($rel); } catch (Exception $e) { if ($e->getCode() == self::ErrorNotFound) { return null; } else { throw $e; } } return $rel; } /** * Get a list of all relationship types on the server * * @return array */ public function getRelationshipTypes() { $command = new Command\GetRelationshipTypes($this); return $this->runCommand($command); } /** * Retrieve information about the server * * @param boolean $force Don't use previous results * @return array */ public function getServerInfo($force=false) { if ($this->serverInfo === null || $force) { $command = new Command\GetServerInfo($this); $this->serverInfo = $this->runCommand($command); } return $this->serverInfo; } /** * Get the transport * * @return Transport */ public function getTransport() { return $this->transport; } /** * Does the connected database have the requested capability? * * @param string $capability * @return mixed true or string if yes, false otherwise */ public function hasCapability($capability) { $info = $this->getServerInfo(); switch ($capability) { case self::CapabilityLabel: case self::CapabilityTransactions: return $info['version']['major'] > 1; case self::CapabilityCypher: if (isset($info['cypher'])) { return $info['cypher']; } else if (isset($info['extensions']['CypherPlugin']['execute_query'])) { return $info['extensions']['CypherPlugin']['execute_query']; } return false; case self::CapabilityGremlin: if (isset($info['extensions']['GremlinPlugin']['execute_script'])) { return $info['extensions']['GremlinPlugin']['execute_script']; } return false; default: return false; } } /** * Load the given node with data from the server * * @param Node $node * @return boolean */ public function loadNode(Node $node) { $cached = $this->getEntityCache()->getCachedEntity($node->getId(), 'node'); if ($cached) { $node->setProperties($cached->getProperties()); return true; } return $this->runCommand(new Command\GetNode($this, $node)); } /** * Load the given relationship with data from the server * * @param Relationship $rel * @return boolean */ public function loadRelationship(Relationship $rel) { $cached = $this->getEntityCache()->getCachedEntity($rel->getId(), 'relationship'); if ($cached) { $rel->setProperties($cached->getProperties()); return true; } return $this->runCommand(new Command\GetRelationship($this, $rel)); } /** * Retrieve a Label object for the given name * * If the name has already been seen, the same * Label object wil be returned, i. e. only one * Label will exist per name. * * @param string $name * @return Label */ public function makeLabel($name) { $label = $this->labelCache->get($name); if (!$label) { $label = new Label($this, $name); $this->labelCache->set($name, $label); } return $label; } /** * Create a new node object bound to this client * * @param array $properties * @throws Exception * @return Node */ public function makeNode($properties=array()) { $nodeFactory = $this->nodeFactory; $node = $nodeFactory($this, $properties); if (!($node instanceof Node)) { throw new Exception('Node factory did not return a Node object.'); } return $node->setProperties($properties); } /** * Create a new relationship object bound to this client * * @param array $properties * @throws Exception * @return Relationship */ public function makeRelationship($properties=array()) { $relFactory = $this->relFactory; $rel = $relFactory($this, $properties); if (!($rel instanceof Relationship)) { throw new Exception('Relationship factory did not return a Relationship object.'); } return $rel->setProperties($properties); } /** * Query an index using a query string. * The default query language in Neo4j is Lucene * * @param Index $index * @param string $query * @return array */ public function queryIndex(Index $index, $query) { $command = new Command\QueryIndex($this, $index, $query); return $this->runCommand($command); } /** * Rollback the transaction * * @param Transaction $transaction * @return mixed */ public function rollbackTransaction(Transaction $transaction) { $command = new Command\RollbackTransaction($this, $transaction); return $this->runCommand($command); } /** * Remove an entity from an index * If $value is not given, all reference of the entity for the key * are removed. * If $key is not given, all reference of the entity are removed. * * @param Index $index * @param PropertyContainer $entity * @param string $key * @param string $value * @return boolean */ public function removeFromIndex(Index $index, PropertyContainer $entity, $key=null, $value=null) { if ($this->openBatch) { $this->openBatch->removeFromIndex($index, $entity, $key, $value); return true; } return $this->runCommand(new Command\RemoveFromIndex($this, $index, $entity, $key, $value)); } /** * Remove a set of labels from a node * * @param Node $node * @param array $labels list of Label objects to remove * @return array of Label objects; the entire list of labels on the given node * including the ones just added */ public function removeLabels(Node $node, $labels) { $command = new Command\RemoveLabels($this, $node, $labels); return $this->runCommand($command); } /** * Save the given index * * @param Index $index * @return boolean */ public function saveIndex(Index $index) { return $this->runCommand(new Command\SaveIndex($this, $index)); } /** * Save the given node * * @param Node $node * @return boolean */ public function saveNode(Node $node) { if ($this->openBatch) { $this->openBatch->save($node); return true; } if ($node->hasId()) { return $this->runCommand(new Command\UpdateNode($this, $node)); } else { return $this->runCommand(new Command\CreateNode($this, $node)); } } /** * Save the given relationship * * @param Relationship $rel * @return boolean */ public function saveRelationship(Relationship $rel) { if ($this->openBatch) { $this->openBatch->save($rel); return true; } if ($rel->hasId()) { return $this->runCommand(new Command\UpdateRelationship($this, $rel)); } else { return $this->runCommand(new Command\CreateRelationship($this, $rel)); } } /** * Search an index for matching entities * * @param Index $index * @param string $key * @param string $value * @return array */ public function searchIndex(Index $index, $key, $value) { $command = new Command\SearchIndex($this, $index, $key, $value); return $this->runCommand($command); } /** * Set the cache to use * * @param Cache\EntityCache $cache */ public function setEntityCache(Cache\EntityCache $cache) { $this->entityCache = $cache; } /** * Set the entity mapper to use * * @param EntityMapper $mapper */ public function setEntityMapper(EntityMapper $mapper) { $this->entityMapper = $mapper; } /** * Set the callback to use to create new Node objects * * Takes a callback of the signature callback(Client $client, $properties=array()) * and returns a new Node object. * The properties can be used to determine what type of Node * should be returned, but are not set by the factory function. * * @param callable $factory * @throws Exception * @return Client */ public function setNodeFactory($factory) { if (!is_callable($factory)) { throw new Exception('Node factory must be callable.'); } $this->nodeFactory = $factory; return $this; } /** * Set the callback to use to create new Relationship objects * * Takes a callback of the signature callback(Client $client, $properties=array()) * and returns a new Relationship object. * The properties can be used to determine what type of Relationship * should be returned, but are not set by the factory function. * * @param callable $factory * @throws Exception * @return Client */ public function setRelationshipFactory($factory) { if (!is_callable($factory)) { throw new Exception('Relationship factory must be callable.'); } $this->relFactory = $factory; return $this; } /** * Set the transport to use * * @param Transport $transport */ public function setTransport(Transport $transport) { $this->transport = $transport; } /** * Start an implicit batch * * Any data manipulation calls that occur between this call * and the subsequent Client::commitBatch() call will be * wrapped in a batch operation. * * @return Batch */ public function startBatch() { if (!$this->openBatch) { $this->openBatch = new Batch($this); } return $this->openBatch; } /** * Run a command that will talk to the transport * * @param Command $command * @return mixed */ protected function runCommand(Command $command) { $result = $command->execute(); return $result; } } ================================================ FILE: lib/Everyman/Neo4j/Command/AddLabels.php ================================================ transaction = $transaction; $this->statements = $statements; $this->commit = $commit; } /** * Return the data to pass * * @return mixed */ protected function getData() { if (!$this->statements && !$this->transaction->getId()) { throw new Exception("Cannot keep-alive a transaction without an id"); } $statements = array_map(array($this, 'formatStatement'), $this->statements); return array('statements' => $statements); } /** * Format the given query into a transactional statement * * @param Query $statement * @return array */ protected function formatStatement(Query $statement) { return array( 'statement' => $statement->getQuery(), 'parameters' => (object)$statement->getParameters(), 'resultDataContents' => array('rest'), ); } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->client->hasCapability(Client::CapabilityTransactions)) { throw new Exception('Transactions unavailable'); } $path = '/transaction'; $id = $this->transaction->getId(); if ($id) { $path .= '/'.$id; } if ($this->commit) { $path .= '/commit'; } return $path; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2 || !empty($data['errors'])) { $this->throwException('Error in transaction', $code, $headers, $data); } if (!$this->transaction->getId() && !$this->commit) { $this->setTransactionId($data); } $results = array_map(array($this, 'mapResult'), $data['results']); return $results; } /** * Map the response into a ResultSet * * @param array $result * @return ResultSet */ protected function mapResult($result) { $data = array_map(function ($row) { return $row['rest']; }, $result['data']); return new ResultSet($this->client, array( 'columns' => $result['columns'], 'data' => $data, )); } /** * Parse the transaction id out of the response and set it on the transaction * * @param array $data */ protected function setTransactionId($data) { $commit = $data['commit']; $path = parse_url($commit, PHP_URL_PATH); $parts = explode('/', $path); $id = $parts[count($parts)-2]; $this->transaction->setId($id); } } ================================================ FILE: lib/Everyman/Neo4j/Command/AddToIndex.php ================================================ index = $index; $this->entity = $entity; $this->key = $key; $this->value = $value; } /** * Return the data to pass * * @return mixed */ protected function getData() { if (!$this->entity || !$this->entity->hasId()) { throw new Exception('No entity to index specified'); } $data = array(); $type = trim((string)$this->index->getType()); $data['uri'] = $this->getTransport()->getEndpoint().'/'.$type.'/'.$this->entity->getId(); $key = trim((string)$this->key); if (!$key) { throw new Exception('No key specified to add to index'); } $data['key'] = $key; $data['value'] = $this->value; return $data; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { $type = trim((string)$this->index->getType()); if ($type != Index::TypeNode && $type != Index::TypeRelationship) { throw new Exception('No type specified for index'); } else if ($type == Index::TypeNode && !($this->entity instanceof Node)) { throw new Exception('Cannot add a node to a non-node index'); } else if ($type == Index::TypeRelationship && !($this->entity instanceof Relationship)) { throw new Exception('Cannot add a relationship to a non-relationship index'); } $name = trim((string)$this->index->getName()); if (!$name) { throw new Exception('No name specified for index'); } $name = rawurlencode($name); return '/index/'.$type.'/'.$name; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to add entity to index', $code, $headers, $data); } return true; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/AddToIndex.php ================================================ batch = $batch; $this->entity = $entity; } /** * Return the data to pass * * @return array */ protected function getData() { $opData = array(); // Prevent the command from throwing an Exception if an unsaved entity if (!$this->entity->hasId()) { $entityId = $this->batch->save($this->entity); $reserved = $this->batch->reserve($entityId); if ($reserved) { $opData = array_merge($opData, $reserved->getCommand()->getData()); } $this->entity->setId(-1); $body = $this->base->getData(); $this->entity->setId(null); $body['uri'] = "{{$entityId}}"; } else { $body = $this->base->getData(); } $opData[] = array( 'method' => strtoupper($this->base->getMethod()), 'to' => $this->base->getPath(), 'body' => $body, 'id' => $this->opId, ); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/Command.php ================================================ base = $base; $this->opId = $opId; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { return '/batch'; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return mixed * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to commit batch', $code, $headers, $data); } foreach ($data as $result) { $this->handleSingleResult($result); } return true; } /** * Handle a single result from the batch of results * * @param array $result * @return mixed * @throws Exception on failure */ protected function handleSingleResult($result) { $headers = array(); if (isset($result['location'])) { $headers['Location'] = $result['location']; } return $this->base->handleResult(200, $headers, $result); } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/Commit.php ================================================ batch = $batch; } /** * Return the data to pass * * @return mixed */ protected function getData() { $operations = $this->batch->getOperations(); $data = array(); foreach ($operations as $op) { if ($op->reserve()) { $opData = $op->getCommand()->getData(); foreach ($opData as $datum) { $data[] = $datum; } } } return $data; } /** * Use the results * * @param array $result */ protected function handleSingleResult($result) { $operations = $this->batch->getOperations(); $command = $operations[$result['id']]->getCommand(); return $command->handleSingleResult($result); } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/CreateNode.php ================================================ strtoupper($this->base->getMethod()), 'to' => $this->base->getPath(), 'body' => $this->base->getData(), 'id' => $this->opId, )); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/CreateRelationship.php ================================================ batch = $batch; $this->rel = $rel; } /** * Return the data to pass * * @return array */ protected function getData() { $opData = array(); // Prevent the command from throwing an Exception if an unsaved start node $startNode = $this->rel->getStartNode(); if (!$startNode->hasId()) { $startId = $this->batch->save($startNode); $reserved = $this->batch->reserve($startId); if ($reserved) { $opData = array_merge($opData, $reserved->getCommand()->getData()); } $start = "{{$startId}}/relationships"; } else { $start = $this->base->getPath(); } // Prevent the command from throwing an Exception if an unsaved end node $endNode = $this->rel->getEndNode(); if (!$endNode->hasId()) { $endId = $this->batch->save($endNode); $reserved = $this->batch->reserve($endId); if ($reserved) { $opData = array_merge($opData, $reserved->getCommand()->getData()); } $endNode->setId('temp'); $data = $this->base->getData(); $endNode->setId(null); $data['to'] = "{{$endId}}"; } else { $data = $this->base->getData(); } $opData[] = array( 'method' => strtoupper($this->base->getMethod()), 'to' => $start, 'body' => $data, 'id' => $this->opId, ); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/DeleteNode.php ================================================ strtoupper($this->base->getMethod()), 'to' => $this->base->getPath(), 'id' => $this->opId, )); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/DeleteRelationship.php ================================================ strtoupper($this->base->getMethod()), 'to' => $this->base->getPath(), 'id' => $this->opId, )); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/RemoveFromIndex.php ================================================ strtoupper($this->base->getMethod()), 'to' => $this->base->getPath(), 'id' => $this->opId, )); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/UpdateNode.php ================================================ strtoupper($this->base->getMethod()), 'to' => $this->base->getPath(), 'body' => $this->base->getData(), 'id' => $this->opId, )); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/Batch/UpdateRelationship.php ================================================ strtoupper($this->base->getMethod()), 'to' => $this->base->getPath(), 'body' => $this->base->getData(), 'id' => $this->opId, )); return $opData; } } ================================================ FILE: lib/Everyman/Neo4j/Command/CreateNode.php ================================================ node = $node; } /** * Return the data to pass * * @return mixed */ protected function getData() { return $this->node->getProperties() ?: null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { return '/node'; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to create node', $code, $headers, $data); } $nodeId = $this->getEntityMapper()->getIdFromUri($headers['Location']); $this->node->setId($nodeId); $this->getEntityCache()->setCachedEntity($this->node); return true; } } ================================================ FILE: lib/Everyman/Neo4j/Command/CreateRelationship.php ================================================ rel = $rel; } /** * Return the data to pass * * @return mixed */ protected function getData() { $end = $this->rel->getEndNode(); $type = $this->rel->getType(); if (!$end || !$end->hasId()) { throw new Exception('No relationship end node specified'); } else if (!$type) { throw new Exception('No relationship type specified'); } $endUri = $this->getTransport()->getEndpoint().'/node/'.$end->getId(); $data = array( 'type' => $type, 'to' => $endUri, ); $properties = $this->rel->getProperties(); if ($properties) { $data['data'] = $properties; } return $data; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { $start = $this->rel->getStartNode(); if (!$start || !$start->hasId()) { throw new Exception('No relationship start node specified'); } return '/node/'.$start->getId().'/relationships'; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to create relationship', $code, $headers, $data); } $relId = $this->getEntityMapper()->getIdFromUri($headers['Location']); $this->rel->setId($relId); $this->getEntityCache()->setCachedEntity($this->rel); return true; } } ================================================ FILE: lib/Everyman/Neo4j/Command/DeleteIndex.php ================================================ index = $index; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'delete'; } /** * Return the path to use * * @return string */ protected function getPath() { $type = trim((string)$this->index->getType()); if ($type != Index::TypeNode && $type != Index::TypeRelationship) { throw new Exception('No type specified for index'); } $name = trim((string)$this->index->getName()); if (!$name) { throw new Exception('No name specified for index'); } $name = rawurlencode($name); return '/index/'.$type.'/'.$name; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2 && (int)$code != 404) { $this->throwException('Unable to delete index', $code, $headers, $data); } return true; } } ================================================ FILE: lib/Everyman/Neo4j/Command/DeleteNode.php ================================================ node = $node; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'delete'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->node->hasId()) { throw new Exception('No node id specified for delete'); } return '/node/'.$this->node->getId(); } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) == 2) { $this->getEntityCache()->deleteCachedEntity($this->node); return true; } else { $this->throwException('Unable to delete node', $code, $headers, $data); } } } ================================================ FILE: lib/Everyman/Neo4j/Command/DeleteRelationship.php ================================================ rel = $rel; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'delete'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->rel->hasId()) { throw new Exception('No relationship id specified for delete'); } return '/relationship/'.$this->rel->getId(); } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) == 2) { $this->getEntityCache()->deleteCachedEntity($this->rel); return true; } else { $this->throwException('Unable to delete relationship', $code, $headers, $data); } } } ================================================ FILE: lib/Everyman/Neo4j/Command/ExecuteCypherQuery.php ================================================ query = $query; } /** * Return the data to pass * * @return mixed */ protected function getData() { $data = array('query' => $this->query->getQuery()); $params = $this->query->getParameters(); if ($params) { $data['params'] = $params; } return $data; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { $url = $this->client->hasCapability(Client::CapabilityCypher); if (!$url) { throw new Exception('Cypher unavailable'); } return preg_replace('/^.+\/db\/data/', '', $url); } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to execute query', $code, $headers, $data); } return new ResultSet($this->client, $data); } } ================================================ FILE: lib/Everyman/Neo4j/Command/ExecuteGremlinQuery.php ================================================ query = $query; } /** * Return the data to pass * * @return mixed */ protected function getData() { $data = array('script' => $this->query->getQuery()); $params = $this->query->getParameters(); if ($params) { $data['params'] = $params; } return $data; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { $url = $this->client->hasCapability(Client::CapabilityGremlin); if (!$url) { throw new Exception('Gremlin unavailable'); } return preg_replace('/^.+\/db\/data/', '', $url); } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to execute query', $code, $headers, $data); } return new ResultSet($this->client, $this->normalizeData($data)); } /** * Normalize the data so a proper ResultSet can be built * Normalized data has 'data' and 'columns' keys for result set. * * @param array $data * @return array */ protected function normalizeData($data) { if (is_scalar($data)) { $data = array($data); } if (!array_key_exists('columns', $data)) { $columns = array(0); if (array_key_exists('self', $data)) { $data = array(array($data)); } else { foreach ($data as $i => $entity) { $data[$i] = array($entity); } } $data = array( 'columns' => $columns, 'data' => $data ); } return $data; } } ================================================ FILE: lib/Everyman/Neo4j/Command/ExecutePagedTraversal.php ================================================ getTraversal(), $pager->getStartNode(), $pager->getReturnType()); $this->pager = $pager; } /** * Return the data to pass * * @return mixed */ protected function getData() { return $this->pager->getId() ? null : parent::getData(); } /** * Return the transport method to call * * @return string */ protected function getMethod() { return $this->pager->getId() ? 'get' : parent::getMethod(); } /** * Return the path to use * * @return string */ protected function getPath() { $path = parent::getPath(); $path = str_replace('traverse', 'paged/traverse', $path); $id = $this->pager->getId(); if ($id) { $path .= "/{$id}"; } else { $queryParams = array(); $pageSize = $this->pager->getPageSize(); $leaseTime = $this->pager->getLeaseTime(); if ($pageSize) { $queryParams['pageSize'] = $pageSize; } if ($leaseTime) { $queryParams['leaseTime'] = $leaseTime; } $queryString = http_build_query($queryParams); $path .= $queryString ? "?{$queryString}" : ''; } return $path; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if (isset($headers['Location'])) { $traversalId = $this->getEntityMapper()->getIdFromUri($headers['Location']); $this->pager->setId($traversalId); } // No results found or end of result set indicated by not found if ($code == Client::ErrorNotFound) { return null; } return parent::handleResult($code, $headers, $data); } } ================================================ FILE: lib/Everyman/Neo4j/Command/ExecuteTraversal.php ================================================ traversal = $traversal; $this->node = $node; $this->returnType = $returnType; } /** * Return the data to pass * * @return mixed */ protected function getData() { $data = array(); $order = $this->traversal->getOrder(); if ($order) { $data['order'] = $order; } $uniqueness = $this->traversal->getUniqueness(); if ($uniqueness) { $data['uniqueness'] = $uniqueness; } $maxDepth = $this->traversal->getMaxDepth(); if ($maxDepth) { $data['max_depth'] = $maxDepth; } $relationships = $this->traversal->getRelationships(); if (count($relationships) > 0) { $data['relationships'] = $relationships; } $prune = $this->traversal->getPruneEvaluator(); if ($prune) { if ($prune['language'] == Traversal::Builtin) { $prune['name'] = $prune['body']; unset($prune['body']); } $data['prune_evaluator'] = $prune; } $filter = $this->traversal->getReturnFilter(); if ($filter) { if ($filter['language'] == Traversal::Builtin) { $filter['name'] = $filter['body']; unset($filter['body']); } $data['return_filter'] = $filter; } return $data; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->node->hasId()) { throw new Exception('No node id specified'); } if ($this->returnType != Traversal::ReturnTypeNode && $this->returnType != Traversal::ReturnTypeRelationship && $this->returnType != Traversal::ReturnTypePath && $this->returnType != Traversal::ReturnTypeFullPath) { throw new Exception('No return type specified for traversal'); } return '/node/'.$this->node->getId().'/traverse/'.$this->returnType; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to execute traversal', $code, $headers, $data); } $this->results = array(); if ($this->returnType == Traversal::ReturnTypeNode) { $this->handleNodes($data); } else if ($this->returnType == Traversal::ReturnTypeRelationship) { $this->handleRelationships($data); } else if ($this->returnType == Traversal::ReturnTypePath) { $this->handlePaths($data); } else if ($this->returnType == Traversal::ReturnTypeFullPath) { $this->handlePaths($data, true); } return $this->results; } /** * Handle nodes * * @param array $data */ protected function handleNodes($data) { foreach ($data as $nodeData) { $this->results[] = $this->getEntityMapper()->makeNode($nodeData); } } /** * Handle relationships * * @param array $data */ protected function handleRelationships($data) { foreach ($data as $relData) { $this->results[] = $this->getEntityMapper()->makeRelationship($relData); } } /** * Handle paths * * @param array $data * @param boolean $full */ protected function handlePaths($data, $full=false) { foreach ($data as $pathData) { foreach ($data as $pathData) { $this->results[] = $this->getEntityMapper()->populatePath(new Path($this->client), $pathData, $full); } } } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetIndexes.php ================================================ type = $type; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'get'; } /** * Return the path to use * * @return string */ protected function getPath() { $type = trim((string)$this->type); if ($type != Index::TypeNode && $type != Index::TypeRelationship) { throw new Exception('No type specified for index'); } return '/index/'.$type; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to retrieve indexes', $code, $headers, $data); } if (!$data) { $data = array(); } $indexes = array(); foreach ($data as $name => $indexData) { $indexes[] = new Index($this->client, $this->type, $name, $indexData); } return $indexes; } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetLabels.php ================================================ node = $node; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'get'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->client->hasCapability(Client::CapabilityLabel)) { throw new \RuntimeException('The connected Neo4j version does not have label capability'); } $path = "/labels"; if ($this->node) { $id = $this->node->getId(); if (!is_numeric($id)) { throw new \InvalidArgumentException("Node given with no id"); } $path = "/node/{$id}{$path}"; } return $path; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return Row * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to labels', $code, $headers, $data); } $labels = array_map(array($this->client, 'makeLabel'), $data); return $labels; } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetNode.php ================================================ node = $node; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'get'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->node->hasId()) { throw new Exception('No node id specified'); } return '/node/'.$this->node->getId(); } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) == 2) { $this->node = $this->getEntityMapper()->populateNode($this->node, $data); $this->getEntityCache()->setCachedEntity($this->node); return true; } else { $this->throwException('Unable to retrieve node', $code, $headers, $data); } } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetNodeRelationships.php ================================================ node = $node; $this->dir = $dir; $this->types = $types; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'get'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->node->hasId()) { throw new Exception('No node id specified'); } $path = '/node/'.$this->node->getId().'/relationships/'.$this->dir; if (!empty($this->types)) { $types = array_map('rawurlencode', $this->types); $path .= '/'.join('&', $types); } return $path; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) == 2) { $rels = array(); foreach ($data as $relData) { $rels[] = $this->getEntityMapper()->makeRelationship($relData); } return $rels; } else { $this->throwException('Unable to retrieve node relationships', $code, $headers, $data); } } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetNodesForLabel.php ================================================ label = $label; $this->propertyName = $propertyName; $this->propertyValue = $propertyValue; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'get'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->client->hasCapability(Client::CapabilityLabel)) { throw new \RuntimeException('The connected Neo4j version does not have label capability'); } $labelName = rawurlencode($this->label->getName()); $path = "/label/{$labelName}/nodes"; if ($this->propertyName || $this->propertyValue) { if (!$this->propertyName || !$this->propertyValue) { throw new \InvalidArgumentException('Cannot specify a property name without a value, or vice versa'); } $propertyName = rawurlencode($this->propertyName); if (is_numeric($this->propertyValue)) { $propertyValue = rawurlencode($this->propertyValue); } else { $propertyValue = rawurlencode('"'.$this->propertyValue.'"'); } $path .= "?{$propertyName}={$propertyValue}"; } return $path; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return Row * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to retrieve nodes for label', $code, $headers, $data); } return new Row($this->client, array_keys($data), $data); } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetPaths.php ================================================ finder = $finder; } /** * Return the data to pass * * @return mixed */ protected function getData() { $data = array(); $end = $this->finder->getEndNode(); if (!$end || !$end->hasId()) { throw new Exception('No end node id specified'); } $endUri = $this->getTransport()->getEndpoint().'/node/'.$end->getId(); $data['to'] = $endUri; $algo = $this->finder->getAlgorithm(); if ($algo == PathFinder::AlgoDijkstra) { $property = $this->finder->getCostProperty(); if (!$property) { throw new Exception('No cost property specified for Dijkstra path search'); } $data['cost_property'] = $property; $data['cost property'] = $property; $cost = $this->finder->getDefaultCost(); if ($cost) { $data['default_cost'] = $cost; $data['default cost'] = $cost; } } $data['algorithm'] = $algo; $max = $this->finder->getMaxDepth(); if (!$max) { $max = 1; } $data['max_depth'] = $max; $data['max depth'] = $max; $type = $this->finder->getType(); $dir = $this->finder->getDirection(); if ($dir && !$type) { throw new Exception('No relationship type specified'); } else if ($type) { $rel = array('type'=>$type); if ($dir) { $rel['direction'] = $dir; } $data['relationships'] = $rel; } return $data; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { $start = $this->finder->getStartNode(); if (!$start || !$start->hasId()) { throw new Exception('No start node id specified'); } return '/node/'.$start->getId().'/paths'; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to retrieve paths', $code, $headers, $data); } $paths = array(); foreach ($data as $pathData) { $paths[] = $this->getEntityMapper()->populatePath(new Path($this->client), $pathData); } return $paths; } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetRelationship.php ================================================ rel = $rel; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'get'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->rel->hasId()) { throw new Exception('No relationship id specified'); } return '/relationship/'.$this->rel->getId(); } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) == 2) { $this->rel = $this->getEntityMapper()->populateRelationship($this->rel, $data); $this->getEntityCache()->setCachedEntity($this->rel); return true; } else { $this->throwException('Unable to retrieve relationship', $code, $headers, $data); } } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetRelationshipTypes.php ================================================ throwException('Unable to retrieve relationship types', $code, $headers, $data); } return $data; } } ================================================ FILE: lib/Everyman/Neo4j/Command/GetServerInfo.php ================================================ throwException('Unable to retrieve server info', $code, $headers, $data); } $data['version'] = $this->parseVersion($data['neo4j_version']); return $data; } /** * Parse the version into usable bits * * @param string $fullVersion * @return array */ protected function parseVersion($fullVersion) { $parts = explode('.', $fullVersion); $versionInfo = array( 'full' => $fullVersion, 'major' => $parts[0], 'minor' => $parts[1], ); if (empty($parts[2])) { $versionInfo['release'] = 'GA'; } else { $versionInfo['release'] = current(explode('-', $parts[2], 2)); } return $versionInfo; } } ================================================ FILE: lib/Everyman/Neo4j/Command/QueryIndex.php ================================================ key); return $path . '?query=' . $query; } } ================================================ FILE: lib/Everyman/Neo4j/Command/RemoveFromIndex.php ================================================ index = $index; $this->entity = $entity; $this->key = $key; $this->value = $value; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'delete'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->entity || !$this->entity->hasId()) { throw new Exception('No entity to index specified'); } $type = trim((string)$this->index->getType()); if ($type != Index::TypeNode && $type != Index::TypeRelationship) { throw new Exception('No type specified for index'); } else if ($type == Index::TypeNode && !($this->entity instanceof Node)) { throw new Exception('Cannot remove a node from a non-node index'); } else if ($type == Index::TypeRelationship && !($this->entity instanceof Relationship)) { throw new Exception('Cannot remove a relationship from a non-relationship index'); } $name = trim((string)$this->index->getName()); if (!$name) { throw new Exception('No name specified for index'); } $name = rawurlencode($name); $key = trim((string)$this->key); $value = trim((string)$this->value); $uri = '/index/'.$type.'/'.$name.'/'; if ($key) { $uri .= rawurlencode($key).'/'; if ($value) { $uri .= rawurlencode($value).'/'; } } $uri .= $this->entity->getId(); return $uri; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to remove entity from index', $code, $headers, $data); } return true; } } ================================================ FILE: lib/Everyman/Neo4j/Command/RemoveLabels.php ================================================ transaction = $transaction; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'delete'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->client->hasCapability(Client::CapabilityTransactions)) { throw new Exception('Transactions unavailable'); } $id = $this->transaction->getId(); if (!$id) { throw new Exception('Cannot rollback a transaction without a transaction id'); } $path = '/transaction/'.$id; return $path; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Error during transaction rollback', $code, $headers, $data); } return true; } } ================================================ FILE: lib/Everyman/Neo4j/Command/SaveIndex.php ================================================ index = $index; } /** * Return the data to pass * * @return mixed */ protected function getData() { $name = trim((string)$this->index->getName()); if (!$name) { throw new Exception('No name specified for index'); } $data = array('name' => $name); $config = $this->index->getConfig(); if ($config) { $data['config'] = $config; } return $data; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'post'; } /** * Return the path to use * * @return string */ protected function getPath() { $type = trim((string)$this->index->getType()); if ($type != Index::TypeNode && $type != Index::TypeRelationship) { throw new Exception('No type specified for index'); } return '/index/'.$type; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to save index', $code, $headers, $data); } return true; } } ================================================ FILE: lib/Everyman/Neo4j/Command/SearchIndex.php ================================================ index = $index; $this->key = $key; $this->value = $value; } /** * Return the data to pass * * @return mixed */ protected function getData() { return null; } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'get'; } /** * Return the path to use * * @return string */ protected function getPath() { $type = trim((string)$this->index->getType()); if ($type != Index::TypeNode && $type != Index::TypeRelationship) { throw new Exception('No type specified for index'); } $name = trim((string)$this->index->getName()); if (!$name) { throw new Exception('No name specified for index'); } $key = trim((string)$this->key); if (!$key) { throw new Exception('No key specified to search index'); } $name = rawurlencode($name); $key = rawurlencode($key); $value = rawurlencode($this->value); return '/index/'.$type.'/'.$name.'/'.$key.'/'.$value; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return integer on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) != 2) { $this->throwException('Unable to search index', $code, $headers, $data); } $buildMethod = $this->index->getType() == Index::TypeNode ? 'makeNode' : 'makeRelationship'; $results = array(); foreach ($data as $entityData) { $results[] = $this->getEntityMapper()->$buildMethod($entityData); } return $results; } } ================================================ FILE: lib/Everyman/Neo4j/Command/SetLabels.php ================================================ hasCapability(Client::CapabilityLabel)) { throw new \RuntimeException('The connected Neo4j version does not have label capability'); } $nodeId = $node->getId(); if (!is_numeric($nodeId)) { throw new \InvalidArgumentException("Cannot set labels on an unsaved node"); } if (!$labels) { throw new \InvalidArgumentException("No labels given to set on node"); } $labelSet = implode(':', array_map(function ($label) { if (!($label instanceof Label)) { throw new \InvalidArgumentException("Cannot set a non-label"); } $name = str_replace('`', '``', $label->getName()); return "`{$name}`"; }, $labels)); $setCommand = $remove ? 'REMOVE' : 'SET'; $query = "START n=node({nodeId}) {$setCommand} n:{$labelSet} RETURN labels(n) AS labels"; $params = array('nodeId' => $nodeId); $cypher = new Query($client, $query, $params); parent::__construct($client, $cypher); } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return array of Label */ protected function handleResult($code, $headers, $data) { $results = parent::handleResult($code, $headers, $data); $nodeLabels = array(); foreach ($results[0]['labels'] as $labelName) { $nodeLabels[] = $this->client->makeLabel($labelName); } return $nodeLabels; } } ================================================ FILE: lib/Everyman/Neo4j/Command/UpdateNode.php ================================================ node = $node; } /** * Return the data to pass * * @return mixed */ protected function getData() { return $this->node->getProperties(); } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'put'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->node->hasId()) { throw new Exception('No node id specified'); } return '/node/'.$this->node->getId().'/properties'; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) == 2) { $this->getEntityCache()->setCachedEntity($this->node); return true; } else { $this->throwException('Unable to update node', $code, $headers, $data); } } } ================================================ FILE: lib/Everyman/Neo4j/Command/UpdateRelationship.php ================================================ rel = $rel; } /** * Return the data to pass * * @return mixed */ protected function getData() { return $this->rel->getProperties(); } /** * Return the transport method to call * * @return string */ protected function getMethod() { return 'put'; } /** * Return the path to use * * @return string */ protected function getPath() { if (!$this->rel->hasId()) { throw new Exception('No relationship id specified'); } return '/relationship/'.$this->rel->getId().'/properties'; } /** * Use the results * * @param integer $code * @param array $headers * @param array $data * @return boolean true on success * @throws Exception on failure */ protected function handleResult($code, $headers, $data) { if ((int)($code / 100) == 2) { $this->getEntityCache()->setCachedEntity($this->rel); return true; } else { $this->throwException('Unable to update relationship', $code, $headers, $data); } } } ================================================ FILE: lib/Everyman/Neo4j/Command.php ================================================ client = $client; } /** * Return the data to pass * * @return mixed */ abstract protected function getData(); /** * Return the transport method to call * * @return string */ abstract protected function getMethod(); /** * Return the path to use * * @return string */ abstract protected function getPath(); /** * Use the results in some way * * @param integer $code * @param array $headers * @param array $data * @return mixed * @throws Exception on failure */ abstract protected function handleResult($code, $headers, $data); /** * Run the command and return a value signalling the result * * @return mixed * @throws Exception on failure */ public function execute() { $method = $this->getMethod(); $path = $this->getPath(); $data = $this->getData(); $result = $this->getTransport()->$method($path, $data); $resultCode = isset($result['code']) ? $result['code'] : Client::ErrorUnknown; $resultHeaders = isset($result['headers']) ? $result['headers'] : array(); $resultData = isset($result['data']) ? $result['data'] : array(); $parseResult = $this->handleResult($resultCode, $resultHeaders, $resultData); return $parseResult; } /** * Get the entity cache * * @return Cache\EntityCache */ protected function getEntityCache() { return $this->client->getEntityCache(); } /** * Get the entity mapper * * @return EntityMapper */ protected function getEntityMapper() { return $this->client->getEntityMapper(); } /** * Get the transport * * @return Transport */ protected function getTransport() { return $this->client->getTransport(); } /** * Throw an exception from handling the results * * @param string $message * @param integer $code * @param array $headers * @param array $data * @throws Exception */ protected function throwException($message, $code, $headers, $data) { $message = "{$message} [{$code}]:\nHeaders: " . print_r($headers, true) . "Body: " . print_r($data, true); throw new Exception($message, $code, $headers, $data); } } ================================================ FILE: lib/Everyman/Neo4j/Cypher/Query.php ================================================ client = $client; $this->template = $template; $this->vars = $vars; } /** * Get the query script * * @return string */ public function getQuery() { return $this->template; } /** * Get the template parameters * * @return array */ public function getParameters() { return $this->vars; } /** * Retrieve the query results * * @return Neo4j\Query\ResultSet */ public function getResultSet() { if ($this->result === null) { $this->result = $this->client->executeCypherQuery($this); } return $this->result; } } ================================================ FILE: lib/Everyman/Neo4j/EntityMapper.php ================================================ client = $client; } /** * Given any object, see if it fulfills the contract * for being a path, node or relationship data returned by the * server. If so, return a full Path, Node or Relationship instance. * Else, return the value untainted. * * @param mixed $value * @return mixed */ public function getEntityFor($value) { if (is_array($value)) { if (array_key_exists('self', $value)) { if (array_key_exists('type', $value)) { $value = $this->makeRelationship($value); } else { $value = $this->makeNode($value); } } else if (array_key_exists('nodes', $value) && array_key_exists('relationships', $value)) { $value = $this->populatePath(new Path($this->client), $value); } } return $value; } /** * Get an id from a URI * * @param string $uri * @return mixed */ public function getIdFromUri($uri) { $uriParts = explode('/', $uri); return array_pop($uriParts); } /** * Generate and populate a node from the given data * * @param array $data * @return Node */ public function makeNode($data) { $node = $this->getNodeFromUri($data['self']); return $this->populateNode($node, $data); } /** * Generate and populate a relationship from the given data * * @param array $data * @return Relationship */ public function makeRelationship($data) { $rel = $this->getRelationshipFromUri($data['self']); return $this->populateRelationship($rel, $data); } /** * Fill a node with data * * @param Node $node * @param array $data * @return Node */ public function populateNode(Node $node, $data) { $node->useLazyLoad(false); $node->setProperties($data['data']); return $node; } /** * Fill a path with data * * @param Path $path * @param array $data * @param boolean $full * @return Path */ public function populatePath(Path $path, $data, $full=false) { foreach ($data['relationships'] as $relData) { $relUri = $full ? $relData['self'] : $relData; $rel = $this->getRelationshipFromUri($relUri); if ($full) { $rel = $this->populateRelationship($rel, $relData); } $path->appendRelationship($rel); } foreach ($data['nodes'] as $nodeData) { $nodeUri = $full ? $nodeData['self'] : $nodeData; $node = $this->getNodeFromUri($nodeUri); if ($full) { $node = $this->populateNode($node, $nodeData); } $path->appendNode($node); } return $path; } /** * Fill a relationship with data * * @param Relationship $rel * @param array $data * @return Relationship */ public function populateRelationship(Relationship $rel, $data) { $rel->useLazyLoad(false); $rel->setProperties($data['data']); $rel->setType($data['type']); $rel->setStartNode($this->getNodeFromUri($data['start'])); $rel->setEndNode($this->getNodeFromUri($data['end'])); return $rel; } /** * Retrieve a node by it's 'self' uri * * @param string $uri * @return Node */ protected function getNodeFromUri($uri) { $nodeId = $this->getIdFromUri($uri); return $this->client->getNode($nodeId, true); } /** * Retrieve a relationship by it's 'self' uri * * @param string $uri * @return Relationship */ protected function getRelationshipFromUri($uri) { $relId = $this->getIdFromUri($uri); return $this->client->getRelationship($relId, true); } } ================================================ FILE: lib/Everyman/Neo4j/Exception.php ================================================ headers = $headers; $this->data = $data; parent::__construct($message, $code); } /** * Return response headers * @return array Response headers */ public function getHeaders() { return $this->headers; } /** * Return response data * @return array Response data */ public function getData() { return $this->data; } } ================================================ FILE: lib/Everyman/Neo4j/Geoff/Exporter.php ================================================ getNodes(); foreach ($pathNodes as $node) { $nodes[$node->getId()] = $node; } $pathRels = $path->getRelationships(); foreach ($pathRels as $rel) { $rels[$rel->getId()] = $rel; } } foreach ($nodes as $id => $node) { $properties = $node->getProperties(); $format = $properties ? "(%s)\t%s\n" : "(%s)\n"; fprintf( $handle, $format, $id, json_encode($properties) ); } foreach ($rels as $id => $rel) { $properties = $rel->getProperties(); $format = "(%s)-[%s:%s]->(%s)"; $format .= $properties ? "\t%s\n" : "\n"; fprintf( $handle, $format, $rel->getStartNode()->getId(), $id, $rel->getType(), $rel->getEndNode()->getId(), json_encode($properties) ); } } } ================================================ FILE: lib/Everyman/Neo4j/Geoff/Importer.php ================================================ client = $client; } /** * Load a GEOFF string from a stream * If a batch is provided, append imported data to it, * else, create and return a new batch * * @param stream $handle * @param Batch $batch * @return Batch */ public function load($handle, Batch $batch=null) { if (!is_resource($handle) || get_resource_type($handle) != 'stream') { throw new Exception("Not a stream resource"); } if (!$batch) { $batch = new Batch($this->client); } $i = 0; $nodes = array(); $rels = array(); while (($line = fgets($handle)) !== false) { $this->loadLine($line, $batch, $i, $nodes, $rels); $i++; } return $batch; } /** * Load a single line into the batch * * @param string $line * @param Batch $batch * @param integer $lineNum * @param array $nodes * @param array $rels */ protected function loadLine($line, Batch $batch, $lineNum, &$nodes, &$rels) { $descriptorPattern = "/^( \((\w+)\) # node identifier or relationship start node ( # next two sub expressions signify a relationship line -\[(\w*):(\w+)\] # relationship identifier and type ->\((\w+)\) # relationship end node )?)( \s+(.*) # properties )?/x"; $indexPattern = "/^( \{(\w+)\} # index name ->(\(|\[) # ( indicates node index, [ indicates relationship index (\w+) # node identifier to index (\)|\]) # must match opening ( or [ )( \s+(.*) # keys:values to index )?/x"; $line = trim($line); if (!$line || $line[0] == '#') { return; } $matches = array(); $descriptorMatch = preg_match($descriptorPattern, $line, $matches); if ($descriptorMatch && !empty($matches[3])) { $startNodeId = $matches[2]; $relId = $matches[4]; $type = $matches[5]; $endNodeId = $matches[6]; if (!isset($nodes[$startNodeId]) || !isset($nodes[$endNodeId])) { throw new Exception("Invalid node reference on line {$lineNum}: $line"); } else if (!empty($relId) && isset($rels[$relId])) { throw new Exception("Duplicate relationship on line {$lineNum}: $line"); } $properties = !empty($matches[8]) ? json_decode($matches[8]) : false; $rel = $this->client->makeRelationship(); $rel->setProperties($properties ?: array()) ->setType($type) ->setStartNode($nodes[$startNodeId]) ->setEndNode($nodes[$endNodeId]); if (!empty($relId)) { $rels[$relId] = $rel; } $batch->save($rel); return; } else if ($descriptorMatch) { $nodeId = $matches[2]; if (isset($nodes[$nodeId])) { throw new Exception("Duplicate node on line {$lineNum}: $line"); } $properties = !empty($matches[7]) ? json_decode($matches[7]) : false; $node = $this->client->makeNode(); $node->setProperties($properties ?: array()); $nodes[$nodeId] = $node; $batch->save($node); return; } $matches = array(); $indexMatch = preg_match($indexPattern, $line, $matches); if ($indexMatch) { $name = $matches[2]; $openBrace = $matches[3]; $closeBrace = $matches[5]; $entityId = $matches[4]; $properties = !empty($matches[7]) ? json_decode($matches[7]) : false; if ($properties) { $type = null; if ($openBrace == '(' && $closeBrace == ')') { if (!isset($nodes[$entityId])) { throw new Exception("Invalid node reference on line {$lineNum}: $line"); } $entity = $nodes[$entityId]; $type = Index::TypeNode; } else if ($openBrace == '[' && $closeBrace == ']') { if (!isset($rels[$entityId])) { throw new Exception("Invalid relationship reference on line {$lineNum}: $line"); } $entity = $rels[$entityId]; $type = Index::TypeRelationship; } if ($type) { $index = new Index($this->client, $type, $name); foreach ($properties as $key => $value) { $batch->addToIndex($index, $entity, $key, $value); } return; } } } throw new Exception("Cannot parse line {$lineNum}: $line"); } } ================================================ FILE: lib/Everyman/Neo4j/Geoff.php ================================================ client = $client; } /** * Dump path information to a GEOFF string or file * * @param mixed $paths a single Path object or an array of Path objects * @param stream $handle * @return mixed stream or string */ public function dump($paths, $handle=null) { $returnString = false; if (!$handle) { $returnString = true; $handle = fopen('data:text/plain,', 'w+'); } $exporter = new Geoff\Exporter(); $exporter->dump($paths, $handle); if ($returnString) { return stream_get_contents($handle, -1, 0); } return $handle; } /** * Load a GEOFF string or file * * @param mixed $handle * @param Batch $batch * @return Batch */ public function load($handle, Batch $batch=null) { if (is_string($handle)) { $handle = fopen('data:text/plain,'.urlencode($handle), 'r'); } $importer = new Geoff\Importer($this->client); return $importer->load($handle, $batch); } } ================================================ FILE: lib/Everyman/Neo4j/Gremlin/Query.php ================================================ client = $client; $this->script = $script; $this->vars = $vars; } /** * Get the query script * * @return string */ public function getQuery() { return $this->script; } /** * Get the template parameters * * @return array */ public function getParameters() { return $this->vars; } /** * Retrieve the query results * * @return Neo4j\Query\ResultSet */ public function getResultSet() { if ($this->result === null) { $this->result = $this->client->executeGremlinQuery($this); } return $this->result; } } ================================================ FILE: lib/Everyman/Neo4j/Index/NodeFulltextIndex.php ================================================ client = $client; $this->type = $type; $this->name = $name; $this->config = $config; } /** * Add an entity to the index * * @param PropertyContainer $entity * @param string $key * @param string $value * @return boolean */ public function add($entity, $key, $value) { return $this->client->addToIndex($this, $entity, $key, $value); } /** * Delete this index * * @return boolean */ public function delete() { return $this->client->deleteIndex($this); } /** * Find entities * * @param string $key * @param string $value * @return array */ public function find($key, $value) { return $this->client->searchIndex($this, $key, $value); } /** * Find a single entity * * @param string $key * @param string $value * @return PropertyContainer */ public function findOne($key, $value) { $entities = $this->client->searchIndex($this, $key, $value); return $entities ? $entities[0] : null; } /** * Get the configuration options for this index * * Configuration options are only used during index creation, * see `save` * * @return array */ public function getConfig() { return $this->config; } /** * Get the index name * * @return string */ public function getName() { return $this->name; } /** * Get the index type * * @return string */ public function getType() { return $this->type; } /** * Query index to find entities * * @param string $query * @return array */ public function query($query) { return $this->client->queryIndex($this, $query); } /** * Query index to find a single entity * * @param string $query * @return PropertyContainer */ public function queryOne($query) { $entities = $this->client->queryIndex($this, $query); return $entities ? $entities[0] : null; } /** * Remove an entity from the index * If $value is not given, all reference of the entity for the key * are removed. * If $key is not given, all reference of the entity are removed. * * @param PropertyContainer $entity * @param string $key * @param string $value * @return boolean */ public function remove($entity, $key=null, $value=null) { return $this->client->removeFromIndex($this, $entity, $key, $value); } /** * Save this index * * @return boolean */ public function save() { return $this->client->saveIndex($this); } } ================================================ FILE: lib/Everyman/Neo4j/Label.php ================================================ setClient($client); $this->name = (string)$name; } /** * Set the client to use with this Label object * * @param Client $client * @return Label */ public function setClient(Client $client) { $this->client = $client; return $this; } /** * Get our client * * @return Client */ public function getClient() { return $this->client; } /** * Return the label name * * @return string */ public function getName() { return $this->name; } /** * Get the nodes with this label * * If a property and value are given, only return * nodes where the given property equals the value * * @param string $propertyName * @param mixed $propertyValue * @return Query\Row * @throws Exception on failure */ public function getNodes($propertyName=null, $propertyValue=null) { return $this->client->getNodesForLabel($this, $propertyName, $propertyValue); } /** * Only serialize our name property * * @return array */ public function __sleep() { return array('name'); } } ================================================ FILE: lib/Everyman/Neo4j/Node.php ================================================ labels) { foreach ($this->labels as $label) { if (!$label->getClient()) { $label->setClient($client); } } } return $this; } /** * Add labels to this node * * @param array $labels * @return array of all the Labels on this node, including those just added */ public function addLabels($labels) { $this->labels = $this->client->addLabels($this, $labels); return $this->labels; } /** * Delete this node * * @return PropertyContainer * @throws Exception on failure */ public function delete() { $this->client->deleteNode($this); return $this; } /** * Find paths from this node to the given node * * @param Node $to * @param string $type * @param string $dir * @return PathFinder */ public function findPathsTo(Node $to, $type=null, $dir=null) { $finder = new PathFinder($this->client); $finder->setStartNode($this); $finder->setEndNode($to); if ($dir) { $finder->setDirection($dir); } if ($type) { $finder->setType($type); } return $finder; } /** * Get the first relationship of this node that matches the given criteria * * @param mixed $types string or array of strings * @param string $dir * @return Relationship */ public function getFirstRelationship($types=array(), $dir=null) { $rels = $this->client->getNodeRelationships($this, $types, $dir); if (count($rels) < 1) { return null; } return $rels[0]; } /** * Get relationships of this node * * @param mixed $types string or array of strings * @param string $dir * @return array of Relationship */ public function getRelationships($types=array(), $dir=null) { return $this->client->getNodeRelationships($this, $types, $dir); } /** * List labels for this node * * @return array * @throws Exception on failure */ public function getLabels() { if (is_null($this->labels)) { $this->labels = $this->client->getLabels($this); } return $this->labels; } /** * Load this node * * @return PropertyContainer * @throws Exception on failure */ public function load() { $this->client->loadNode($this); return $this; } /** * Make a new relationship * * @param Node $to * @param string $type * @return Relationship */ public function relateTo(Node $to, $type) { $rel = $this->client->makeRelationship(); $rel->setStartNode($this); $rel->setEndNode($to); $rel->setType($type); return $rel; } /** * Remove labels from this node * * @param array $labels * @return array of all the Labels on this node, after removing the given labels */ public function removeLabels($labels) { $this->labels = $this->client->removeLabels($this, $labels); return $this->labels; } /** * Save this node * * @return PropertyContainer * @throws Exception on failure */ public function save() { $this->client->saveNode($this); $this->useLazyLoad(false); return $this; } /** * Be sure to add our properties to the things to serialize * * @return array */ public function __sleep() { return array_merge(parent::__sleep(), array('labels')); } } ================================================ FILE: lib/Everyman/Neo4j/Pager.php ================================================ traversal = $traversal; $this->startNode = $startNode; $this->returnType = $returnType; } /** * Get the paged traversal id * * @return string */ public function getId() { return $this->id; } /** * Get the lease time, in secods * * @return integer */ public function getLeaseTime() { return $this->leaseTime; } /** * Get the next page of results * If the traversal hasn't been run yet, this will run it * * @return array */ public function getNextResults() { return $this->traversal->getClient()->executePagedTraversal($this); } /** * Get the maximum result page set size * * @return integer */ public function getPageSize() { return $this->pageSize; } /** * Get the return type * * @return string */ public function getReturnType() { return $this->returnType; } /** * Return the start node of the traversal * * @return Node */ public function getStartNode() { return $this->startNode; } /** * Get the traversal being paginated * * @return Traversal */ public function getTraversal() { return $this->traversal; } /** * Set the paged traversal id * * @param string $id * @return Traversal */ public function setId($id) { $this->id = $id; return $this; } /** * Set the lease time * * @param integer $leaseTime * @return Traversal */ public function setLeaseTime($leaseTime) { $this->leaseTime = $leaseTime; return $this; } /** * Set the page size * * @param integer $pageSize * @return Traversal */ public function setPageSize($pageSize) { $this->pageSize = $pageSize; return $this; } } ================================================ FILE: lib/Everyman/Neo4j/Path.php ================================================ nodes[] = $node; } /** * Add another relationship to the end of this path * * @param Relationship $rel * @return Path */ public function appendRelationship(Relationship $rel) { $this->relationships[] = $rel; } /** * Get the number of relationships in this path * * @return integer */ public function count() { return $this->context == self::ContextNode ? count($this->nodes) : count($this->relationships); } /** * Get the current context for iteration * * @return string */ public function getContext() { return $this->context; } /** * Get the end node * * @return Node */ public function getEndNode() { $length = count($this->nodes); if ($length) { return $this->nodes[$length-1]; } return null; } /** * Get the number of relationships in this path * * @return integer */ public function getLength() { return $this->count(); } /** * Return an iterator for iterating through the path * * @return Iterator */ public function getIterator() { return $this->context == self::ContextNode ? new \ArrayIterator($this->nodes) : new \ArrayIterator($this->relationships); } /** * Get the list of nodes that make up this path * * @return array */ public function getNodes() { return $this->nodes; } /** * Get the list of relationships that make up this path * * @return array */ public function getRelationships() { return $this->relationships; } /** * Get the start node * * @return Node */ public function getStartNode() { $length = count($this->nodes); if ($length) { return $this->nodes[0]; } return null; } /** * Set the context for iteration * * @param string $context * @return Path */ public function setContext($context) { if ($context != self::ContextNode && $context != self::ContextRelationship) { $context = self::ContextNode; } $this->context = $context; return $this; } } ================================================ FILE: lib/Everyman/Neo4j/PathFinder.php ================================================ client = $client; } /** * Get the current path finding algorithm * * @return string */ public function getAlgorithm() { return $this->algo; } /** * Get the finder's client * * @return Client */ public function getClient() { return $this->client; } /** * Get the cost property name for the Dijkstra search * * @return string */ public function getCostProperty() { return $this->costProperty; } /** * Get the default relationship cost for the Dijkstra search * * @return numeric */ public function getDefaultCost() { return $this->defaultCost; } /** * Get the path direction type * * @return string */ public function getDirection() { return $this->dir; } /** * Get the end node * * @return Node */ public function getEndNode() { return $this->end; } /** * Get the maximum allowed path length * * @return integer */ public function getMaxDepth() { return $this->maxDepth; } /** * Find paths * * @return array of Path */ public function getPaths() { return $this->client->getPaths($this); } /** * Get a single path * * @return Path */ public function getSinglePath() { $paths = $this->getPaths(); return $paths ? $paths[0] : null; } /** * Get the start node * * @return Node */ public function getStartNode() { return $this->start; } /** * Get the relationship type * * @return string */ public function getType() { return $this->type; } /** * Set the algorithm to use * * @param string $algo * @return PathFinder */ public function setAlgorithm($algo) { $this->algo = $algo; return $this; } /** * Set the cost property name for the Dijkstra search * * @param string $property * @return PathFinder */ public function setCostProperty($property) { $this->costProperty = $property; return $this; } /** * Set the default relationship cost for the Dijkstra search * * @param numeric $cost * @return PathFinder */ public function setDefaultCost($cost) { $this->defaultCost = $cost; return $this; } /** * Set the direction of the path * * @param string $dir * @return PathFinder */ public function setDirection($dir) { $this->dir = $dir; return $this; } /** * Set the end node * * @param Node $end * @return PathFinder */ public function setEndNode(Node $end) { $this->end = $end; return $this; } /** * Set the maximum allowed path length * * @param integer $max * @return PathFinder */ public function setMaxDepth($max) { $this->maxDepth = $max; return $this; } /** * Set the start node * * @param Node $start * @return PathFinder */ public function setStartNode(Node $start) { $this->start = $start; return $this; } /** * Set the type * * @param string $type * @return PathFinder */ public function setType($type) { $this->type = $type; return $this; } } ================================================ FILE: lib/Everyman/Neo4j/PropertyContainer.php ================================================ setClient($client); } public function __get($key) { return $this->getProperty($key); } public function __set($key, $value) { $this->setProperty($key, $value); } public function __unset($key) { $this->removeProperty($key); } public function __isset($key) { return array_key_exists($key, $this->properties); } public function __sleep() { return array('id', 'properties', 'lazyLoad', 'loaded'); } /** * Delete this entity * * @return PropertyContainer * @throws Exception on failure */ abstract public function delete(); /** * Load this entity * * @return PropertyContainer * @throws Exception on failure */ abstract public function load(); /** * Save this entity * * @return PropertyContainer * @throws Exception on failure */ abstract public function save(); /** * Get the entity's client * * @return Client */ public function getClient() { return $this->client; } /** * Get the entity's id * * @return integer */ public function getId() { return $this->id; } /** * Return all properties * * @return array */ public function getProperties() { $this->loadProperties(); return $this->properties; } /** * Return the named property * * @param string $property * @return mixed */ public function getProperty($property) { $this->loadProperties(); return (isset($this->properties[$property])) ? $this->properties[$property] : null; } /** * Is this entity identified? * * @return boolean */ public function hasId() { return $this->getId() !== null; } /** * Remove a property set on the entity * * @param string $property * @return PropertyContainer */ public function removeProperty($property) { $this->loadProperties(); unset($this->properties[$property]); return $this; } /** * Set the entity's client * * @param Client $client * @return PropertyContainer */ public function setClient(Client $client) { $this->client = $client; return $this; } /** * Set the entity's id * * @param integer $id * @return PropertyContainer */ public function setId($id) { $this->id = $id === null ? null : (int)$id; return $this; } /** * Set multiple properties on the entity * * @param array $properties * @return PropertyContainer */ public function setProperties($properties) { $this->loadProperties(); foreach ($properties as $property => $value) { $this->setProperty($property, $value); } return $this; } /** * Set a property on the entity * * @param string $property * @param mixed $value * @return PropertyContainer */ public function setProperty($property, $value) { $this->loadProperties(); if ($value === null) { $this->removeProperty($property); } else { $this->properties[$property] = $value; } return $this; } /** * Should this entity be lazy-loaded if necessary? * * @param boolean $lazyLoad * @return PropertyContainer */ public function useLazyLoad($lazyLoad) { $this->lazyLoad = (bool)$lazyLoad; return $this; } /** * Set up the properties array the first time we need it * * This includes loading the properties from the server * if we can get them. */ protected function loadProperties() { if ($this->hasId() && $this->lazyLoad && !$this->loaded) { $this->loaded = true; $this->load(); } } } ================================================ FILE: lib/Everyman/Neo4j/Query/ResultSet.php ================================================ client = $client; if (is_array($result) && array_key_exists('data', $result)) { $this->data = $result['data']; $this->columns = $result['columns']; } } /** * Return the list of column names * * @return array */ public function getColumns() { return $this->columns; } // ArrayAccess API public function offsetExists($offset) { return isset($this->data[$offset]); } public function offsetGet($offset) { if (!isset($this->rows[$offset])) { $this->rows[$offset] = new Row($this->client, $this->columns, $this->data[$offset]); } return $this->rows[$offset]; } public function offsetSet($offset, $value) { throw new \BadMethodCallException("You cannot modify a query result."); } public function offsetUnset($offset) { throw new \BadMethodCallException("You cannot modify a query result."); } // Countable API public function count() { return count($this->data); } // Iterator API public function rewind() { $this->position = 0; } public function current() { return $this[$this->position]; } public function key() { return $this->position; } public function next() { ++$this->position; } public function valid() { return isset($this->data[$this->position]); } } ================================================ FILE: lib/Everyman/Neo4j/Query/Row.php ================================================ client = $client; $this->raw = $rowData; $this->data = array(); $this->columns = $columns; } // ArrayAccess API public function offsetExists($offset) { if (!is_integer($offset)) { $rawOffset = array_search($offset, $this->columns); if ($rawOffset === false) { return false; } return isset($this->raw[$rawOffset]); } return isset($this->raw[$offset]); } public function offsetGet($offset) { if (!is_integer($offset)) { $offset = array_search($offset, $this->columns); } if (!isset($this->data[$offset])) { $raw = $this->raw[$offset]; $data = $this->client->getEntityMapper()->getEntityFor($raw); if (is_array($data)) { $data = new Row($this->client, array_keys($raw), array_values($raw)); } $this->data[$offset] = $data; } return $this->data[$offset]; } public function offsetSet($offset, $value) { throw new \BadMethodCallException("You cannot modify a result row."); } public function offsetUnset($offset) { throw new \BadMethodCallException("You cannot modify a result row."); } // Countable API public function count() { return count($this->raw); } // Iterator API public function rewind() { $this->position = 0; } public function current() { return $this[$this->position]; } public function key() { return $this->columns[$this->position]; } public function next() { ++$this->position; } public function valid() { return $this->position < count($this->raw); } } ================================================ FILE: lib/Everyman/Neo4j/Query.php ================================================ start && !$this->start->getClient()) { $this->start->setClient($client); } if ($this->end && !$this->end->getClient()) { $this->end->setClient($client); } return $this; } /** * Delete this relationship * * @return PropertyContainer * @throws Exception on failure */ public function delete() { $this->client->deleteRelationship($this); return $this; } /** * Get the end node * * @return Node */ public function getEndNode() { if (null === $this->end) { $this->loadProperties(); } return $this->end; } /** * Get the start node * * @return Node */ public function getStartNode() { if (null === $this->start) { $this->loadProperties(); } return $this->start; } /** * Get the relationship type * * @return string */ public function getType() { $this->loadProperties(); return $this->type; } /** * Load this relationship * * @return PropertyContainer * @throws Exception on failure */ public function load() { $this->client->loadRelationship($this); return $this; } /** * Save this node * * @return PropertyContainer * @throws Exception on failure */ public function save() { $this->client->saveRelationship($this); $this->useLazyLoad(false); return $this; } /** * Set the end node * * @param Node $end * @return Relationship */ public function setEndNode(Node $end) { $this->end = $end; return $this; } /** * Set the start node * * @param Node $start * @return Relationship */ public function setStartNode(Node $start) { $this->start = $start; return $this; } /** * Set the type * * @param string $type * @return Relationship */ public function setType($type) { $this->type = $type; return $this; } /** * Be sure to add our properties to the things to serialize * * @return array */ public function __sleep() { return array_merge(parent::__sleep(), array('start', 'end', 'type')); } } ================================================ FILE: lib/Everyman/Neo4j/Transaction.php ================================================ client = $client; } /** * Add statements to this transaction * * @param mixed $statements a single or list of Cypher\Query objects to add to the transaction * @param boolean $commit should this transaction be committed with these statements? * @return Query\ResultSet */ public function addStatements($statements, $commit=false) { $unwrap = false; if (!is_array($statements)) { $statements = array($statements); $unwrap = true; } $result = $this->performClientAction(function ($client, $transaction) use ($statements, $commit) { return $client->addStatementsToTransaction($transaction, $statements, $commit); }, $commit, false); if ($unwrap) { $result = reset($result); } return $result; } /** * Commit this transaction immediately, without adding any new statements * * @return Transaction */ public function commit() { $this->performClientAction(function ($client, $transaction) { $client->addStatementsToTransaction($transaction, array(), true); }, true); return $this; } /** * Return the transaction id * * @return integer */ public function getId() { return $this->id; } /** * Has this transaction been closed? * * @return boolean */ public function isClosed() { return $this->isClosed; } /** * Has this transaction experienced an error? * * @return boolean */ public function isError() { return $this->isError; } /** * Ask for more time to keep this transaction open * * @return Transaction */ public function keepAlive() { $this->performClientAction(function ($client, $transaction) { $client->addStatementsToTransaction($transaction); }, false); return $this; } /** * Rollback the transaction * * @return Transaction */ public function rollback() { $this->performClientAction(function ($client, $transaction) { $client->rollbackTransaction($transaction); }, true); return $this; } /** * Set the transaction id * * Once an id has been set, the same id can be set again. * Attempting to set a different id will throw an InvalidArgumentException. * * @param integer $id * @return Transaction * @throws InvalidArgumentException if an id is given that is different from the existing id */ public function setId($id) { if ($this->id && $this->id != $id) { throw new \InvalidArgumentException("Cannot set a new id on a transaction once an id has been set"); } $this->id = $id; return $this; } /** * Perform an action against the client * * @param callable $action * @param boolean $shouldClose * @param boolean $requireId */ protected function performClientAction($action, $shouldClose, $requireId=true) { if ($this->isClosed()) { throw new Exception('Transaction is already closed'); } $result = null; if (!$requireId || $this->getId()) { try { $result = $action($this->client, $this); } catch (\Exception $e) { $this->isClosed = true; $this->isError = true; throw $e; } } $this->isClosed = $shouldClose; return $result; } } ================================================ FILE: lib/Everyman/Neo4j/Transport/Curl.php ================================================ handle) { curl_close($this->handle); } } /** * @inherit */ public function makeRequest($method, $path, $data=array()) { $url = $this->getEndpoint().$path; $options = array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLOPT_HTTPHEADER => array( 'Accept: application/json;stream=true', 'Content-type: application/json', 'User-Agent: '.Version::userAgent(), 'X-Stream: true' ), CURLOPT_CUSTOMREQUEST => self::GET, CURLOPT_POST => false, CURLOPT_POSTFIELDS => null, CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, ); if ($this->username && $this->password) { $options[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC; $options[CURLOPT_USERPWD] = $this->username.':'.$this->password; } switch ($method) { case self::DELETE: $options[CURLOPT_CUSTOMREQUEST] = self::DELETE; break; case self::POST: case self::PUT: $dataString = $this->encodeData($data); $options[CURLOPT_CUSTOMREQUEST] = $method; $options[CURLOPT_POSTFIELDS] = $dataString; $options[CURLOPT_HTTPHEADER][] = 'Content-Length: '.strlen($dataString); if (self::POST == $method) { $options[CURLOPT_POST] = true; } break; } $ch = $this->getHandle(); curl_setopt_array($ch, $options); $response = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); if ($response === false) { throw new Exception("Can't open connection to ".$url); } if (!$code) { $code = 500; $headerSize = 0; $response = json_encode(array("error"=>curl_error($ch).' ['.curl_errno($ch).']')); } $bodyString = substr($response, $headerSize); $bodyData = json_decode($bodyString, true); $headerString = substr($response, 0, $headerSize); $headers = explode("\r\n", $headerString); foreach ($headers as $i => $header) { unset($headers[$i]); $parts = explode(':', $header); if (isset($parts[1])) { $name = trim(array_shift($parts)); $value = join(':', $parts); $headers[$name] = $value; } } return array( 'code' => $code, 'headers' => $headers, 'data' => $bodyData, ); } /** * Get the cURL handle * * @return resource cURL handle */ protected function getHandle() { if (!$this->handle) { $this->handle = curl_init(); } return $this->handle; } } ================================================ FILE: lib/Everyman/Neo4j/Transport/Stream.php ================================================ getEndpoint().$path; $context_options = array ( $this->scheme => array ( 'method' => 'GET', 'ignore_errors' => true, 'header'=> "Content-type: application/json\r\n" . "Accept: application/json;stream=true\r\n" . "User-Agent: ".Version::userAgent()."\r\n" . "X-Stream: true\r\n" ) ); if ($this->username && $this->password) { $encodedAuth = base64_encode($this->username.':'.$this->password); $context_options[$this->scheme]['header'] .= 'Authorization: Basic ' . $encodedAuth . "\r\n"; } switch ($method) { case self::DELETE: $context_options[$this->scheme]['method'] = self::DELETE; break; 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"; break; } $context = stream_context_create($context_options); $response = file_get_contents($url, false, $context); if ($response === false) { throw new Exception("Can't open connection to ".$url); } // $http_response_header is set by file_get_contents with the http:// wrapper preg_match('/^HTTP\/1\.[0-1] (\d{3})/', $http_response_header[0], $parts); $code = $parts[1]; if (!$code) { $code = 500; $response = json_encode(array("error"=>'error [' . $code . ']')); } $bodyData = json_decode($response, true); $headers = array(); foreach ($http_response_header as $header) { $parts = explode(':', $header, 2); if (count($parts) == 2) { $headers[$parts[0]] = $parts[1]; } } return array( 'code' => $code, 'headers' => $headers, 'data' => $bodyData, ); } } ================================================ FILE: lib/Everyman/Neo4j/Transport.php ================================================ host = $host; $this->port = $port; } /** * Return the Neo4j REST endpoint * * @return string */ public function getEndpoint() { return "{$this->scheme}://{$this->host}:{$this->port}{$this->path}"; } /** * Encode data for transport * * @param mixed $data * @return string */ public function encodeData($data) { $encoded = ''; if (!is_scalar($data)) { if ($data) { $keys = array_keys($data); $nonNumeric = array_filter($keys, function ($var) { return !is_int($var); }); if ($nonNumeric) { $data = (object)$data; } } else { $data = (object)$data; } } $encoded = json_encode($data); return $encoded; } /** * Make a request against the endpoint * Returned array has the following elements: * 'code' => the HTTP status code returned * 'headers' => array of HTTP headers, indexed by header name * 'data' => array return data * * @param string $method * @param string $path * @param array $data * @return array */ abstract public function makeRequest($method, $path, $data=array()); /** * Make a GET request * * @param $path * @param $data * @return array see 'makeRequest' */ public function get($path, $data=array()) { return $this->makeRequest(self::GET, $path, $data); } /** * Make a POST request * * @param $path * @param $data * @return array see 'makeRequest' */ public function post($path, $data=array()) { return $this->makeRequest(self::POST, $path, $data); } /** * Make a PUT request * * @param $path * @param $data * @return array see 'makeRequest' */ public function put($path, $data=array()) { return $this->makeRequest(self::PUT, $path, $data); } /** * Make a DELETE request * * @param $path * @return array see 'makeRequest' */ public function delete($path) { return $this->makeRequest(self::DELETE, $path); } /** * Set username and password to use with HTTP Basic Auth * * Returns this Trnasport object * * @param string $username * @param string $password * @return Transport */ public function setAuth($username=null, $password=null) { $this->username = $username; $this->password = $password; return $this; } /** * Turn HTTPS on or off * * Returns this Trnasport object * * @param boolean $useHttps * @return Transport */ public function useHttps($useHttps=true) { $this->scheme = $useHttps ? 'https' : 'http'; return $this; } } ================================================ FILE: lib/Everyman/Neo4j/Traversal.php ================================================ client = $client; } /** * Add a relationship type and direction * * @param string $type * @param string $direction * @return Traversal */ public function addRelationship($type, $direction=null) { $relationship = array('type'=>$type); if ($direction) { $relationship['direction'] = $direction; } $this->relationships[] = $relationship; return $this; } /** * Get the finder's client * * @return Client */ public function getClient() { return $this->client; } /** * Get the maximum allowed path length * * @return integer */ public function getMaxDepth() { return $this->maxDepth; } /** * Return the order in which to traverse * * @return string */ public function getOrder() { return $this->order; } /** * Get the prune evaluator * * @return array ('language'=>..., 'body'=>...) */ public function getPruneEvaluator() { return $this->pruneEvaluator; } /** * Get the relationship type and description * * @return array ('type'=>..., 'direction'=>...) */ public function getRelationships() { return $this->relationships; } /** * Run the traversal, and return the results * * @param Node $startNode * @param string $returnType * @return array */ public function getResults(Node $startNode, $returnType) { return $this->client->executeTraversal($this, $startNode, $returnType); } /** * Get the return filter * * @return array ('language'=>..., 'body'=>...) */ public function getReturnFilter() { return $this->returnFilter; } /** * Run the traversal, and return the first result * * @param Node $startNode * @param string $returnType * @return mixed */ public function getSingleResult(Node $startNode, $returnType) { $results = $this->getResults($startNode, $returnType); return $results ? $results[0] : null; } /** * Return the uniqueness of the traversal * * @return string */ public function getUniqueness() { return $this->uniqueness; } /** * Set the maximum allowed path length * * @param integer $max * @return Traversal */ public function setMaxDepth($max) { $this->maxDepth = $max; return $this; } /** * Set the order in which to traverse * * @param string $order * @return Traversal */ public function setOrder($order) { $this->order = $order; return $this; } /** * Set the prune evaluator * If language is one of the special builtin self::Prune* constants, * the evaluator language will be set to 'builtin' and the body * will be set to the value of the constant. * * @param string $language * @param string $body * @return Traversal */ public function setPruneEvaluator($language=null, $body=null) { if (!$language) { $this->pruneEvaluator = null; } else if ($language == self::PruneNone) { $this->pruneEvaluator = array( 'language' => self::Builtin, 'body' => $language, ); } else { $this->pruneEvaluator = array( 'language' => $language, 'body' => $body, ); } return $this; } /** * Set the return filter * If language is one of the special builtin self::Return* constants, * the filter language will be set to 'builtin' and the body * will be set to the value of the constant. * * @param string $language * @param string $body * @return Traversal */ public function setReturnFilter($language=null, $body=null) { if (!$language) { $this->returnFilter = null; } else if ($language == self::ReturnAll || $language == self::ReturnAllButStart) { $this->returnFilter = array( 'language' => self::Builtin, 'body' => $language, ); } else { $this->returnFilter = array( 'language' => $language, 'body' => $body, ); } return $this; } /** * Set the uniquenss * * @param string $uniqueness * @return Traversal */ public function setUniqueness($uniqueness) { $this->uniqueness = $uniqueness; return $this; } } ================================================ FILE: lib/Everyman/Neo4j/Version.php ================================================ getMetaData(); if ($command == '-help') { echo <<] -help Display help text -license Display software license -readme Display README -version Display version information () Test connection to Neo4j instance on host (port defaults to 7474) HELP; } else if ($command == '-license') { echo file_get_contents('phar://neo4jphp.phar/LICENSE')."\n\n"; } else if ($command == '-readme') { echo file_get_contents('phar://neo4jphp.phar/README.md')."\n\n"; } else if ($command == '-version') { echo "Neo4jPHP version {$meta['version']}\n\n"; } else { $port = empty($_SERVER['argv'][2]) ? 7474 : $_SERVER['argv'][2]; $client = new Everyman\Neo4j\Client($command, $port); print_r($client->getServerInfo()); } exit(0); } __HALT_COMPILER(); ================================================ FILE: tests/cs/ruleset.xml ================================================ Code style guidelines for the Neo4jPHP library ================================================ FILE: tests/phpunit.xml ================================================ ./unit ================================================ FILE: tests/unit/lib/Everyman/Neo4j/BatchTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->batch = new Batch($this->client); } public function testGetClient_ClientSetCorrectly_ReturnsClient() { $this->assertSame($this->client, $this->batch->getClient()); } public function testCommit_PassesSelfToClient_Success_ReturnsTrue() { $this->client->expects($this->once()) ->method('commitBatch') ->with($this->batch) ->will($this->returnValue(true)); $this->assertTrue($this->batch->commit()); } public function testCommit_PassesSelfToClient_Failure_ReturnsFalse() { $this->client->expects($this->once()) ->method('commitBatch') ->with($this->batch) ->will($this->returnValue(false)); $this->assertFalse($this->batch->commit()); } public function testCommit_CommitMoreThanOnce_ThrowsException() { $this->client->expects($this->once()) ->method('commitBatch'); $this->batch->commit(); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->batch->commit(); } public function testSave_PropertyContainerEntities_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $nodeA->setId(123); $nodeB = new Node($this->client); $nodeB->setId(456); $nodeC = new Node($this->client); $rel = new Relationship($this->client); $rel->setId(987) ->setStartNode($nodeA) ->setEndNode($nodeB); $this->assertEquals(0, $this->batch->save($nodeA)); $this->assertEquals(1, $this->batch->save($nodeB)); $this->assertEquals(2, $this->batch->save($nodeC)); $this->assertEquals(3, $this->batch->save($rel)); } public function testSave_SameEntityMoreThanOnce_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $this->assertEquals(0, $this->batch->save($nodeA)); $this->assertEquals(0, $this->batch->save($nodeA)); } public function testDelete_PropertyContainerEntities_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $nodeA->setId(123); $nodeB = new Node($this->client); $nodeB->setId(456); $nodeC = new Node($this->client); $rel = new Relationship($this->client); $rel->setId(987) ->setStartNode($nodeA) ->setEndNode($nodeB); $this->assertEquals(0, $this->batch->delete($nodeA)); $this->assertEquals(1, $this->batch->delete($nodeB)); $this->assertEquals(2, $this->batch->delete($nodeC)); $this->assertEquals(3, $this->batch->delete($rel)); } public function testDelete_SameEntityMoreThanOnce_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $this->assertEquals(0, $this->batch->delete($nodeA)); $this->assertEquals(0, $this->batch->delete($nodeA)); } public function testAddToIndex_Index_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $nodeA->setId(123); $nodeB = new Node($this->client); $nodeB->setId(456); $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->assertEquals(0, $this->batch->addToIndex($index, $nodeA, 'somekey', 'somevalue')); $this->assertEquals(1, $this->batch->addToIndex($index, $nodeB, 'otherkey', 'othervalue')); $this->assertEquals(2, $this->batch->addToIndex($index, $nodeB, 'diffkey', 'diffvalue')); } public function testAddToIndex_SameEntitySameKeyValueMoreThanOnce_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->assertEquals(0, $this->batch->addToIndex($index, $nodeA, 'somekey', 'somevalue')); $this->assertEquals(0, $this->batch->addToIndex($index, $nodeA, 'somekey', 'somevalue')); } public function testRemoveFromIndex_Index_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $nodeA->setId(123); $nodeB = new Node($this->client); $nodeB->setId(456); $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->assertEquals(0, $this->batch->removeFromIndex($index, $nodeA, 'somekey', 'somevalue')); $this->assertEquals(1, $this->batch->removeFromIndex($index, $nodeA, 'otherkey')); $this->assertEquals(2, $this->batch->removeFromIndex($index, $nodeA)); $this->assertEquals(3, $this->batch->removeFromIndex($index, $nodeB, 'diffkey', 'diffvalue')); } public function testRemoveFromIndex_SameEntitySameKeyValueMoreThanOnce_ReturnsIntegerOperationIndex() { $nodeA = new Node($this->client); $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->assertEquals(0, $this->batch->removeFromIndex($index, $nodeA, 'somekey', 'somevalue')); $this->assertEquals(0, $this->batch->removeFromIndex($index, $nodeA, 'somekey', 'somevalue')); $this->assertEquals(1, $this->batch->removeFromIndex($index, $nodeA, 'otherkey')); $this->assertEquals(1, $this->batch->removeFromIndex($index, $nodeA, 'otherkey')); $this->assertEquals(2, $this->batch->removeFromIndex($index, $nodeA)); $this->assertEquals(2, $this->batch->removeFromIndex($index, $nodeA)); } public function testGetOperations_MixedOperations_ReturnsOperations() { $nodeA = new Node($this->client); $this->assertEquals(0, $this->batch->save($nodeA)); $this->assertEquals(1, $this->batch->delete($nodeA)); $operations = $this->batch->getOperations(); $this->assertInternalType('array', $operations); $this->assertEquals(2, count($operations)); $saveMatch = new Batch\Save($this->batch, $nodeA, 123); $deleteMatch = new Batch\Delete($this->batch, $nodeA, 456); $this->assertEquals($saveMatch->matchId(), $operations[0]->matchId()); $this->assertEquals($deleteMatch->matchId(), $operations[1]->matchId()); } public function testReserve_OperationNotReserved_ReturnsOperation() { $nodeA = new Node($this->client); $opId = $this->batch->save($nodeA); $reservation = $this->batch->reserve($opId); $this->assertInstanceOf('Everyman\Neo4j\Batch\Operation', $reservation); $saveMatch = new Batch\Save($this->batch, $nodeA, 123); $this->assertEquals($saveMatch->matchId(), $reservation->matchId()); } public function testReserve_OperationAlreadyReserved_ReturnsFalse() { $nodeA = new Node($this->client); $opId = $this->batch->save($nodeA); $temp = $this->batch->reserve($opId); $reservation = $this->batch->reserve($opId); $this->assertFalse($reservation); } public function testReserve_OperationNotExists_ReturnsFalse() { $reservation = $this->batch->reserve(0); $this->assertFalse($reservation); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Cache/MemcacheTest.php ================================================ markTestSkipped('Memcache extension not enabled/installed'); } $this->memcache = $this->getMock('\Memcache'); $this->cache = new Memcache($this->memcache); } public function testSet_PassesThroughToMemcache() { $this->memcache->expects($this->once()) ->method('set') ->with('somekey', 'somevalue', 0, 12345) ->will($this->returnValue(true)); $this->assertTrue($this->cache->set('somekey', 'somevalue', 12345)); } public function testGet_PassesThroughToMemcache() { $this->memcache->expects($this->once()) ->method('get') ->with('somekey') ->will($this->returnValue('somevalue')); $this->assertEquals('somevalue', $this->cache->get('somekey')); } public function testDelete_PassesThroughToMemcache() { $this->memcache->expects($this->once()) ->method('delete') ->with('somekey') ->will($this->returnValue(true)); $this->assertTrue($this->cache->delete('somekey')); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Cache/MemcachedTest.php ================================================ markTestSkipped('Memcached extension not enabled/installed'); } else if (version_compare($memcachedVersion, '2.2.0', '>=')) { $this->markTestSkipped('Memcached tests can only be run with memcached extension 2.1.0 or lower'); } $this->memcached = $this->getMock('\Memcached'); $this->cache = new Memcached($this->memcached); } public function testSet_PassesThroughToMemcached() { $this->memcached->expects($this->once()) ->method('set') ->with('somekey', 'somevalue', 12345) ->will($this->returnValue(true)); $this->assertTrue($this->cache->set('somekey', 'somevalue', 12345)); } public function testGet_PassesThroughToMemcached() { $this->memcached->expects($this->once()) ->method('get') ->with('somekey') ->will($this->returnValue('somevalue')); $this->assertEquals('somevalue', $this->cache->get('somekey')); } public function testDelete_PassesThroughToMemcached() { $this->memcached->expects($this->once()) ->method('delete') ->with('somekey') ->will($this->returnValue(true)); $this->assertTrue($this->cache->delete('somekey')); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Cache/NoneTest.php ================================================ cache = new None(); } public function testDelete_ReturnsTrue() { $this->assertTrue($this->cache->delete('somekey')); } public function testGet_ReturnsFalse() { $this->assertFalse($this->cache->get('somekey')); } public function testSet_ReturnsTrue() { $this->assertTrue($this->cache->set('somekey', 'somevalue', 12345)); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Cache/VariableTest.php ================================================ cache = new Variable(); } public function testSet_ReturnsTrue() { $this->assertTrue($this->cache->set('somekey', 'somevalue', 12345)); } public function testGet_KeyDoesNotExist_ReturnsFalse() { $this->assertFalse($this->cache->get('somekey')); } public function testGet_KeyExists_ReturnsValue() { $this->cache->set('somekey', 'somevalue', 12345); $this->assertEquals('somevalue', $this->cache->get('somekey')); } public function testGet_ExpiredValue_ReturnsFalse() { $this->cache->set('somekey', 'somevalue', time()-10000); $this->assertFalse($this->cache->get('somekey')); } public function testDelete_KeyDoesNotExist_ReturnsTrue() { $this->assertTrue($this->cache->delete('somekey')); } public function testDelete_KeyExists_ReturnsTrue() { $this->cache->set('somekey', 'somevalue', 12345); $this->assertTrue($this->cache->delete('somekey')); $this->assertFalse($this->cache->get('somekey')); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/ClientTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); } public function testConstruct_TransportGiven_SetsTransport() { $this->assertSame($this->transport, $this->client->getTransport()); } public function testConstruct_NoTransportGiven_SetsCreateTransport() { $client = new Client(); $transport = $client->getTransport(); $this->assertInstanceOf('Everyman\Neo4j\Transport', $transport); $this->assertEquals('http://localhost:7474/db/data', $transport->getEndpoint()); } public function testConstruct_HostAndPortGiven_SetsCreateTransport() { $client = new Client('somehost', 7575); $transport = $client->getTransport(); $this->assertInstanceOf('Everyman\Neo4j\Transport', $transport); $this->assertEquals('http://somehost:7575/db/data', $transport->getEndpoint()); } public function testDeleteNode_NodeDeleted_ReturnsTrue() { $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/node/123') ->will($this->returnValue(array('code'=>204))); $this->assertTrue($this->client->deleteNode($node)); } public function testDeleteNode_NodeNotFound_ThrowsException() { $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/node/123') ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->deleteNode($node); } public function testDeleteNode_TransportError_ThrowsException() { $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/node/123') ->will($this->returnValue(array('code'=>409))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->deleteNode($node); } public function testDeleteNode_NodeHasNoId_ThrowsException() { $node = new Node($this->client); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->deleteNode($node); } public function testSaveNode_Update_NodeHasNoId_ThrowsException() { $node = new Node($this->client); $command = new Command\UpdateNode($this->client, $node); $this->setExpectedException('Everyman\Neo4j\Exception'); $command->execute(); } public function testSaveNode_UpdateNodeFound_ReturnsTrue() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $node = new Node($this->client); $node->useLazyLoad(false) ->setId(123) ->setProperties($properties); $this->transport->expects($this->once()) ->method('put') ->with('/node/123/properties', $properties) ->will($this->returnValue(array('code'=>204))); $this->assertTrue($this->client->saveNode($node)); $this->assertEquals(123, $node->getId()); } public function testSaveNode_UpdateNodeNotFound_ThrowsException() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $node = new Node($this->client); $node->useLazyLoad(false) ->setId(123) ->setProperties($properties); $this->transport->expects($this->once()) ->method('put') ->with('/node/123/properties', $properties) ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveNode($node); } public function testSaveNode_Update_TransportError_ThrowsException() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $node = new Node($this->client); $node->useLazyLoad(false) ->setId(123) ->setProperties($properties); $this->transport->expects($this->once()) ->method('put') ->with('/node/123/properties', $properties) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveNode($node); } public function testSaveNode_Create_ReturnsTrue() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $node = new Node($this->client); $node->setProperties($properties); $this->transport->expects($this->once()) ->method('post') ->with('/node', $properties) ->will($this->returnValue(array( 'code'=>201, 'headers'=>array('Location'=>'http://foo.com:1234/db/data/node/123') ))); $this->assertTrue($this->client->saveNode($node)); $this->assertEquals(123, $node->getId()); } public function testSaveNode_Create_TransportError_ThrowsException() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $node = new Node($this->client); $node->setProperties($properties); $this->transport->expects($this->once()) ->method('post') ->with('/node', $properties) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveNode($node); } public function testSaveNode_CreateNoProperties_ReturnsSuccess() { $node = new Node($this->client); $this->transport->expects($this->once()) ->method('post') ->with('/node',null) ->will($this->returnValue(array('code'=>201, 'headers'=>array('Location'=>'http://foo.com:1234/db/data/node/123')))); $this->assertTrue($this->client->saveNode($node)); $this->assertEquals(123, $node->getId()); } public function testGetNode_TransportError_ThrowsException() { $nodeId = 123; $this->transport->expects($this->once()) ->method('get') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->getNode($nodeId); } public function testGetNode_NotFound_ReturnsNull() { $nodeId = 123; $this->transport->expects($this->once()) ->method('get') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>404))); $this->assertNull($this->client->getNode($nodeId)); } public function testGetNode_Force_ReturnsNode() { $nodeId = 123; $this->transport->expects($this->never()) ->method('get'); $node = $this->client->getNode($nodeId, true); $this->assertInstanceOf('Everyman\Neo4j\Node', $node); $this->assertEquals($nodeId, $node->getId()); } public function testGetNode_Found_ReturnsNode() { $nodeId = 123; $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $this->transport->expects($this->once()) ->method('get') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>200,'data'=>array('data'=>$properties)))); $node = $this->client->getNode($nodeId); $this->assertNotNull($node); $this->assertInstanceOf('Everyman\Neo4j\Node', $node); $this->assertEquals($nodeId, $node->getId()); $this->assertEquals($properties, $node->getProperties()); } public function testLoadNode_NodeNotFound_ThrowsException() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $this->transport->expects($this->once()) ->method('get') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->loadNode($node); } public function testLoadNode_NodeHasNoId_ThrowsException() { $node = new Node($this->client); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->loadNode($node); } public function testGetRelationship_TransportError_ThrowsException() { $relId = 123; $this->transport->expects($this->once()) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->getRelationship($relId); } public function testGetRelationship_NotFound_ReturnsNull() { $relId = 123; $this->transport->expects($this->once()) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>'404'))); $this->assertNull($this->client->getRelationship($relId)); } public function testGetRelationship_Force_ReturnsRelationship() { $relId = 123; $this->transport->expects($this->never()) ->method('get'); $rel = $this->client->getRelationship($relId, true); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rel); $this->assertEquals($relId, $rel->getId()); } public function testGetRelationship_Found_ReturnsRelationship() { $relId = 123; $data = array( 'data' => array( 'foo' => 'bar', 'baz' => 'qux', ), 'start' => 'http://foo:1234/db/data/node/567', 'end' => 'http://foo:1234/db/data/node/890', 'type' => 'FOOTYPE', ); $this->transport->expects($this->once()) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>'200','data'=>$data))); $rel = $this->client->getRelationship($relId); $this->assertNotNull($rel); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rel); $this->assertEquals($relId, $rel->getId()); $this->assertEquals($data['data'], $rel->getProperties()); $this->assertEquals($data['type'], $rel->getType()); $start = $rel->getStartNode(); $this->assertNotNull($start); $this->assertInstanceOf('Everyman\Neo4j\Node', $start); $this->assertEquals(567, $start->getId()); $end = $rel->getEndNode(); $this->assertNotNull($end); $this->assertInstanceOf('Everyman\Neo4j\Node', $end); $this->assertEquals(890, $end->getId()); } /** * Regression test for http://github.com/jadell/neo4jphp/issues/52 */ public function testGetRelationship_Found_LazyLoadNodes() { $relId = 123; $data = array( 'data' => array( 'foo' => 'bar', 'baz' => 'qux', ), 'start' => 'http://foo:1234/db/data/node/567', 'end' => 'http://foo:1234/db/data/node/890', 'type' => 'FOOTYPE', ); $this->transport->expects($this->at(0)) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>'200','data'=>$data))); $this->transport->expects($this->at(1)) ->method('get') ->with('/node/567') ->will($this->returnValue(array('code'=>'200','data'=>array('data' => array())))); $this->transport->expects($this->at(2)) ->method('get') ->with('/node/890') ->will($this->returnValue(array('code'=>'200','data'=>array('data' => array())))); $rel = $this->client->getRelationship($relId); $rel->getStartNode()->getProperties(); $rel->getEndNode()->getProperties(); } public function testLoadRelationship_RelationshipNotFound_ThrowsException() { $relId = 123; $rel = new Relationship($this->client); $rel->setId($relId); $this->transport->expects($this->once()) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->loadRelationship($rel); } public function testLoadRelationship_RelationshipHasNoId_ThrowsException() { $rel = new Relationship($this->client); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->loadRelationship($rel); } public function testDeleteRelationship_Found_ReturnsTrue() { $rel = new Relationship($this->client); $rel->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/relationship/123') ->will($this->returnValue(array('code'=>204))); $this->assertTrue($this->client->deleteRelationship($rel)); } public function testDeleteRelationship_NotFound_ThrowsException() { $rel = new Relationship($this->client); $rel->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/relationship/123') ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->deleteRelationship($rel); } public function testDeleteRelationship_TransportError_ThrowsException() { $rel = new Relationship($this->client); $rel->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/relationship/123') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->deleteRelationship($rel); } public function testDeleteRelationship_RelationshipHasNoId_ThrowsException() { $rel = new Relationship($this->client); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->deleteRelationship($rel); } public function testSaveRelationship_Create_NoStartNode_ThrowsException() { $rel = new Relationship($this->client); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveRelationship($rel); } public function testSaveRelationship_Create_NoEndNode_ThrowsException() { $start = new Node($this->client); $start->setId(123); $rel = new Relationship($this->client); $rel->setStartNode($start); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveRelationship($rel); } public function testSaveRelationship_Create_NoType_ThrowsException() { $start = new Node($this->client); $start->setId(123); $end = new Node($this->client); $end->setId(456); $rel = new Relationship($this->client); $rel->setStartNode($start); $rel->setEndNode($end); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveRelationship($rel); } public function testSaveRelationship_Create_ReturnsTrue() { $data = array( 'data' => array( 'foo' => 'bar', 'baz' => 'qux', ), 'to' => $this->endpoint.'/node/456', 'type' => 'FOOTYPE', ); $start = new Node($this->client); $start->setId(123); $end = new Node($this->client); $end->setId(456); $rel = new Relationship($this->client); $rel->setType('FOOTYPE') ->setStartNode($start) ->setEndNode($end) ->setProperties($data['data']); $this->transport->expects($this->once()) ->method('post') ->with('/node/123/relationships', $data) ->will($this->returnValue(array('code'=>201, 'headers'=>array('Location'=>'http://foo.com:1234/db/data/relationship/890')))); $this->assertTrue($this->client->saveRelationship($rel)); $this->assertEquals(890, $rel->getId()); } public function testSaveRelationship_CreateNoData_ReturnsTrue() { $data = array( 'to' => $this->endpoint.'/node/456', 'type' => 'FOOTYPE', ); $start = new Node($this->client); $start->setId(123); $end = new Node($this->client); $end->setId(456); $rel = new Relationship($this->client); $rel->setType('FOOTYPE') ->setStartNode($start) ->setEndNode($end) ->setProperties(array()); $this->transport->expects($this->once()) ->method('post') ->with('/node/123/relationships', $data) ->will($this->returnValue(array('code'=>201, 'headers'=>array('Location'=>'http://foo.com:1234/db/data/relationship/890')))); $this->assertTrue($this->client->saveRelationship($rel)); $this->assertEquals(890, $rel->getId()); } public function testSaveRelationship_CreateTransportError_ThrowsException() { $data = array( 'data' => array( 'foo' => 'bar', 'baz' => 'qux', ), 'to' => $this->endpoint.'/node/456', 'type' => 'FOOTYPE', ); $start = new Node($this->client); $start->setId(123); $end = new Node($this->client); $end->setId(456); $rel = new Relationship($this->client); $rel->setType('FOOTYPE') ->setStartNode($start) ->setEndNode($end) ->setProperties($data['data']); $this->transport->expects($this->once()) ->method('post') ->with('/node/123/relationships', $data) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveRelationship($rel); } public function testSaveRelationship_Update_RelationshipHasNoId_ThrowsException() { $rel = new Relationship($this->client); $command = new Command\UpdateRelationship($this->client, $rel); $this->setExpectedException('Everyman\Neo4j\Exception'); $command->execute(); } public function testSaveRelationship_UpdateFound_ReturnsTrue() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $rel = new Relationship($this->client); $rel->useLazyLoad(false) ->setId(123) ->setProperties($properties); $this->transport->expects($this->once()) ->method('put') ->with('/relationship/123/properties', $properties) ->will($this->returnValue(array('code'=>204))); $this->assertTrue($this->client->saveRelationship($rel)); } public function testSaveRelationship_UpdateNotFound_ReturnsFalse() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $rel = new Relationship($this->client); $rel->useLazyLoad(false) ->setId(123) ->setProperties($properties); $this->transport->expects($this->once()) ->method('put') ->with('/relationship/123/properties', $properties) ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveRelationship($rel); } public function testSaveRelationship_UpdateTransportError_ThrowsException() { $properties = array( 'foo' => 'bar', 'baz' => 'qux', ); $rel = new Relationship($this->client); $rel->useLazyLoad(false) ->setId(123) ->setProperties($properties); $this->transport->expects($this->once()) ->method('put') ->with('/relationship/123/properties', $properties) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->saveRelationship($rel); } public function testGetNodeRelationships_NodeNotPersisted_ThrowsException() { $node = new Node($this->client); $type = 'FOOTYPE'; $dir = Relationship::DirectionOut; $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->getNodeRelationships($node, $type, $dir); } public function testGetNodeRelationships_NodeNotFound_ThrowsException() { $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->once()) ->method('get') ->with('/node/123/relationships/all') ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->getNodeRelationships($node, array(), null); } public function testGetNodeRelationships_NoRelationships_ReturnsEmptyArray() { $node = new Node($this->client); $node->setId(123); $types = array('FOOTYPE'); $dir = Relationship::DirectionIn; $this->transport->expects($this->once()) ->method('get') ->with('/node/123/relationships/in/FOOTYPE') ->will($this->returnValue(array('code'=>200,'data'=>array()))); $this->assertEquals(array(), $this->client->getNodeRelationships($node, $types, $dir)); } public function testGetNodeRelationships_Relationships_ReturnsArray() { $node = new Node($this->client); $node->setId(123); $types = array('FOOTYPE','BARTYPE'); $dir = Relationship::DirectionOut; $data = array( array( "self" => "http://localhost:7474/db/data/relationship/56", "start" => "http://localhost:7474/db/data/node/123", "end" => "http://localhost:7474/db/data/node/93", "type" => "KNOWS", "data" => array('foo'=>'bar','baz'=>'qux'), ), array( "self" => "http://localhost:7474/db/data/relationship/834", "start" => "http://localhost:7474/db/data/node/32", "end" => "http://localhost:7474/db/data/node/123", "type" => "LOVES", "data" => array('bar'=>'foo','qux'=>'baz'), ), ); $this->transport->expects($this->once()) ->method('get') ->with('/node/123/relationships/out/FOOTYPE&BARTYPE') ->will($this->returnValue(array('code'=>200,'data'=>$data))); $result = $this->client->getNodeRelationships($node, $types, $dir); $this->assertEquals(2, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $result[0]); $this->assertEquals(56, $result[0]->getId()); $this->assertEquals($data[0]['data'], $result[0]->getProperties()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getStartNode()); $this->assertEquals(123, $result[0]->getStartNode()->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getEndNode()); $this->assertEquals(93, $result[0]->getEndNode()->getId()); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $result[1]); $this->assertEquals(834, $result[1]->getId()); $this->assertEquals($data[1]['data'], $result[1]->getProperties()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[1]->getStartNode()); $this->assertEquals(32, $result[1]->getStartNode()->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[1]->getEndNode()); $this->assertEquals(123, $result[1]->getEndNode()->getId()); } public function testGetNodeRelationships_UrlCharactersInTypeName_EncodesCorrectly() { $node = new Node($this->client); $node->setId(123); $types = array('FOO\TYPE','BAR?TYPE','BAZ/TYPE'); $this->transport->expects($this->once()) ->method('get') ->with('/node/123/relationships/all/FOO%5CTYPE&BAR%3FTYPE&BAZ%2FTYPE') ->will($this->returnValue(array('code'=>200,'data'=>array()))); $result = $this->client->getNodeRelationships($node, $types); } public function testGetRelationshipTypes_ServerReturnsErrorCode_ThrowsException() { $this->transport->expects($this->once()) ->method('get') ->with('/relationship/types') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $result = $this->client->getRelationshipTypes(); } public function testGetRelationshipTypes_ServerReturnsArray_ReturnsArray() { $this->transport->expects($this->once()) ->method('get') ->with('/relationship/types') ->will($this->returnValue(array('code'=>200, 'data'=>array("foo","bar")))); $result = $this->client->getRelationshipTypes(); $this->assertEquals(array("foo","bar"), $result); } public function testGetServerInfo_ServerReturnsArray_ReturnsArray() { $returnData = array( "relationship_index" => "http://localhost:7474/db/data/index/relationship", "node" => "http://localhost:7474/db/data/node", "relationship_types" => "http://localhost:7474/db/data/relationship/types", "batch" => "http://localhost:7474/db/data/batch", "extensions_info" => "http://localhost:7474/db/data/ext", "node_index" => "http://localhost:7474/db/data/index/node", "reference_node" => "http://localhost:7474/db/data/node/2", "extensions" => array(), "neo4j_version" => "1.5.M01-793-gc100417-dirty", ); $expectedData = $returnData; $expectedData['version'] = array( "full" => "1.5.M01-793-gc100417-dirty", "major" => "1", "minor" => "5", "release" => "M01", ); $this->transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>$returnData))); $result = $this->client->getServerInfo(); $this->assertEquals($expectedData, $result); } public function testGetServerInfo_GeneralAvailabilityRelease_ReturnsArray() { $returnData = array( "relationship_index" => "http://localhost:7474/db/data/index/relationship", "node" => "http://localhost:7474/db/data/node", "neo4j_version" => "1.5", ); $expectedData = $returnData; $expectedData['version'] = array( "full" => "1.5", "major" => "1", "minor" => "5", "release" => "GA", ); $this->transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>$returnData))); $result = $this->client->getServerInfo(); $this->assertEquals($expectedData, $result); } public function testGetServerInfo_UnsuccessfulResponse_ThrowsException() { $this->transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->getServerInfo(); } public function testStartBatch_MultipleCallsWithoutCommit_ReturnsSameBatch() { $batch = $this->client->startBatch(); $this->assertInstanceOf('Everyman\Neo4j\Batch', $batch); $batchAgain = $this->client->startBatch(); $this->assertSame($batch, $batchAgain); } public function testStartBatch_CommitAndStartAnother_ReturnsNewBatch() { $this->transport->expects($this->once()) ->method('post') ->with('/batch') ->will($this->returnValue(array('code'=>200))); $batch = $this->client->startBatch(); $batch->save(new Node($this->client)); $this->assertInstanceOf('Everyman\Neo4j\Batch', $batch); $this->client->commitBatch(); $batchAgain = $this->client->startBatch(); $this->assertInstanceOf('Everyman\Neo4j\Batch', $batchAgain); $this->assertNotSame($batch, $batchAgain); } public function testStartBatch_CommitOpenedBatch_ReturnsNewBatch() { $this->transport->expects($this->once()) ->method('post') ->with('/batch') ->will($this->returnValue(array('code'=>200))); $batch = $this->client->startBatch(); $batch->save(new Node($this->client)); $this->assertInstanceOf('Everyman\Neo4j\Batch', $batch); $batch->commit(); $batchAgain = $this->client->startBatch(); $this->assertInstanceOf('Everyman\Neo4j\Batch', $batchAgain); $this->assertNotSame($batch, $batchAgain); } public function testStartBatch_CommitOtherBatch_ReturnsSameBatch() { $this->transport->expects($this->once()) ->method('post') ->with('/batch') ->will($this->returnValue(array('code'=>200))); $openBatch = $this->client->startBatch(); $batch = new Batch($this->client); $batch->save(new Node($this->client)); $batch->commit(); $batchAgain = $this->client->startBatch(); $this->assertSame($openBatch, $batchAgain); } public function testStartBatch_EndBatch_ReturnsNewBatch() { $batch = $this->client->startBatch(); $this->client->endBatch(); $batchAgain = $this->client->startBatch(); $this->assertNotSame($batch, $batchAgain); } public function testCommitBatch_NoBatchGivenNoOpenBatch_ThrowsException() { $this->setExpectedException('Everyman\Neo4j\Exception'); $this->client->commitBatch(); } public function testCommitBatch_NoOperationsInBatch_ReturnsTrue() { $this->transport->expects($this->never()) ->method('post'); $batch = new Batch($this->client); $this->assertTrue($this->client->commitBatch($batch)); } public function testMakeNode_ReturnsNode() { $data = array( 'foo' => 'bar', 'baz' => 'qux', ); $node = $this->client->makeNode($data); $this->assertInstanceOf('Everyman\Neo4j\Node', $node); $this->assertSame($this->client, $node->getClient()); $this->assertEquals($data, $node->getProperties()); } public function testMakeRelationship_ReturnsRelationship() { $data = array( 'foo' => 'bar', 'baz' => 'qux', ); $rel = $this->client->makeRelationship($data); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rel); $this->assertSame($this->client, $rel->getClient()); $this->assertEquals($data, $rel->getProperties()); } public function testGetReferenceNode_Found_ReturnsNode() { $this->transport->expects($this->once()) ->method('get') ->with('/node/0') ->will($this->returnValue(array('code'=>200,'data'=>array('data'=>array())))); $node = $this->client->getReferenceNode(); $this->assertNotNull($node); $this->assertInstanceOf('Everyman\Neo4j\Node', $node); $this->assertEquals(0, $node->getId()); } public function testNodeFactory_SetNodeFactory_ReturnsNodeFromFactory() { $this->client->setNodeFactory(function (Client $client, $properties=array()) { return new NodeFactoryTestClass_ClientTest($client); }); $node = $this->client->makeNode(); $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()) { return new \stdClass(); }); $this->setExpectedException('Everyman\Neo4j\Exception'); $node = $this->client->makeNode(); } public function testRelationshipFactory_SetRelationshipFactory_ReturnsRelationshipFromFactory() { $this->client->setRelationshipFactory(function (Client $client, $properties=array()) { return new RelFactoryTestClass_ClientTest($client); }); $rel = $this->client->makeRelationship(); $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()) { return new \stdClass(); }); $this->setExpectedException('Everyman\Neo4j\Exception'); $rel = $this->client->makeRelationship(); } } class NodeFactoryTestClass_ClientTest extends Node {} class RelFactoryTestClass_ClientTest extends Relationship {} ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_Batch_IndexTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); $this->batch = new Batch($this->client); } public function testCommitBatch_AddToIndex_NodeExists_Success_ReturnsTrue() { $node = new Node($this->client); $node->setId(123); $index = new Index($this->client, Index::TypeNode, 'indexname'); $request = array(array('id' => 0, 'method' => 'POST', 'to' => '/index/node/indexname', 'body' => array( 'key' => 'somekey', 'value' => 'somevalue', 'uri' => $this->endpoint.'/node/123', ) )); $return = array('code' => 200, 'data' => array(array('id' => 0))); $this->batch->addToIndex($index, $node, 'somekey', 'somevalue'); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); } public function testCommitBatch_AddToIndex_NodeDoesNotExist_Success_ReturnsTrue() { $node = new Node($this->client); $index = new Index($this->client, Index::TypeNode, 'indexname'); $request = array( array('id' => 1, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 0, 'method' => 'POST', 'to' => '/index/node/indexname', 'body' => array( 'key' => 'somekey', 'value' => 'somevalue', 'uri' => '{1}', ) )); $return = array('code' => 200, 'data' => array( array('id' => 1, 'location' => 'http://foo:1234/db/data/node/123'), array('id' => 0) )); $this->batch->addToIndex($index, $node, 'somekey', 'somevalue'); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(123, $node->getId()); } public function testCommitBatch_AddToIndex_RelationshipExists_Success_ReturnsTrue() { $rel = new Relationship($this->client); $rel->setId(123); $index = new Index($this->client, Index::TypeRelationship, 'indexname'); $request = array(array('id' => 0, 'method' => 'POST', 'to' => '/index/relationship/indexname', 'body' => array( 'key' => 'somekey', 'value' => 'somevalue', 'uri' => $this->endpoint.'/relationship/123', ) )); $return = array('code' => 200, 'data' => array(array('id' => 0))); $this->batch->addToIndex($index, $rel, 'somekey', 'somevalue'); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); } public function testCommitBatch_AddToIndex_NoEntitiesExist_Success_ReturnsTrue() { $nodeA = new Node($this->client); $nodeB = new Node($this->client); $rel = new Relationship($this->client); $rel->setType('TEST') ->setStartNode($nodeA) ->setEndNode($nodeB); $index = new Index($this->client, Index::TypeRelationship, 'indexname'); $request = array( array('id' => 2, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 3, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 1, 'method' => 'POST', 'to' => '{2}/relationships', 'body' => array('to' => '{3}', 'type' => 'TEST') ), array('id' => 0, 'method' => 'POST', 'to' => '/index/relationship/indexname', 'body' => array( 'key' => 'somekey', 'value' => 'somevalue', 'uri' => '{1}', ) ) ); $return = array('code' => 200, 'data' => array( array('id' => 2, 'location' => 'http://foo:1234/db/data/node/123'), array('id' => 3, 'location' => 'http://foo:1234/db/data/node/456'), array('id' => 1, 'location' => 'http://foo:1234/db/data/relationship/789'), array('id' => 0) )); $this->batch->addToIndex($index, $rel, 'somekey', 'somevalue'); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(123, $nodeA->getId()); $this->assertEquals(456, $nodeB->getId()); $this->assertEquals(789, $rel->getId()); } public function testCommitBatch_RemoveFromIndex_Entity_Success_ReturnsTrue() { $node = new Node($this->client); $node->setId(123); $index = new Index($this->client, Index::TypeNode, 'indexname'); $request = array(array('id' => 0, 'method' => 'DELETE', 'to' => '/index/node/indexname/123')); $return = array('code' => 200, 'data' => array(array('id' => 0))); $this->batch->removeFromIndex($index, $node); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); } public function testCommitBatch_RemoveFromIndex_EntityKey_Success_ReturnsTrue() { $node = new Node($this->client); $node->setId(123); $index = new Index($this->client, Index::TypeNode, 'indexname'); $request = array(array('id' => 0, 'method' => 'DELETE', 'to' => '/index/node/indexname/somekey/123')); $return = array('code' => 200, 'data' => array(array('id' => 0))); $this->batch->removeFromIndex($index, $node, 'somekey'); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); } public function testCommitBatch_RemoveFromIndex_EntityKeyValue_Success_ReturnsTrue() { $node = new Node($this->client); $node->setId(123); $index = new Index($this->client, Index::TypeNode, 'indexname'); $request = array(array('id' => 0, 'method' => 'DELETE', 'to' => '/index/node/indexname/somekey/somevalue/123')); $return = array('code' => 200, 'data' => array(array('id' => 0))); $this->batch->removeFromIndex($index, $node, 'somekey', 'somevalue'); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); } protected function setupTransportExpectation($request, $will) { $this->transport->expects($this->once()) ->method('post') ->with('/batch', $request) ->will($will); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_Batch_NodeTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->client = new Client($this->transport); $this->batch = new Batch($this->client); $this->client->getEntityCache()->setCache(new Cache\Variable()); } public function testCommitBatch_TransportError_ThrowsException() { $node = new Node($this->client); $request = array(array('id' => 0, 'method' => 'POST', 'to' => '/node', 'body' => null)); $this->batch->save($node); $this->setupTransportExpectation($request, $this->returnValue(array('code' => 400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->commitBatch($this->batch); } public function testCommitBatch_CreateNode_Success_ReturnsTrue() { $node = new Node($this->client); $node->setProperties(array('foo' => 'bar','baz' => 'qux')); $request = array(array('id' => 0, 'method' => 'POST', 'to' => '/node', 'body' => array('foo' => 'bar','baz' => 'qux'))); $return = array('code' => 200, 'data' => array( array('id' => 0, 'location' => 'http://foo:1234/db/data/node/123'))); $this->batch->save($node); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(123, $node->getId()); $this->assertSame($node, $this->client->getEntityCache()->getCachedEntity(123, 'node')); } public function testCommitBatch_UpdateNode_Success_ReturnsTrue() { $node = new Node($this->client); $node->useLazyLoad(false) ->setId(123) ->setProperties(array('foo' => 'bar','baz' => 'qux')); $request = array(array('id' => 0, 'method' => 'PUT', 'to' => '/node/123/properties', 'body' => array('foo' => 'bar','baz' => 'qux'))); $return = array('code' => 200, 'data' => array( array('id' => 0))); $this->batch->save($node); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertSame($node, $this->client->getEntityCache()->getCachedEntity(123, 'node')); } public function testCommitBatch_DeleteNode_Success_ReturnsTrue() { $node = new Node($this->client); $node->setId(123); $this->client->getEntityCache()->setCachedEntity($node); $request = array(array('id' => 0, 'method' => 'DELETE', 'to' => '/node/123')); $return = array('code' => 200, 'data' => array( array('id' => 0))); $this->batch->delete($node); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertFalse($this->client->getEntityCache()->getCachedEntity(123, 'node')); } protected function setupTransportExpectation($request, $will) { $this->transport->expects($this->once()) ->method('post') ->with('/batch', $request) ->will($will); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_Batch_RelationshipTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); $this->batch = new Batch($this->client); $this->client->getEntityCache()->setCache(new Cache\Variable()); } public function testCommitBatch_CreateRelationship_Success_ReturnsTrue() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $endNode->setId(456); $rel = new Relationship($this->client); $rel->setType('TEST') ->setStartNode($startNode) ->setEndNode($endNode) ->setProperties(array('foo' => 'bar','baz' => 'qux')); $request = array(array('id' => 0, 'method' => 'POST', 'to' => '/node/123/relationships', 'body' => array('to' => $this->endpoint.'/node/456', 'type' => 'TEST', 'data' => array('foo' => 'bar','baz' => 'qux')))); $return = array('code' => 200, 'data' => array( array('id' => 0, 'location' => 'http://foo:1234/db/data/relationship/789'))); $this->batch->save($rel); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(789, $rel->getId()); $this->assertSame($rel, $this->client->getEntityCache()->getCachedEntity(789, 'relationship')); } public function testCommitBatch_CreateRelationship_StartNodeUnidentified_ReturnsTrue() { $startNode = new Node($this->client); $endNode = new Node($this->client); $endNode->setId(456); $rel = new Relationship($this->client); $rel->setType('TEST') ->setStartNode($startNode) ->setEndNode($endNode); $request = array( array('id' => 1, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 0, 'method' => 'POST', 'to' => '{1}/relationships', 'body' => array('to' => $this->endpoint.'/node/456', 'type' => 'TEST')), ); $return = array('code' => 200, 'data' => array( array('id' => 1, 'location' => 'http://foo:1234/db/data/node/123'), array('id' => 0, 'location' => 'http://foo:1234/db/data/relationship/789'), )); $this->batch->save($rel); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(789, $rel->getId()); $this->assertEquals(123, $startNode->getId()); $this->assertSame($rel, $this->client->getEntityCache()->getCachedEntity(789, 'relationship')); $this->assertSame($startNode, $this->client->getEntityCache()->getCachedEntity(123, 'node')); } public function testCommitBatch_CreateRelationship_EndNodeUnidentified_ReturnsTrue() { $startNode = new Node($this->client); $startNode->setId(456); $endNode = new Node($this->client); $rel = new Relationship($this->client); $rel->setType('TEST') ->setStartNode($startNode) ->setEndNode($endNode) ->setProperties(array('foo' => 'bar','baz' => 'qux')); $request = array( array('id' => 1, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 0, 'method' => 'POST', 'to' => '/node/456/relationships', 'body' => array('to' => '{1}', 'type' => 'TEST', 'data' => array('foo' => 'bar','baz' => 'qux'))), ); $return = array('code' => 200, 'data' => array( array('id' => 1, 'location' => 'http://foo:1234/db/data/node/123'), array('id' => 0, 'location' => 'http://foo:1234/db/data/relationship/789'), )); $this->batch->save($rel); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(789, $rel->getId()); $this->assertEquals(123, $endNode->getId()); $this->assertSame($rel, $this->client->getEntityCache()->getCachedEntity(789, 'relationship')); $this->assertSame($endNode, $this->client->getEntityCache()->getCachedEntity(123, 'node')); } public function testCommitBatch_CreateRelationship_NeitherNodeUnidentified_ReturnsTrue() { $startNode = new Node($this->client); $endNode = new Node($this->client); $rel = new Relationship($this->client); $rel->setType('TEST') ->setStartNode($startNode) ->setEndNode($endNode) ->setProperties(array('foo' => 'bar','baz' => 'qux')); $request = array( array('id' => 1, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 2, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 0, 'method' => 'POST', 'to' => '{1}/relationships', 'body' => array('to' => '{2}', 'type' => 'TEST', 'data' => array('foo' => 'bar','baz' => 'qux'))), ); $return = array('code' => 200, 'data' => array( array('id' => 1, 'location' => 'http://foo:1234/db/data/node/123'), array('id' => 2, 'location' => 'http://foo:1234/db/data/node/456'), array('id' => 0, 'location' => 'http://foo:1234/db/data/relationship/789'), )); $this->batch->save($rel); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(789, $rel->getId()); $this->assertEquals(123, $startNode->getId()); $this->assertEquals(456, $endNode->getId()); $this->assertSame($rel, $this->client->getEntityCache()->getCachedEntity(789, 'relationship')); $this->assertSame($startNode, $this->client->getEntityCache()->getCachedEntity(123, 'node')); $this->assertSame($endNode, $this->client->getEntityCache()->getCachedEntity(456, 'node')); } public function testCommitBatch_CreateRelationship_UnidentifiedNodeAlreadySavedInBatch_ReturnsTrue() { $startNode = new Node($this->client); $endNode = new Node($this->client); $rel = new Relationship($this->client); $rel->setType('TEST') ->setStartNode($startNode) ->setEndNode($endNode) ->setProperties(array('foo' => 'bar','baz' => 'qux')); $request = array( array('id' => 0, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 2, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 1, 'method' => 'POST', 'to' => '{0}/relationships', 'body' => array('to' => '{2}', 'type' => 'TEST', 'data' => array('foo' => 'bar','baz' => 'qux'))), ); $return = array('code' => 200, 'data' => array( array('id' => 0, 'location' => 'http://foo:1234/db/data/node/123'), array('id' => 2, 'location' => 'http://foo:1234/db/data/node/456'), array('id' => 1, 'location' => 'http://foo:1234/db/data/relationship/789'), )); $this->batch->save($startNode); $this->batch->save($rel); $this->batch->save($endNode); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertEquals(789, $rel->getId()); $this->assertEquals(123, $startNode->getId()); $this->assertEquals(456, $endNode->getId()); } public function testCommitBatch_UpdateRelationship_Success_ReturnsTrue() { $rel = new Relationship($this->client); $rel->useLazyLoad(false) ->setId(123) ->setProperties(array('foo' => 'bar','baz' => 'qux')); $request = array(array('id' => 0, 'method' => 'PUT', 'to' => '/relationship/123/properties', 'body' => array('foo' => 'bar','baz' => 'qux'))); $return = array('code' => 200, 'data' => array( array('id' => 0))); $this->batch->save($rel); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertSame($rel, $this->client->getEntityCache()->getCachedEntity(123, 'relationship')); } public function testCommitBatch_DeleteRelationship_Success_ReturnsTrue() { $rel = new Relationship($this->client); $rel->setId(123); $this->client->getEntityCache()->setCachedEntity($rel); $request = array(array('id' => 0, 'method' => 'DELETE', 'to' => '/relationship/123')); $return = array('code' => 200, 'data' => array( array('id' => 0))); $this->batch->delete($rel); $this->setupTransportExpectation($request, $this->returnValue($return)); $result = $this->client->commitBatch($this->batch); $this->assertTrue($result); $this->assertFalse($this->client->getEntityCache()->getCachedEntity(123, 'relationship')); } public function testImplicitBatch_StartBatch_CloseBatch_ExpectedBatchRequest() { $startNode = new Node($this->client); $endNode = new Node($this->client); $endNode->setId(456)->useLazyLoad(false); $rel = new Relationship($this->client); $rel->setType('TEST') ->setStartNode($startNode) ->setEndNode($endNode); $deleteNode = new Node($this->client); $deleteNode->setId(987); $deleteRel = new Relationship($this->client); $deleteRel->setId(321); $addIndexNode = new Node($this->client); $addIndexNode->setId(654); $removeIndexNode = new Node($this->client); $removeIndexNode->setId(209); $index = new Index($this->client, Index::TypeNode, 'indexname'); $request = array( array('id' => 0, 'method' => 'POST', 'to' => '/node', 'body' => null), array('id' => 1, 'method' => 'PUT', 'to' => '/node/456/properties', 'body' => array()), array('id' => 2, 'method' => 'POST', 'to' => '{0}/relationships', 'body' => array( 'to' => $this->endpoint.'/node/456', 'type' => 'TEST' ) ), array('id' => 3, 'method' => 'DELETE', 'to' => '/node/987'), array('id' => 4, 'method' => 'DELETE', 'to' => '/relationship/321'), array('id' => 5, 'method' => 'POST', 'to' => '/index/node/indexname', 'body' => array( 'key' => 'addkey', 'value' => 'addvalue', 'uri' => $this->endpoint.'/node/654', ) ), array('id' => 6, 'method' => 'DELETE', 'to' => '/index/node/indexname/removekey/removevalue/209'), ); $return = array('code' => 200, 'data' => array( array('id' => 0, 'location' => 'http://foo:1234/db/data/node/123'), array('id' => 1), array('id' => 2, 'location' => 'http://foo:1234/db/data/relationship/789'), array('id' => 3), array('id' => 4), array('id' => 5), array('id' => 6), )); $this->setupTransportExpectation($request, $this->returnValue($return)); $batch = $this->client->startBatch(); $this->assertInstanceOf('Everyman\Neo4j\Batch', $batch); $startNode->save(); $endNode->save(); $rel->save(); $deleteNode->delete(); $deleteRel->delete(); $index->add($addIndexNode, 'addkey', 'addvalue'); $index->remove($removeIndexNode, 'removekey', 'removevalue'); $this->assertTrue($this->client->commitBatch()); $this->assertEquals(789, $rel->getId()); $this->assertEquals(123, $startNode->getId()); } protected function setupTransportExpectation($request, $will) { $this->transport->expects($this->once()) ->method('post') ->with('/batch', $request) ->will($will); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_CacheTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->cache = new Cache\Variable(); $this->client = new Client($this->transport); $this->client->getEntityCache()->setCache($this->cache); } public function testLoadNode_Found_NodeInCache() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $data = array('data' => array( 'name' => 'FOO', )); $this->transport->expects($this->once()) ->method('get') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>'200','data'=>$data))); $this->client->loadNode($node); $this->assertSame($node, $this->cache->get("node-{$nodeId}")); $subseq = new Node($this->client); $subseq->setId($nodeId); $this->client->loadNode($subseq); $this->assertEquals($node->getProperties(), $subseq->getProperties()); } public function testLoadNode_NotFound_NodeNotInCache() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $this->transport->expects($this->once()) ->method('get') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>'404'))); try { $this->client->loadNode($node); $this->fail(); } catch (Exception $e) { $this->assertFalse($this->cache->get("node-{$nodeId}")); } } public function testLoadRelationship_Found_RelationshipInCache() { $relId = 123; $rel = new Relationship($this->client); $rel->setId($relId); $data = array( 'data' => array( 'name' => 'FOO', ), 'start' => 'http://foo:1234/db/data/node/567', 'end' => 'http://foo:1234/db/data/node/890', 'type' => 'FOOTYPE', ); $this->transport->expects($this->once()) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>'200','data'=>$data))); $this->client->loadRelationship($rel); $this->assertSame($rel, $this->cache->get("relationship-{$relId}")); $subseq = new Relationship($this->client); $subseq->setId($relId); $this->client->loadRelationship($subseq); $this->assertEquals($rel->getProperties(), $subseq->getProperties()); } public function testLoadRelationship_NotFound_RelationshipNotInCache() { $relId = 123; $rel = new Relationship($this->client); $rel->setId($relId); $this->transport->expects($this->once()) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>'404','data'=>array()))); try { $this->client->loadRelationship($rel); $this->fail(); } catch (Exception $e) { $this->assertFalse($this->cache->get("relationship-{$relId}")); } } public function testGetNode_Found_SubsequentCallsReturnsFromCache() { $nodeId = 123; $this->transport->expects($this->once()) ->method('get') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>'200','data'=>array('data'=>array())))); $node = $this->client->getNode($nodeId); $subseq = $this->client->getNode($nodeId); $this->assertSame($node, $subseq); } public function testGetRelationship_Found_SubsequentCallsReturnsFromCache() { $relId = 123; $data = array( 'data' => array(), 'start' => 'http://foo:1234/db/data/node/567', 'end' => 'http://foo:1234/db/data/node/890', 'type' => 'FOOTYPE', ); $this->transport->expects($this->once()) ->method('get') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>'200','data'=>$data))); $rel = $this->client->getRelationship($relId); $subseq = $this->client->getRelationship($relId); $this->assertSame($rel, $subseq); } public function testDeleteNode_Success_NodeNotInCache() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $this->transport->expects($this->once()) ->method('delete') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>'200'))); $this->cache->set("node-{$nodeId}", $node); $this->client->deleteNode($node); $this->assertFalse($this->cache->get("node-{$nodeId}")); } public function testDeleteNode_Failure_NodeRemainsInCache() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $this->transport->expects($this->once()) ->method('delete') ->with('/node/'.$nodeId) ->will($this->returnValue(array('code'=>'400'))); $this->cache->set("node-{$nodeId}", $node); try { $this->client->deleteNode($node); $this->fail(); } catch (Exception $e) { $this->assertSame($node, $this->cache->get("node-{$nodeId}")); } } public function testDeleteRelationship_Success_RelationshipNotInCache() { $relId = 123; $rel = new Relationship($this->client); $rel->setId($relId); $this->transport->expects($this->once()) ->method('delete') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>'200'))); $this->cache->set("relationship-{$relId}", $rel); $this->client->deleteRelationship($rel); $this->assertFalse($this->cache->get("relationship-{$relId}")); } public function testDeleteRelationship_Failure_RelationshipRemainsInCache() { $relId = 123; $rel = new Relationship($this->client); $rel->setId($relId); $this->transport->expects($this->once()) ->method('delete') ->with('/relationship/'.$relId) ->will($this->returnValue(array('code'=>400))); $this->cache->set("relationship-{$relId}", $rel); try { $this->client->deleteRelationship($rel); $this->fail(); } catch (Exception $e) { $this->assertSame($rel, $this->cache->get("relationship-{$relId}")); } } public function testSaveNode_Success_NodeInCache() { $nodeId = 123; $node = new Node($this->client); $node->useLazyLoad(false) ->setId($nodeId); $this->transport->expects($this->once()) ->method('put') ->with('/node/123/properties', array()) ->will($this->returnValue(array('code'=>204))); $this->client->saveNode($node); $this->assertSame($node, $this->cache->get("node-{$nodeId}")); } public function testSaveNode_Failure_NodeNotInCache() { $nodeId = 123; $node = new Node($this->client); $node->useLazyLoad(false) ->setId($nodeId); $this->transport->expects($this->once()) ->method('put') ->with('/node/123/properties', array()) ->will($this->returnValue(array('code'=>400))); try { $this->client->saveNode($node); $this->fail(); } catch (Exception $e) { $this->assertFalse($this->cache->get("node-{$nodeId}")); } } public function testSaveRelationship_Success_RelationshipInCache() { $relId = 123; $rel = new Relationship($this->client); $rel->useLazyLoad(false) ->setId($relId); $this->transport->expects($this->once()) ->method('put') ->with('/relationship/123/properties', array()) ->will($this->returnValue(array('code'=>204))); $this->client->saveRelationship($rel); $this->assertSame($rel, $this->cache->get("relationship-{$relId}")); } public function testSaveRelationship_Failure_RelationshipNotInCache() { $relId = 123; $rel = new Relationship($this->client); $rel->useLazyLoad(false) ->setId($relId); $this->transport->expects($this->once()) ->method('put') ->with('/relationship/123/properties', array()) ->will($this->returnValue(array('code'=>400))); try { $this->client->saveRelationship($rel); $this->fail(); } catch (Exception $e) { $this->assertFalse($this->cache->get("relationship-{$relId}")); } } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_CypherTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); } /** * @dataProvider dataProvider_TestCypherQuery */ public function testCypherQuery($returnValue, $resultCount) { $props = array( 'query' => 'START a=({start}) MATCH (a)->(b) WHERE b.name = {name} RETURN b', 'params' => array('start' => 1, 'name' => 'friend name'), ); $this->transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'neo4j_version' => '1.5.foo', 'extensions' => array('CypherPlugin' => array( 'execute_query' => $this->endpoint.'/ext/CypherPlugin/graphdb/execute_query' )), )))); $this->transport->expects($this->once()) ->method('post') ->with('/ext/CypherPlugin/graphdb/execute_query', $props) ->will($this->returnValue($returnValue)); $query = new Cypher\Query($this->client, $props['query'], $props['params']); $result = $this->client->executeCypherQuery($query); $this->assertInstanceOf('\Everyman\Neo4j\Query\ResultSet', $result); $this->assertEquals(count($result), $resultCount); } /** * @dataProvider dataProvider_TestCypherQuery */ public function testCypherQuery_NewEndpoint($returnValue, $resultCount) { $props = array( 'query' => 'START a=({start}) MATCH (a)->(b) WHERE b.name = {name} RETURN b', 'params' => array('start' => 1, 'name' => 'friend name'), ); $this->transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'neo4j_version' => '1.5.foo', 'cypher' => $this->endpoint.'/cypher', )))); $this->transport->expects($this->once()) ->method('post') ->with('/cypher', $props) ->will($this->returnValue($returnValue)); $query = new Cypher\Query($this->client, $props['query'], $props['params']); $result = $this->client->executeCypherQuery($query); $this->assertInstanceOf('\Everyman\Neo4j\Query\ResultSet', $result); $this->assertEquals(count($result), $resultCount); } /** * Test for http://github.com/jadell/neo4jphp/issues/63 * @dataProvider dataProvider_TestCypherQuery */ public function testCypherQuery_ProxyHost($returnValue, $resultCount) { $proxyEndpoint = 'http://proxy.me:1234/db/data'; $transport = $this->getMock('Everyman\Neo4j\Transport'); $transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($proxyEndpoint)); $client = new Client($transport); $props = array( 'query' => 'START a=({start}) MATCH (a)->(b) WHERE b.name = {name} RETURN b', 'params' => array('start' => 1, 'name' => 'friend name'), ); $transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'neo4j_version' => '1.5.foo', 'cypher' => $this->endpoint.'/cypher', )))); $transport->expects($this->once()) ->method('post') ->with('/cypher', $props) ->will($this->returnValue($returnValue)); $query = new Cypher\Query($client, $props['query'], $props['params']); $result = $client->executeCypherQuery($query); $this->assertInstanceOf('\Everyman\Neo4j\Query\ResultSet', $result); $this->assertEquals(count($result), $resultCount); } public function dataProvider_TestCypherQuery() { $return = array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14) ) ); return array( array(array('code'=>204,'data'=>null), 0), array(array('code'=>200,'data'=>$return), 3), ); } public function testCypherQuery_ServerReturnsErrorCode_ThrowsException() { $props = array( 'query' => 'START a=(0) RETURN a' ); $this->transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'neo4j_version' => '1.5.foo', 'extensions' => array('CypherPlugin' => array( 'execute_query' => $this->endpoint.'/ext/CypherPlugin/graphdb/execute_query' )), )))); $this->transport->expects($this->once()) ->method('post') ->with('/ext/CypherPlugin/graphdb/execute_query', $props) ->will($this->returnValue(array('code'=>404))); $query = new Cypher\Query($this->client, $props['query']); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->executeCypherQuery($query); } public function testCypherQuery_CypherNotAvailable_ThrowsException() { $this->transport->expects($this->once()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'neo4j_version' => '1.5.foo', )))); $this->transport->expects($this->never()) ->method('post'); $query = new Cypher\Query($this->client, 'query'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->executeCypherQuery($query); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_GremlinTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->client = $this->getMock('Everyman\Neo4j\Client', array('getServerInfo'), array($this->transport)); $this->client->expects($this->any()) ->method('getServerInfo') ->will($this->returnValue(array( 'extensions' => array( 'GremlinPlugin' => array( 'execute_script' => $this->endpoint.'/ext/GremlinPlugin/graphdb/execute_script', ) ) ))); } public function testGremlinQuery_ServerReturnsErrorCode_ReturnsFalse() { $props = array( 'script' => 'i=g.foo(start);', 'params' => array('start' => 123), ); $query = new Gremlin\Query($this->client, $props['script'], $props['params']); $this->transport->expects($this->once()) ->method('post') ->with('/ext/GremlinPlugin/graphdb/execute_script', $props) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->executeGremlinQuery($query); } public function testGremlinQuery_DataAndColumnsReturned_ReturnsResultSet() { $props = array( 'script' => 'i=g.foo(start);', 'params' => array('start' => 123), ); $query = new Gremlin\Query($this->client, $props['script'], $props['params']); $this->transport->expects($this->once()) ->method('post') ->with('/ext/GremlinPlugin/graphdb/execute_script', $props) ->will($this->returnValue(array('code'=>200,'data'=>array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14) ) )))); $result = $this->client->executeGremlinQuery($query); $this->assertInstanceOf('Everyman\Neo4j\Query\ResultSet', $result); $this->assertEquals('Brenda', $result[2]['name']); } public function testGremlinQuery_ListOfEntitiesReturned_ReturnsResultSet() { $props = array('script' => 'i=g.foo();'); $query = new Gremlin\Query($this->client, $props['script']); $this->transport->expects($this->once()) ->method('post') ->with('/ext/GremlinPlugin/graphdb/execute_script', $props) ->will($this->returnValue(array('code'=>200,'data'=>array( array('self' => 'http://foo:1234/db/data/node/1','data'=>array()), array('self' => 'http://foo:1234/db/data/node/2','data'=>array()), array('self' => 'http://foo:1234/db/data/node/3','data'=>array()), )))); $result = $this->client->executeGremlinQuery($query); $this->assertInstanceOf('Everyman\Neo4j\Query\ResultSet', $result); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[1][0]); $this->assertEquals(2, $result[1][0]->getId()); } public function testGremlinQuery_SingleEntityReturned_ReturnsResultSet() { $props = array('script' => 'i=g.foo();'); $query = new Gremlin\Query($this->client, $props['script']); $this->transport->expects($this->once()) ->method('post') ->with('/ext/GremlinPlugin/graphdb/execute_script', $props) ->will($this->returnValue(array('code'=>200,'data'=>array( 'self' => 'http://foo:1234/db/data/node/2', 'data' => array() )))); $result = $this->client->executeGremlinQuery($query); $this->assertInstanceOf('Everyman\Neo4j\Query\ResultSet', $result); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0][0]); $this->assertEquals(2, $result[0][0]->getId()); } public function testGremlinQuery_ScalarValueReturned_ReturnsResultSet() { $props = array('script' => 'i=g.foo();'); $query = new Gremlin\Query($this->client, $props['script']); $this->transport->expects($this->once()) ->method('post') ->with('/ext/GremlinPlugin/graphdb/execute_script', $props) ->will($this->returnValue(array('code'=>200,'data'=>"this is some scalar value"))); $result = $this->client->executeGremlinQuery($query); $this->assertInstanceOf('Everyman\Neo4j\Query\ResultSet', $result); $this->assertEquals("this is some scalar value", $result[0][0]); } public function testGremlinQuery_GremlinNotAvailable_ThrowsException() { $this->client = $this->getMock('Everyman\Neo4j\Client', array('getServerInfo'), array($this->transport)); $this->client->expects($this->any()) ->method('getServerInfo') ->will($this->returnValue(array('extensions' => array()))); $this->transport->expects($this->never()) ->method('post'); $props = array('script' => 'i=g.foo();'); $query = new Gremlin\Query($this->client, $props['script']); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->executeGremlinQuery($query); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_IndexTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); } public function testSaveIndex_UnknownIndexType_ThrowsException() { $index = new Index($this->client, 'FOO', 'indexname'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->saveIndex($index); } public function testSaveIndex_NoName_ThrowsException() { $index = new Index($this->client, Index::TypeNode, null); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->saveIndex($index); } /** * @dataProvider dataProvider_SaveIndexScenarios */ public function testSaveIndex_ReturnsSuccess($type, $name, $config, $result) { $index = new Index($this->client, $type, $name, $config); $data = array('name' => $name); if ($config) { $data['config'] = $config; } $this->transport->expects($this->once()) ->method('post') ->with('/index/'.$type, $data) ->will($this->returnValue($result)); $this->assertTrue($this->client->saveIndex($index)); } public function dataProvider_SaveIndexScenarios() { return array(// type, name, config, result array(Index::TypeNode, 'somekey', array(), array('code'=>201)), array(Index::TypeRelationship, 'somekey', array(), array('code'=>201)), array(Index::TypeNode, 'somekey', array('type' => 'fulltext'), array('code'=>201)), ); } public function testSaveIndex_ServerError_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'somekey'); $this->transport->expects($this->once()) ->method('post') ->with('/index/node', array( 'name' => 'somekey', )) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->saveIndex($index); } public function testDeleteIndex_UnknownIndexType_ThrowsException() { $index = new Index($this->client, 'FOO', 'indexname'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->deleteIndex($index); } public function testDeleteIndex_NoName_ThrowsException() { $index = new Index($this->client, Index::TypeNode, null); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->deleteIndex($index); } /** * @dataProvider dataProvider_SaveIndexScenarios */ public function testDeleteIndex_ReturnsSuccess($type, $name, $config, $result) { $index = new Index($this->client, $type, $name); $this->transport->expects($this->once()) ->method('delete') ->with('/index/'.$type.'/'.$name) ->will($this->returnValue($result)); $this->assertTrue($this->client->deleteIndex($index)); } public function testDeleteIndex_ServerError_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'somekey'); $this->transport->expects($this->once()) ->method('delete') ->with('/index/node/somekey') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->deleteIndex($index); } public function testDeleteIndex_UrlEntities_ReturnsCorrectSuccess() { $index = new Index($this->client, Index::TypeNode, 'ind@ex na$me'); $this->transport->expects($this->once()) ->method('delete') ->with('/index/node/ind%40ex%20na%24me') ->will($this->returnValue(array('code'=>200))); $this->assertTrue($this->client->deleteIndex($index)); } public function testDeleteIndex_NotFound_ReturnsSuccess() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->transport->expects($this->once()) ->method('delete') ->with('/index/node/indexname') ->will($this->returnValue(array('code'=>404))); $this->assertTrue($this->client->deleteIndex($index)); } public function testAddToIndex_UnknownIndexType_ThrowsException() { $index = new Index($this->client, 'FOO', 'indexname'); $node = new Node($this->client); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function dataProvider_AddToIndexScenarios_NoName_ThrowsException() { $index = new Index($this->client, Index::TypeNode, null); $node = new Node($this->client); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function dataProvider_AddToIndexScenarios_WrongEntityType_ThrowsException() { $index = new Index($this->client, Index::TypeRelationship, 'indexname'); $node = new Node($this->client); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function testAddToIndex_EntityAdded_ReturnsSuccess() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $node->setId(123); $data = array( 'key' => 'somekey', 'value' => 'somevalue', 'uri' => $this->endpoint.'/node/123', ); $this->transport->expects($this->once()) ->method('post') ->with('/index/node/indexname', $data) ->will($this->returnValue(array('code'=>201))); $this->assertTrue($this->client->addToIndex($index, $node, 'somekey', 'somevalue')); } public function testAddToIndex_UrlEntities_ReturnsCorrectSuccess() { $index = new Index($this->client, Index::TypeNode, 'index name'); $node = new Node($this->client); $node->setId(123); $data = array( 'key' => 'some@key', 'value' => 'some$value', 'uri' => $this->endpoint.'/node/123', ); $this->transport->expects($this->once()) ->method('post') ->with('/index/node/index%20name', $data) ->will($this->returnValue(array('code'=>200))); $this->assertTrue($this->client->addToIndex($index, $node, 'some@key', 'some$value')); } public function testAddToIndex_ServerError_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $node->setId(123); $data = array( 'key' => 'somekey', 'value' => 'somevalue', 'uri' => $this->endpoint.'/node/123', ); $this->transport->expects($this->once()) ->method('post') ->with('/index/node/indexname', $data) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function testAddToIndex_BadIndexName_ThrowsException() { $index = new Index($this->client, Index::TypeNode, null); $node = new Node($this->client); $node->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function testAddToIndex_EntityNotPersisted_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function testAddToIndex_BadType_ThrowsException() { $index = new Index($this->client, 'FOOTYPE', 'indexname'); $node = new Node($this->client); $node->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function testAddToIndex_BadKey_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $node->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, null, 'somevalue'); } public function testAddToIndex_RelationshipTypeMismatch_ThrowsException() { $index = new Index($this->client, Index::TypeRelationship, 'indexname'); $node = new Node($this->client); $node->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $node, 'somekey', 'somevalue'); } public function testAddToIndex_NodeTypeMismatch_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $rel = new Relationship($this->client); $rel->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addToIndex($index, $rel, 'somekey', 'somevalue'); } /** * @dataProvider dataProvider_RemoveFromIndexScenarios */ public function testRemoveFromIndex_ReturnsSuccess($key, $value, $path, $result) { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/index/node/indexname'.$path.'/123') ->will($this->returnValue($result)); $this->assertTrue($this->client->removeFromIndex($index, $node, $key, $value)); } public function dataProvider_RemoveFromIndexScenarios() { return array(// key, value, path, result array('somekey', 'somevalue', '/somekey/somevalue', array('code'=>201)), array('somekey', null, '/somekey', array('code'=>201)), array(null, null, '', array('code'=>201)), array('some key@', 'som$e value', '/some%20key%40/som%24e%20value', array('code'=>201)), ); } public function testRemoveFromIndex_NotFound_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/index/node/indexname/somekey/somevalue/123') ->will($this->returnValue(array('code'=>404))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->removeFromIndex($index, $node, 'somekey', 'somevalue'); } public function testRemoveFromIndex_ServerError_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->once()) ->method('delete') ->with('/index/node/indexname/somekey/somevalue/123') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->removeFromIndex($index, $node, 'somekey', 'somevalue'); } public function testRemoveFromIndex_BadIndexName_ThrowsException() { $index = new Index($this->client, Index::TypeNode, null); $node = new Node($this->client); $node->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->removeFromIndex($index, $node); } public function testRemoveFromIndex_EntityNotPersisted_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $node = new Node($this->client); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->removeFromIndex($index, $node); } public function testRemoveFromIndex_BadType_ThrowsException() { $index = new Index($this->client, 'FOOTYPE', 'indexname'); $node = new Node($this->client); $node->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->removeFromIndex($index, $node); } public function testRemoveFromIndex_RelationshipTypeMismatch_ThrowsException() { $index = new Index($this->client, Index::TypeRelationship, 'indexname'); $node = new Node($this->client); $node->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->removeFromIndex($index, $node); } public function testRemoveFromIndex_NodeTypeMismatch_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $rel = new Relationship($this->client); $rel->setId(123); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->removeFromIndex($index, $rel); } public function testSearchIndex_BadType_ThrowsException() { $index = new Index($this->client, 'badtype', 'indexname'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->searchIndex($index, 'somekey', 'somevalue'); } public function testSearchIndex_NoIndexName_ThrowsException() { $index = new Index($this->client, Index::TypeNode, null); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->searchIndex($index, 'somekey', 'somevalue'); } public function testSearchIndex_NoKeySpecified_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->searchIndex($index, null, 'somevalue'); } public function testSearchIndex_Error_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->transport->expects($this->once()) ->method('get') ->with('/index/node/indexname/somekey/somevalue') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->searchIndex($index, 'somekey', 'somevalue'); } public function testSearchIndex_NodesFound_ReturnsArray() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $return = array( array( "self" => "http://localhost:7474/db/data/node/123", "data" => array("foo"=>"bar"), ), array( "self" => "http://localhost:7474/db/data/node/456", "data" => array("baz"=>"qux"), ) ); $this->transport->expects($this->once()) ->method('get') ->with('/index/node/indexname/somekey/somevalue') ->will($this->returnValue(array('code'=>200,'data'=>$return))); $result = $this->client->searchIndex($index, 'somekey', 'somevalue'); $this->assertEquals(2, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]); $this->assertEquals(123, $result[0]->getId()); $this->assertEquals(array('foo'=>'bar'), $result[0]->getProperties()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[1]); $this->assertEquals(456, $result[1]->getId()); $this->assertEquals(array('baz'=>'qux'), $result[1]->getProperties()); } public function testSearchIndex_RelationshipsFound_ReturnsArray() { $index = new Index($this->client, Index::TypeRelationship, 'indexname'); $return = array( array( "start" => "http://localhost:7474/db/data/node/123", "end" => "http://localhost:7474/db/data/node/456", "self" => "http://localhost:7474/db/data/relationship/789", "type" => "FOOTYPE", "data" => array("foo"=>"bar"), ), ); $this->transport->expects($this->once()) ->method('get') ->with('/index/relationship/indexname/somekey/somevalue') ->will($this->returnValue(array('code'=>200,'data'=>$return))); $result = $this->client->searchIndex($index, 'somekey', 'somevalue'); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $result[0]); $this->assertEquals(789, $result[0]->getId()); $this->assertEquals(array('foo'=>'bar'), $result[0]->getProperties()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getStartNode()); $this->assertEquals(123, $result[0]->getStartNode()->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getEndNode()); $this->assertEquals(456, $result[0]->getEndNode()->getId()); } public function testSearchIndex_UrlEntities_ReturnsArray() { $index = new Index($this->client, Index::TypeRelationship, 'index name'); $return = array( array( "start" => "http://localhost:7474/db/data/node/123", "end" => "http://localhost:7474/db/data/node/456", "self" => "http://localhost:7474/db/data/relationship/789", "type" => "FOOTYPE", "data" => array("foo"=>"bar"), ), ); $this->transport->expects($this->once()) ->method('get') ->with('/index/relationship/index%20name/some%40key/some%24value') ->will($this->returnValue(array('code'=>200,'data'=>$return))); $result = $this->client->searchIndex($index, 'some@key', 'some$value'); $this->assertEquals(1, count($result)); } public function testQueryIndex_BadType_ThrowsException() { $index = new Index($this->client, 'badtype', 'indexname'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->queryIndex($index, 'somekey:somevalue*'); } public function testQueryIndex_NoIndexName_ThrowsException() { $index = new Index($this->client, Index::TypeNode, null); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->queryIndex($index, 'somekey:somevalue*'); } public function testQueryIndex_NoQuerySpecified_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->queryIndex($index, null); } public function testQueryIndex_Error_ThrowsException() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $this->transport->expects($this->once()) ->method('get') ->with('/index/node/indexname?query='.rawurlencode('somekey:somevalue*')) ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->queryIndex($index, 'somekey:somevalue*'); } public function testQueryIndex_NodesFound_ReturnsArray() { $index = new Index($this->client, Index::TypeNode, 'indexname'); $return = array( array( "self" => "http://localhost:7474/db/data/node/123", "data" => array("foo"=>"bar"), ), array( "self" => "http://localhost:7474/db/data/node/456", "data" => array("baz"=>"qux"), ) ); $this->transport->expects($this->once()) ->method('get') ->with('/index/node/indexname?query='.rawurlencode('somekey:somevalue*')) ->will($this->returnValue(array('code'=>200,'data'=>$return))); $result = $this->client->queryIndex($index, 'somekey:somevalue*'); $this->assertEquals(2, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]); $this->assertEquals(123, $result[0]->getId()); $this->assertEquals(array('foo'=>'bar'), $result[0]->getProperties()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[1]); $this->assertEquals(456, $result[1]->getId()); $this->assertEquals(array('baz'=>'qux'), $result[1]->getProperties()); } public function testQueryIndex_RelationshipsFound_ReturnsArray() { $index = new Index($this->client, Index::TypeRelationship, 'indexname'); $return = array( array( "start" => "http://localhost:7474/db/data/node/123", "end" => "http://localhost:7474/db/data/node/456", "self" => "http://localhost:7474/db/data/relationship/789", "type" => "FOOTYPE", "data" => array("foo"=>"bar"), ), ); $this->transport->expects($this->once()) ->method('get') ->with('/index/relationship/indexname?query='.rawurlencode('somekey:somevalue*')) ->will($this->returnValue(array('code'=>200,'data'=>$return))); $result = $this->client->queryIndex($index, 'somekey:somevalue*'); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $result[0]); $this->assertEquals(789, $result[0]->getId()); $this->assertEquals(array('foo'=>'bar'), $result[0]->getProperties()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getStartNode()); $this->assertEquals(123, $result[0]->getStartNode()->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getEndNode()); $this->assertEquals(456, $result[0]->getEndNode()->getId()); } public function testGetIndexes_ServerError_ThrowsException() { $this->transport->expects($this->once()) ->method('get') ->with('/index/node') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $results = $this->client->getIndexes(Index::TypeNode); } public function testGetIndexes_BadType_ThrowsException() { $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->getIndexes('foo'); } public function testGetIndexes_NoIndexes_ReturnsEmptyArray() { $this->transport->expects($this->once()) ->method('get') ->with('/index/node') ->will($this->returnValue(array('code'=>200, 'data'=>''))); $results = $this->client->getIndexes(Index::TypeNode); $this->assertInternalType('array', $results); $this->assertEquals(0, count($results)); } public function testGetIndexes_NodeType_ReturnsArray() { $favoritesConfig = array( 'template' =>'http://0.0.0.0:7474/db/data/index/node/favorites/{key}/{value}', 'provider' =>'lucene', 'type' =>'exact', ); $usersConfig = array( 'template' =>'http://0.0.0.0:7474/db/data/index/node/users/{key}/{value}', 'provider' =>'lucene', 'type' =>'fulltext', ); $this->transport->expects($this->once()) ->method('get') ->with('/index/node') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'favorites' => $favoritesConfig, 'users' => $usersConfig, )))); $results = $this->client->getIndexes(Index::TypeNode); $this->assertEquals(2, count($results)); $this->assertInstanceOf('Everyman\Neo4j\Index', $results[0]); $this->assertEquals(Index::TypeNode, $results[0]->getType()); $this->assertEquals('favorites', $results[0]->getName()); $this->assertEquals($favoritesConfig, $results[0]->getConfig()); $this->assertInstanceOf('Everyman\Neo4j\Index', $results[1]); $this->assertEquals(Index::TypeNode, $results[1]->getType()); $this->assertEquals('users', $results[1]->getName()); $this->assertEquals($usersConfig, $results[1]->getConfig()); } public function testGetIndexes_RelationshipType_ReturnsArray() { $this->transport->expects($this->once()) ->method('get') ->with('/index/relationship') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'favorites' => array('template' =>'http://0.0.0.0:7474/db/data/index/relationship/favorites/{key}/{value}'), 'users' => array('template' =>'http://0.0.0.0:7474/db/data/index/relationship/users/{key}/{value}'), )))); $results = $this->client->getIndexes(Index::TypeRelationship); $this->assertEquals(2, count($results)); $this->assertInstanceOf('Everyman\Neo4j\Index', $results[0]); $this->assertEquals(Index::TypeRelationship, $results[0]->getType()); $this->assertEquals('favorites', $results[0]->getName()); $this->assertInstanceOf('Everyman\Neo4j\Index', $results[1]); $this->assertEquals(Index::TypeRelationship, $results[1]->getType()); $this->assertEquals('users', $results[1]->getName()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_LabelTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = $this->getMock('Everyman\Neo4j\Client', array('getServerInfo'), array($this->transport)); $this->client->expects($this->any()) ->method('getServerInfo') ->will($this->returnValue(array( 'cypher' => $this->endpoint.'/cypher', 'version' => array( "full" => "2.0.0-M06", "major" => "2", "minor" => "0", ) ))); } public function testMakeLabel_ReturnsLabel() { $labelNameA = 'FOOBAR'; $labelNameB = 'BAZQUX'; $labelA = $this->client->makeLabel($labelNameA); $labelB = $this->client->makeLabel($labelNameB); self::assertInstanceOf('Everyman\Neo4j\Label', $labelA); self::assertEquals($labelNameA, $labelA->getName()); self::assertInstanceOf('Everyman\Neo4j\Label', $labelB); self::assertEquals($labelNameB, $labelB->getName()); } public function testMakeLabel_SameName_ReturnsSameLabelInstance() { $labelName = 'FOOBAR'; $labelA = $this->client->makeLabel($labelName); $labelB = $this->client->makeLabel($labelName); self::assertInstanceOf('Everyman\Neo4j\Label', $labelA); self::assertInstanceOf('Everyman\Neo4j\Label', $labelB); self::assertSame($labelA, $labelB); } public function testGetNodesForLabel_NodesExistForLabel_ReturnsRow() { $labelName = 'FOOBAR'; $label = new Label($this->client, $labelName); $returnData = array( array( "self" => "http://localhost:7474/db/data/relationship/56", "data" => array(), ), array( "self" => "http://localhost:7474/db/data/relationship/834", "data" => array(), ), ); $this->transport->expects($this->once()) ->method('get') ->with("/label/{$labelName}/nodes") ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $nodes = $this->client->getNodesForLabel($label); self::assertInstanceOf('Everyman\Neo4j\Query\Row', $nodes); self::assertEquals(2, count($nodes)); self::assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); self::assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); self::assertEquals(56, $nodes[0]->getId()); self::assertEquals(834, $nodes[1]->getId()); } public function testGetNodesForLabel_NodesExistForLabelAndProperty_ReturnsRow() { $labelName = 'FOOBAR'; $propertyName = 'baz'; $propertyValue = 'qux'; $label = new Label($this->client, $labelName); $returnData = array( array( "self" => "http://localhost:7474/db/data/relationship/56", "data" => array($propertyName => $propertyValue), ), ); $this->transport->expects($this->once()) ->method('get') ->with("/label/{$labelName}/nodes?{$propertyName}=%22{$propertyValue}%22") ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $nodes = $this->client->getNodesForLabel($label, $propertyName, $propertyValue); self::assertInstanceOf('Everyman\Neo4j\Query\Row', $nodes); self::assertEquals(1, count($nodes)); self::assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); self::assertEquals(56, $nodes[0]->getId()); } public function testGetNodesForLabel_NoNodesExist_ReturnsEmptyRow() { $labelName = 'FOOBAR'; $label = new Label($this->client, $labelName); $returnData = array(); $this->transport->expects($this->once()) ->method('get') ->with("/label/{$labelName}/nodes") ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $nodes = $this->client->getNodesForLabel($label); self::assertInstanceOf('Everyman\Neo4j\Query\Row', $nodes); self::assertEquals(0, count($nodes)); } public function testGetNodesForLabel_ProperlyUrlEncodesPath() { $labelName = 'FOO+Bar /Baz'; $propertyName = 'ba$! "z qux"'; $propertyValue = 'f @oo !B"/+%20ar '; $label = new Label($this->client, $labelName); $expectedLabel = rawurlencode($labelName); $expectedName = rawurlencode($propertyName); $expectedValue = rawurlencode('"'.$propertyValue.'"'); $this->transport->expects($this->once()) ->method('get') ->with("/label/{$expectedLabel}/nodes?{$expectedName}={$expectedValue}") ->will($this->returnValue(array('code'=>200,'data'=>array()))); $this->client->getNodesForLabel($label, $propertyName, $propertyValue); } public function testGetNodesForLabel_PropertyWithIntegerValueGiven_CallsClientMethod() { $labelName = 'FOOBAR'; $propertyName = 'baz'; $propertyValue = 1; $label = new Label($this->client, $labelName); $returnData = array( array( "self" => "http://localhost:7474/db/data/relationship/56", "data" => array($propertyName => $propertyValue), ), ); $this->transport->expects($this->once()) ->method('get') ->with("/label/{$labelName}/nodes?{$propertyName}={$propertyValue}") ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $nodes = $this->client->getNodesForLabel($label, $propertyName, $propertyValue); self::assertInstanceOf('Everyman\Neo4j\Query\Row', $nodes); self::assertEquals(1, count($nodes)); self::assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); self::assertEquals(56, $nodes[0]->getId()); } public function testGetNodesForLabel_PropertyNameWithoutValue_ThrowsException() { $labelName = 'FOOBAR'; $label = new Label($this->client, $labelName); $this->transport->expects($this->never()) ->method('get'); $this->setExpectedException('InvalidArgumentException'); $this->client->getNodesForLabel($label, 'prop', null); } public function testGetNodesForLabel_PropertyValueWithoutName_ThrowsException() { $labelName = 'FOOBAR'; $label = new Label($this->client, $labelName); $this->transport->expects($this->never()) ->method('get'); $this->setExpectedException('InvalidArgumentException'); $this->client->getNodesForLabel($label, null, 'val'); } public function testGetNodesForLabel_NoLabelCapability_ThrowsException() { $this->client = $this->getMock('Everyman\Neo4j\Client', array('getServerInfo'), array($this->transport)); $this->client->expects($this->any()) ->method('getServerInfo') ->will($this->returnValue(array( 'cypher' => $this->endpoint.'/cypher', 'version' => array( "full" => "1.9.0", "major" => "1", "minor" => "9", ) ))); $labelName = 'FOOBAR'; $label = new Label($this->client, $labelName); $this->transport->expects($this->never()) ->method('get'); $this->setExpectedException('RuntimeException', 'label capability'); $this->client->getNodesForLabel($label); } public function testGetLabels_NoNode_ReturnsArrayOfLabelsAttachedToNodesOnTheServer() { $labelAlreadyInstantiated = $this->client->makeLabel('BAZQUX'); $returnData = array('FOOBAR', $labelAlreadyInstantiated->getName(), 'LOREMIPSUM'); $this->transport->expects($this->once()) ->method('get') ->with("/labels") ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $labels = $this->client->getLabels(); self::assertEquals(count($returnData), count($labels)); foreach ($labels as $i => $label) { self::assertInstanceOf('Everyman\Neo4j\Label', $label); self::assertEquals($returnData[$i], $label->getName()); } self::assertSame($labelAlreadyInstantiated, $labels[1]); } public function testGetLabels_NodeSpecified_ReturnsArrayOfLabelsAttachedToNode() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $returnData = array('FOOBAR', 'BAZQUX'); $this->transport->expects($this->once()) ->method('get') ->with("/node/{$nodeId}/labels") ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $labels = $this->client->getLabels($node); self::assertEquals(count($returnData), count($labels)); foreach ($labels as $i => $label) { self::assertInstanceOf('Everyman\Neo4j\Label', $label); self::assertEquals($returnData[$i], $label->getName()); } } public function testGetLabels_NodeIdZero_ReturnsArrayOfLabelsAttachedToNode() { $nodeId = 0; $node = new Node($this->client); $node->setId($nodeId); $returnData = array('FOOBAR', 'BAZQUX'); $this->transport->expects($this->once()) ->method('get') ->with("/node/{$nodeId}/labels") ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $labels = $this->client->getLabels($node); self::assertEquals(count($returnData), count($labels)); foreach ($labels as $i => $label) { self::assertInstanceOf('Everyman\Neo4j\Label', $label); self::assertEquals($returnData[$i], $label->getName()); } } public function testGetLabels_NoNodeId_ThrowsException() { $node = new Node($this->client); $this->transport->expects($this->never()) ->method('get'); $this->setExpectedException('InvalidArgumentException'); $labels = $this->client->getLabels($node); } public function testGetLabels_NoLabelCapabiltiy_ThrowsException() { $this->client = $this->getMock('Everyman\Neo4j\Client', array('getServerInfo'), array($this->transport)); $this->client->expects($this->any()) ->method('getServerInfo') ->will($this->returnValue(array( 'cypher' => $this->endpoint.'/cypher', 'version' => array( "full" => "1.9.0", "major" => "1", "minor" => "9", ) ))); $this->transport->expects($this->never()) ->method('get'); $this->setExpectedException('RuntimeException', 'label capability'); $this->client->getLabels(); } public function testAddLabels_SendsCorrectCypherQuery() { $nodeId = 123; $labelAName = 'FOOBAR'; $labelBName = 'BAZ QUX'; $labelCName = 'HACK`THIS'; $escapedCName = 'HACK``THIS'; $node = new Node($this->client); $node->setId($nodeId); $labelA = $this->client->makeLabel($labelAName); $labelB = $this->client->makeLabel($labelBName); $labelC = $this->client->makeLabel($labelCName); $expectedLabels = array('LOREMIPSUM', $labelAName, $labelBName, $labelCName); $expectedQuery = "START n=node({nodeId}) SET n:`{$labelAName}`:`{$labelBName}`:`{$escapedCName}` RETURN labels(n) AS labels"; $expectedParams = array("nodeId" => $nodeId); $this->transport->expects($this->any()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'neo4j_version' => '2.0.foo', 'cypher' => $this->endpoint.'/cypher', )))); $this->transport->expects($this->once()) ->method('post') ->with('/cypher', array( 'query' => $expectedQuery, 'params' => $expectedParams, )) ->will($this->returnValue(array('code'=>200,'data'=>array( 'columns' => array('labels'), 'data' => array(array($expectedLabels)), )))); $resultLabels = $this->client->addLabels($node, array($labelA, $labelB, $labelC)); self::assertEquals(count($expectedLabels), count($resultLabels)); foreach ($resultLabels as $i => $label) { self::assertInstanceOf('Everyman\Neo4j\Label', $label); self::assertEquals($expectedLabels[$i], $label->getName()); } } public function testAddLabels_NoLabelCapability_ThrowsException() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $labelAName = 'FOOBAR'; $labelA = $this->client->makeLabel($labelAName); $this->client = $this->getMock('Everyman\Neo4j\Client', array('getServerInfo'), array($this->transport)); $this->client->expects($this->any()) ->method('getServerInfo') ->will($this->returnValue(array( 'cypher' => $this->endpoint.'/cypher', 'version' => array( "full" => "1.9.0", "major" => "1", "minor" => "9", ) ))); $this->transport->expects($this->never()) ->method('get'); $this->setExpectedException('RuntimeException'); $this->client->addLabels($node, array($labelA)); } public function testAddLabels_NoNodeId_ThrowsException() { $labelAName = 'FOOBAR'; $labelA = $this->client->makeLabel($labelAName); $node = new Node($this->client); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('InvalidArgumentException', 'unsaved node'); $this->client->addLabels($node, array($labelA)); } public function testAddLabels_NodeIdZero_DoesNotThrowException() { $nodeId = 0; $labelAName = 'FOOBAR'; $node = new Node($this->client); $node->setId($nodeId); $labelA = $this->client->makeLabel($labelAName); $expectedQuery = "START n=node({nodeId}) SET n:`{$labelAName}` RETURN labels(n) AS labels"; $expectedParams = array("nodeId" => $nodeId); $this->transport->expects($this->once()) ->method('post') ->with('/cypher', array( 'query' => $expectedQuery, 'params' => $expectedParams, )) ->will($this->returnValue(array('code'=>200,'data'=>array( 'columns' => array('labels'), 'data' => array(array(array($labelAName))), )))); $resultLabels = $this->client->addLabels($node, array($labelA)); self::assertEquals(1, count($resultLabels)); self::assertEquals($labelAName, $resultLabels[0]->getName()); } public function testAddLabels_NonLabelGiven_ThrowsException() { $labelAName = 'FOOBAR'; $labelA = $this->client->makeLabel($labelAName); $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('InvalidArgumentException', 'non-label'); $this->client->addLabels($node, array($labelA, 'not-a-label')); } public function testAddLabels_NoLabelsGiven_ThrowsException() { $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('InvalidArgumentException', 'No labels'); $this->client->addLabels($node, array()); } public function testRemoveLabels_SendsCorrectCypherQuery() { $nodeId = 123; $labelAName = 'FOOBAR'; $labelBName = 'BAZ QUX'; $node = new Node($this->client); $node->setId($nodeId); $labelA = $this->client->makeLabel($labelAName); $labelB = $this->client->makeLabel($labelBName); $expectedLabels = array('LOREMIPSUM', $labelAName, $labelBName); $expectedQuery = "START n=node({nodeId}) REMOVE n:`{$labelAName}`:`{$labelBName}` RETURN labels(n) AS labels"; $expectedParams = array("nodeId" => $nodeId); $this->transport->expects($this->any()) ->method('get') ->with('/') ->will($this->returnValue(array('code'=>200, 'data'=>array( 'neo4j_version' => '2.0.foo', 'cypher' => $this->endpoint.'/cypher', )))); $this->transport->expects($this->once()) ->method('post') ->with('/cypher', array( 'query' => $expectedQuery, 'params' => $expectedParams, )) ->will($this->returnValue(array('code'=>200,'data'=>array( 'columns' => array('labels'), 'data' => array(array($expectedLabels)), )))); $resultLabels = $this->client->removeLabels($node, array($labelA, $labelB)); self::assertEquals(count($expectedLabels), count($resultLabels)); foreach ($resultLabels as $i => $label) { self::assertInstanceOf('Everyman\Neo4j\Label', $label); self::assertEquals($expectedLabels[$i], $label->getName()); } } public function testRemoveLabels_NoLabelCapability_ThrowsException() { $nodeId = 123; $node = new Node($this->client); $node->setId($nodeId); $labelAName = 'FOOBAR'; $labelA = $this->client->makeLabel($labelAName); $this->client = $this->getMock('Everyman\Neo4j\Client', array('getServerInfo'), array($this->transport)); $this->client->expects($this->any()) ->method('getServerInfo') ->will($this->returnValue(array( 'cypher' => $this->endpoint.'/cypher', 'version' => array( "full" => "1.9.0", "major" => "1", "minor" => "9", ) ))); $this->transport->expects($this->never()) ->method('get'); $this->setExpectedException('RuntimeException'); $this->client->removeLabels($node, array($labelA)); } public function testRemoveLabels_NoNodeId_ThrowsException() { $labelAName = 'FOOBAR'; $labelA = $this->client->makeLabel($labelAName); $node = new Node($this->client); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('InvalidArgumentException', 'unsaved node'); $this->client->removeLabels($node, array($labelA)); } public function testRemoveLabels_NonLabelGiven_ThrowsException() { $labelAName = 'FOOBAR'; $labelA = $this->client->makeLabel($labelAName); $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('InvalidArgumentException', 'non-label'); $this->client->removeLabels($node, array($labelA, 'not-a-label')); } public function testRemoveLabels_NoLabelsGiven_ThrowsException() { $node = new Node($this->client); $node->setId(123); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('InvalidArgumentException', 'No labels'); $this->client->removeLabels($node, array()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_PathTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); } public function testGetPaths_PathsExist_ReturnsArray() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $endNode->setId(456); $finder = new PathFinder($this->client); $finder->setType('FOOTYPE') ->setDirection(Relationship::DirectionOut) ->setMaxDepth(3) ->setStartNode($startNode) ->setEndNode($endNode); $data = array( 'to' => $this->endpoint.'/node/456', 'relationships' => array('type'=>'FOOTYPE', 'direction'=>Relationship::DirectionOut), 'max_depth' => 3, 'max depth' => 3, 'algorithm' => 'shortestPath' ); $returnData = array( array( "start" => "http://localhost:7474/db/data/node/123", "nodes" => array("http://localhost:7474/db/data/node/123", "http://localhost:7474/db/data/node/341", "http://localhost:7474/db/data/node/456"), "length" => 2, "relationships" => array("http://localhost:7474/db/data/relationship/564", "http://localhost:7474/db/data/relationship/32"), "end" => "http://localhost:7474/db/data/node/456" ), array( "start" => "http://localhost:7474/db/data/node/123", "nodes" => array("http://localhost:7474/db/data/node/123", "http://localhost:7474/db/data/node/41", "http://localhost:7474/db/data/node/456"), "length" => 2, "relationships" => array("http://localhost:7474/db/data/relationship/437", "http://localhost:7474/db/data/relationship/97"), "end" => "http://localhost:7474/db/data/node/456" ), ); $this->transport->expects($this->once()) ->method('post') ->with('/node/123/paths', $data) ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $paths = $this->client->getPaths($finder); $this->assertEquals(2, count($paths)); $this->assertInstanceOf('Everyman\Neo4j\Path', $paths[0]); $this->assertInstanceOf('Everyman\Neo4j\Path', $paths[1]); $rels = $paths[0]->getRelationships(); $this->assertEquals(2, count($rels)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[0]); $this->assertEquals(564, $rels[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[1]); $this->assertEquals(32, $rels[1]->getId()); $nodes = $paths[0]->getNodes(); $this->assertEquals(3, count($nodes)); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); $this->assertEquals(123, $nodes[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); $this->assertEquals(341, $nodes[1]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[2]); $this->assertEquals(456, $nodes[2]->getId()); $rels = $paths[1]->getRelationships(); $this->assertEquals(2, count($rels)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[0]); $this->assertEquals(437, $rels[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[1]); $this->assertEquals(97, $rels[1]->getId()); $nodes = $paths[1]->getNodes(); $this->assertEquals(3, count($nodes)); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); $this->assertEquals(123, $nodes[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); $this->assertEquals(41, $nodes[1]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[2]); $this->assertEquals(456, $nodes[2]->getId()); } public function testGetPaths_NoMaxDepth_MaxDepthDefaultsToOne_ReturnsArray() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $endNode->setId(456); $finder = new PathFinder($this->client); $finder->setType('FOOTYPE') ->setDirection(Relationship::DirectionOut) ->setStartNode($startNode) ->setEndNode($endNode); $data = array( 'to' => $this->endpoint.'/node/456', 'relationships' => array('type'=>'FOOTYPE', 'direction'=>Relationship::DirectionOut), 'max_depth' => 1, 'max depth' => 1, 'algorithm' => 'shortestPath' ); $returnData = array(); $this->transport->expects($this->once()) ->method('post') ->with('/node/123/paths', $data) ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $paths = $this->client->getPaths($finder); $this->assertEquals(0, count($paths)); } public function testGetPaths_DirectionGivenButNoType_ThrowsException() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $endNode->setId(456); $finder = new PathFinder($this->client); $finder->setDirection(Relationship::DirectionOut) ->setStartNode($startNode) ->setEndNode($endNode); $this->setExpectedException('\Everyman\Neo4j\Exception'); $paths = $this->client->getPaths($finder); } public function testGetPaths_StartNodeNotPersisted_ThrowsException() { $startNode = new Node($this->client); $endNode = new Node($this->client); $endNode->setId(456); $finder = new PathFinder($this->client); $finder->setStartNode($startNode) ->setEndNode($endNode); $this->setExpectedException('\Everyman\Neo4j\Exception'); $paths = $this->client->getPaths($finder); } public function testGetPaths_EndNodeNotPersisted_ThrowsException() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $finder = new PathFinder($this->client); $finder->setStartNode($startNode) ->setEndNode($endNode); $this->setExpectedException('\Everyman\Neo4j\Exception'); $paths = $this->client->getPaths($finder); } public function testGetPaths_DijkstraSearchNoCostProperty_ThrowsException() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $endNode->setId(456); $finder = new PathFinder($this->client); $finder->setStartNode($startNode) ->setEndNode($endNode) ->setAlgorithm(PathFinder::AlgoDijkstra); $this->setExpectedException('\Everyman\Neo4j\Exception'); $paths = $this->client->getPaths($finder); } public function testGetPaths_DijkstraSearch_ReturnsResult() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $endNode->setId(456); $finder = new PathFinder($this->client); $finder->setStartNode($startNode) ->setEndNode($endNode) ->setAlgorithm(PathFinder::AlgoDijkstra) ->setCostProperty('distance') ->setDefaultCost(2); $data = array( 'to' => $this->endpoint.'/node/456', 'max_depth' => 1, 'max depth' => 1, 'algorithm' => 'dijkstra', 'cost_property' => 'distance', 'cost property' => 'distance', 'default_cost' => 2, 'default cost' => 2, ); $returnData = array(); $this->transport->expects($this->once()) ->method('post') ->with('/node/123/paths', $data) ->will($this->returnValue(array('code'=>200,'data'=>$returnData))); $paths = $this->client->getPaths($finder); $this->assertEquals(0, count($paths)); } public function testGetPaths_TransportFails_ThrowsException() { $startNode = new Node($this->client); $startNode->setId(123); $endNode = new Node($this->client); $endNode->setId(456); $finder = new PathFinder($this->client); $finder->setType('FOOTYPE') ->setDirection(Relationship::DirectionOut) ->setMaxDepth(3) ->setStartNode($startNode) ->setEndNode($endNode); $this->transport->expects($this->any()) ->method('post') ->will($this->returnValue(array('code'=>400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->getPaths($finder); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_TransactionTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = $this->getMock('Everyman\Neo4j\Client', array('hasCapability'), array($this->transport)); $this->client->expects($this->any()) ->method('hasCapability') ->will($this->returnValue(true)); } public function testBeginTransaction_ReturnsNewTransactionWithNoId() { $result = $this->client->beginTransaction(); self::assertInstanceOf('\Everyman\Neo4j\Transaction', $result); self::assertNull($result->getId()); } public function testAddStatements_NewTransaction_ReturnsResultSetAndSetsTransactionId() { $queryTemplateA = "This is the query template"; $queryParamsA = array('foo' => 'bar', 'baz' => 123); $queryA = new Cypher\Query($this->client, $queryTemplateA, $queryParamsA); $queryTemplateB = "This is the query template B"; $queryParamsB = array('foo' => 'barB', 'bazB' => 456); $queryB = new Cypher\Query($this->client, $queryTemplateB, $queryParamsB); $transaction = new Transaction($this->client); $expectedRequest = array( 'statements' => array( array( 'statement' => $queryTemplateA, 'parameters' => (object)$queryParamsA, 'resultDataContents' => array('rest'), ), array( 'statement' => $queryTemplateB, 'parameters' => (object)$queryParamsB, 'resultDataContents' => array('rest'), ), ), ); $expectedResponse = array( "commit" => $this->endpoint . '/transaction/987/commit', "transaction" => array("expires" => "Wed, 16 Oct 2013 23:07:12 +0000"), "errors" => array(), "results" => array( // Result of queryA array( 'columns' => array('name','age'), 'data' => array( array("rest" => array('Bob', 12)), array("rest" => array('Lotta', 0)), array("rest" => array('Brenda', 14)), ) ), // Result of queryB array( 'columns' => array('count','somenode'), 'data' => array( array("rest" => array( 5, array( "self" => $this->endpoint.'/node/34', "data" => array("baz" => "qux"), ) )), array("rest" => array( 2, array( "self" => $this->endpoint.'/node/21', "data" => array("lorem" => "ipsum"), ) )), ) ), ), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction', $expectedRequest) ->will($this->returnValue(array("code" => 201, "data" => $expectedResponse))); $result = $this->client->addStatementsToTransaction($transaction, array($queryA, $queryB)); self::assertInternalType('array', $result); self::assertEquals(2, count($result)); $resultA = $result[0]; self::assertInstanceOf('\Everyman\Neo4j\Query\ResultSet', $resultA); self::assertEquals(3, count($resultA)); self::assertEquals('Bob', $resultA[0]['name']); self::assertEquals(12, $resultA[0]['age']); $resultB = $result[1]; self::assertInstanceOf('\Everyman\Neo4j\Query\ResultSet', $resultB); self::assertEquals(2, count($resultB)); self::assertEquals(2, $resultB[1]['count']); self::assertInstanceOf('\Everyman\Neo4j\Node', $resultB[1]['somenode']); self::assertEquals(21, $resultB[1]['somenode']->getId()); self::assertEquals('ipsum', $resultB[1]['somenode']->getProperty('lorem')); self::assertEquals(987, $transaction->getId()); self::assertFalse($transaction->isClosed()); self::assertFalse($transaction->isError()); } public function testAddStatements_NoParams_ParamsSentAsEmptyObject() { $queryTemplateA = "This is the query template"; $queryA = new Cypher\Query($this->client, $queryTemplateA); $transaction = new Transaction($this->client); $expectedRequest = array( 'statements' => array( array( 'statement' => $queryTemplateA, 'parameters' => (object)array(), 'resultDataContents' => array('rest'), ), ), ); $expectedResponse = array( "commit" => $this->endpoint . '/transaction/987/commit', "transaction" => array("expires" => "Wed, 16 Oct 2013 23:07:12 +0000"), "errors" => array(), "results" => array( // Result of queryA array( 'columns' => array('name'), 'data' => array( array("rest" => array('Brenda')), ) ), ), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction', $expectedRequest) ->will($this->returnValue(array("code" => 201, "data" => $expectedResponse))); $result = $this->client->addStatementsToTransaction($transaction, array($queryA)); self::assertInternalType('array', $result); self::assertEquals(1, count($result)); } public function testAddStatements_ExistingTransactionId_ReturnsResultSet() { $queryA = new Cypher\Query($this->client, 'foobar'); $transaction = new Transaction($this->client); $transaction->setId(321); $expectedResponse = array( "commit" => $this->endpoint . '/transaction/321/commit', "transaction" => array("expires" => "Wed, 16 Oct 2013 23:07:12 +0000"), "errors" => array(), "results" => array(), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction/'.$transaction->getId()) ->will($this->returnValue(array("code" => 200, "data" => $expectedResponse))); $this->client->addStatementsToTransaction($transaction, array($queryA)); self::assertFalse($transaction->isClosed()); self::assertFalse($transaction->isError()); } public function testAddStatements_TransactionFailed_ThrowsException() { $queryA = new Cypher\Query($this->client, 'foobar'); $transaction = new Transaction($this->client); $expectedResponse = array( "commit" => $this->endpoint . '/transaction/321/commit', "transaction" => array("expires" => "Wed, 16 Oct 2013 23:07:12 +0000"), "errors" => array(), "results" => array(), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction') ->will($this->returnValue(array("code" => 400))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addStatementsToTransaction($transaction, array($queryA)); } public function testAddStatements_ErrorsGiven_ThrowsException() { $queryA = new Cypher\Query($this->client, 'foobar'); $transaction = new Transaction($this->client); $expectedResponse = array( "commit" => $this->endpoint . '/transaction/321/commit', "transaction" => array("expires" => "Wed, 16 Oct 2013 23:07:12 +0000"), "errors" => array("foo bar error"), "results" => array(), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction') ->will($this->returnValue(array("code" => 200, "data" => $expectedResponse))); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addStatementsToTransaction($transaction, array($queryA)); } public function testAddStatements_NewTransactionWithCommit_ReturnsResulSet() { $queryA = new Cypher\Query($this->client, 'foobar'); $transaction = new Transaction($this->client); $commit = true; $expectedResponse = array( "errors" => array(), "results" => array(), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction/commit') ->will($this->returnValue(array("code" => 200, "data" => $expectedResponse))); $this->client->addStatementsToTransaction($transaction, array($queryA), $commit); } public function testAddStatements_ExistingTransactionWithCommit_ReturnsResulSet() { $queryA = new Cypher\Query($this->client, 'foobar'); $transaction = new Transaction($this->client); $transaction->setId(321); $commit = true; $expectedResponse = array( "commit" => $this->endpoint . '/transaction/321/commit', "transaction" => array("expires" => "Wed, 16 Oct 2013 23:07:12 +0000"), "errors" => array(), "results" => array(), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction/'.$transaction->getId().'/commit') ->will($this->returnValue(array("code" => 200, "data" => $expectedResponse))); $this->client->addStatementsToTransaction($transaction, array($queryA), $commit); } public function testAddStatements_KeepAlive_HasTransactionId_SendsToTransportWithoutStatements() { $transaction = new Transaction($this->client); $transaction->setId(321); $expectedRequest = array( 'statements' => array(), ); $expectedResponse = array( "commit" => $this->endpoint . '/transaction/321/commit', "transaction" => array("expires" => "Wed, 16 Oct 2013 23:07:12 +0000"), "errors" => array(), "results" => array(), ); $this->transport->expects($this->once()) ->method('post') ->with('/transaction/'.$transaction->getId(), $expectedRequest) ->will($this->returnValue(array("code" => 200, "data" => $expectedResponse))); $this->client->addStatementsToTransaction($transaction, array()); } public function testAddStatements_KeepAlive_NoTransactionId_ThrowsException() { $transaction = new Transaction($this->client); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addStatementsToTransaction($transaction, array()); } public function testAddStatements_NoTransactionCapability_ThrowsException() { $this->client = $this->getMock('Everyman\Neo4j\Client', array('hasCapability'), array($this->transport)); $this->client->expects($this->any()) ->method('hasCapability') ->will($this->returnValue(false)); $queryA = new Cypher\Query($this->client, 'foobar'); $transaction = new Transaction($this->client); $this->transport->expects($this->never()) ->method('post'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->addStatementsToTransaction($transaction, array($queryA)); } public function testRollback_HasTransactionId_SendsDelete() { $transaction = new Transaction($this->client); $transaction->setId(321); $this->transport->expects($this->once()) ->method('delete') ->with('/transaction/'.$transaction->getId()) ->will($this->returnValue(array("code" => 200))); $this->client->rollbackTransaction($transaction); } public function testRollback_NoTransactionId_ThrowsException() { $transaction = new Transaction($this->client); $this->transport->expects($this->never()) ->method('delete'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->rollbackTransaction($transaction); } public function testRollback_NoTransactionCapability_ThrowsException() { $this->client = $this->getMock('Everyman\Neo4j\Client', array('hasCapability'), array($this->transport)); $this->client->expects($this->any()) ->method('hasCapability') ->will($this->returnValue(false)); $transaction = new Transaction($this->client); $transaction->setId(321); $this->transport->expects($this->never()) ->method('delete'); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->rollbackTransaction($transaction); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Client_TraversalTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); } public function testTraversal_NoNodeId_ThrowsException() { $traversal = new Traversal($this->client); $node = new Node($this->client); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->executeTraversal($traversal, $node, Traversal::ReturnTypeNode); } public function testTraversal_BadReturnType_ThrowsException() { $traversal = new Traversal($this->client); $node = new Node($this->client); $node->setId(1); $this->setExpectedException('\Everyman\Neo4j\Exception'); $this->client->executeTraversal($traversal, $node, 'FOOTYPE'); } /** * @dataProvider dataProvider_TestTraversal */ public function testTraversal_TraversalOptions_PassesThroughCorrectDataToTransport($traversal, $expectedData) { $node = new Node($this->client); $node->setId(1); $this->transport->expects($this->once()) ->method('post') ->with('/node/1/traverse/node', $expectedData) ->will($this->returnValue(array("code"=>200,"data"=>array()))); $result = $this->client->executeTraversal($traversal, $node, Traversal::ReturnTypeNode); $this->assertEquals(array(), $result); } public function dataProvider_TestTraversal() { $this->transport = $this->getMock('Everyman\Neo4j\Transport'); $this->transport->expects($this->any()) ->method('getEndpoint') ->will($this->returnValue($this->endpoint)); $this->client = new Client($this->transport); $scenarios = array(); $traversal = new Traversal($this->client); $scenarios[] = array($traversal, array()); $traversal = new Traversal($this->client); $traversal->setOrder(Traversal::OrderDepthFirst); $scenarios[] = array($traversal, array( "order" => "depth_first", )); $traversal = new Traversal($this->client); $traversal->setUniqueness(Traversal::UniquenessNodePath); $scenarios[] = array($traversal, array( "uniqueness" => "node_path", )); $traversal = new Traversal($this->client); $traversal->setMaxDepth(2); $scenarios[] = array($traversal, array( "max_depth" => 2, )); $traversal = new Traversal($this->client); $traversal->addRelationship('FOOTYPE') ->addRelationship('BARTYPE', Relationship::DirectionIn); $scenarios[] = array($traversal, array( "relationships" => array( array('type'=>'FOOTYPE'), array('type'=>'BARTYPE', 'direction' => 'in'), ), )); $traversal = new Traversal($this->client); $traversal->setPruneEvaluator('javascript', "position.endNode().getProperty('date')>1234567;"); $scenarios[] = array($traversal, array( "prune_evaluator" => array( "language" => "javascript", "body" => "position.endNode().getProperty('date')>1234567;", ), )); $traversal = new Traversal($this->client); $traversal->setPruneEvaluator(Traversal::PruneNone); $scenarios[] = array($traversal, array( "prune_evaluator" => array( "language" => "builtin", "name" => "none", ), )); $traversal = new Traversal($this->client); $traversal->setReturnFilter('javascript', "position.endNode().getProperty('date')>1234567;"); $scenarios[] = array($traversal, array( "return_filter" => array( "language" => "javascript", "body" => "position.endNode().getProperty('date')>1234567;", ), )); $traversal = new Traversal($this->client); $traversal->setReturnFilter(Traversal::ReturnAll); $scenarios[] = array($traversal, array( "return_filter" => array( "language" => "builtin", "name" => "all", ), )); return $scenarios; } public function testTraversal_ReturnTypeNode_ReturnsArrayOfNodes() { $traversal = new Traversal($this->client); $node = new Node($this->client); $node->setId(1); $data = array( array( "self" => "http://localhost:7474/db/data/node/2", "data" => array( "name" => "foo", ), ), ); $this->transport->expects($this->once()) ->method('post') ->with('/node/1/traverse/node', array()) ->will($this->returnValue(array("code"=>200,"data"=>$data))); $result = $this->client->executeTraversal($traversal, $node, Traversal::ReturnTypeNode); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]); $this->assertEquals(2, $result[0]->getId()); $this->assertEquals('foo', $result[0]->getProperty('name')); } public function testTraversal_ReturnTypeRelationship_ReturnsArrayOfRelationships() { $traversal = new Traversal($this->client); $node = new Node($this->client); $node->setId(1); $data = array( array( "self" => "http://localhost:7474/db/data/relationship/2", "start" => "http://localhost:7474/db/data/node/1", "end" => "http://localhost:7474/db/data/node/3", "type" => "FOOTYPE", "data" => array( "name" => "foo", ), ), ); $this->transport->expects($this->once()) ->method('post') ->with('/node/1/traverse/relationship', array()) ->will($this->returnValue(array("code"=>200,"data"=>$data))); $result = $this->client->executeTraversal($traversal, $node, Traversal::ReturnTypeRelationship); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $result[0]); $this->assertEquals(2, $result[0]->getId()); $this->assertEquals('foo', $result[0]->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getStartNode()); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]->getEndNode()); $this->assertEquals(1, $result[0]->getStartNode()->getId()); $this->assertEquals(3, $result[0]->getEndNode()->getId()); } public function testTraversal_ReturnTypePath_ReturnsArrayOfPaths() { $traversal = new Traversal($this->client); $node = new Node($this->client); $node->setId(1); $data = array( array( "relationships" => array("http://localhost:7474/db/data/relationship/2"), "nodes" => array("http://localhost:7474/db/data/node/1","http://localhost:7474/db/data/node/3"), ), ); $this->transport->expects($this->once()) ->method('post') ->with('/node/1/traverse/path', array()) ->will($this->returnValue(array("code"=>200,"data"=>$data))); $result = $this->client->executeTraversal($traversal, $node, Traversal::ReturnTypePath); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Path', $result[0]); $rels = $result[0]->getRelationships(); $this->assertEquals(1, count($rels)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[0]); $this->assertEquals(2, $rels[0]->getId()); $nodes = $result[0]->getNodes(); $this->assertEquals(2, count($nodes)); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); $this->assertEquals(1, $nodes[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); $this->assertEquals(3, $nodes[1]->getId()); } public function testTraversal_ReturnTypeFullPath_ReturnsArrayOfPaths() { $traversal = new Traversal($this->client); $node = new Node($this->client); $node->setId(1); $data = array( array( "relationships" => array( array( "self" => "http://localhost:7474/db/data/relationship/2", "start" => "http://localhost:7474/db/data/node/1", "end" => "http://localhost:7474/db/data/node/3", "type" => "FOOTYPE", "data" => array( "name" => "baz", ), ), ), "nodes" => array( array( "self" => "http://localhost:7474/db/data/node/1", "data" => array( "name" => "foo", ), ), array( "self" => "http://localhost:7474/db/data/node/3", "data" => array( "name" => "bar", ), ), ), ), ); $this->transport->expects($this->once()) ->method('post') ->with('/node/1/traverse/fullpath', array()) ->will($this->returnValue(array("code"=>200,"data"=>$data))); $result = $this->client->executeTraversal($traversal, $node, Traversal::ReturnTypeFullPath); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Path', $result[0]); $rels = $result[0]->getRelationships(); $this->assertEquals(1, count($rels)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[0]); $this->assertEquals(2, $rels[0]->getId()); $this->assertEquals('FOOTYPE', $rels[0]->getType()); $this->assertEquals('baz', $rels[0]->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $rels[0]->getStartNode()); $this->assertInstanceOf('Everyman\Neo4j\Node', $rels[0]->getEndNode()); $this->assertEquals(1, $rels[0]->getStartNode()->getId()); $this->assertEquals(3, $rels[0]->getEndNode()->getId()); $nodes = $result[0]->getNodes(); $this->assertEquals(2, count($nodes)); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); $this->assertEquals(1, $nodes[0]->getId()); $this->assertEquals('foo', $nodes[0]->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); $this->assertEquals(3, $nodes[1]->getId()); $this->assertEquals('bar', $nodes[1]->getProperty('name')); } public function testTraversal_ServerReturnsErrorCode_ThrowsException() { $traversal = new Traversal($this->client); $node = new Node($this->client); $node->setId(1); $this->transport->expects($this->once()) ->method('post') ->with('/node/1/traverse/node', array()) ->will($this->returnValue(array("code"=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $result = $this->client->executeTraversal($traversal, $node, Traversal::ReturnTypeNode); } public function testPagedTraversal_TraversalGiven_ReturnsResultSets() { $traversal = new Traversal($this->client); $traversal->setOrder(Traversal::OrderDepthFirst); $node = new Node($this->client); $node->setId(1); $pager = new Pager($traversal, $node, Traversal::ReturnTypeNode); $pager->setPageSize(1) ->setLeaseTime(30); $data = array( // First results page array( array( "self" => "http://localhost:7474/db/data/node/2", "data" => array( "name" => "foo", ), ), ), // Second results page array( array( "self" => "http://localhost:7474/db/data/node/3", "data" => array( "name" => "bar", ), ), ), ); $this->transport->expects($this->at(0)) ->method('post') ->with('/node/1/paged/traverse/node?pageSize=1&leaseTime=30',array("order" => "depth_first")) ->will($this->returnValue(array("code"=>200,"data"=>$data[0],"headers"=>array('Location' => "http://localhost:7474/db/data/node/1/paged/traverse/node/a1b2c3")))); $this->transport->expects($this->at(1)) ->method('get') ->with('/node/1/paged/traverse/node/a1b2c3', null) ->will($this->returnValue(array("code"=>200,"data"=>$data[1]))); $this->transport->expects($this->at(2)) ->method('get') ->with('/node/1/paged/traverse/node/a1b2c3', null) ->will($this->returnValue(array("code"=>404))); $result = $this->client->executePagedTraversal($pager); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]); $this->assertEquals(2, $result[0]->getId()); $this->assertEquals('foo', $result[0]->getProperty('name')); $result = $this->client->executePagedTraversal($pager); $this->assertEquals(1, count($result)); $this->assertInstanceOf('Everyman\Neo4j\Node', $result[0]); $this->assertEquals(3, $result[0]->getId()); $this->assertEquals('bar', $result[0]->getProperty('name')); $result = $this->client->executePagedTraversal($pager); $this->assertNull($result); } public function testPagedTraversal_ServerReturnsError_ThrowsException() { $traversal = new Traversal($this->client); $traversal->setOrder(Traversal::OrderDepthFirst); $node = new Node($this->client); $node->setId(1); $pager = new Pager($traversal, $node, Traversal::ReturnTypeNode); $pager->setPageSize(1) ->setLeaseTime(30); $this->transport->expects($this->once()) ->method('post') ->with('/node/1/paged/traverse/node?pageSize=1&leaseTime=30',array("order" => "depth_first")) ->will($this->returnValue(array("code"=>400))); $this->setExpectedException('Everyman\Neo4j\Exception'); $result = $this->client->executePagedTraversal($pager); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Cypher/QueryTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->template = 'START a=({start}) RETURN a'; $this->vars = array('start' => 0); $this->query = new Query($this->client, $this->template, $this->vars); } public function testGetQuery_ReturnsString() { $result = $this->query->getQuery(); $this->assertEquals($result, $this->template); } public function testGetParameters_ReturnsArray() { $result = $this->query->getParameters(); $this->assertEquals($result, $this->vars); } public function testGetResultSet_OnlyExecutesOnce_ReturnsResultSet() { $return = $this->getMock('Everyman\Neo4j\Query\ResultSet', array(), array(), '', false); $this->client->expects($this->once()) ->method('executeCypherQuery') ->will($this->returnValue($return)); $this->assertSame($return, $this->query->getResultSet()); $this->assertSame($return, $this->query->getResultSet()); } public function testGetResultSet_ClientReturnsFalse_ReturnsFalse() { $return = false; $this->client->expects($this->once()) ->method('executeCypherQuery') ->will($this->returnValue($return)); $this->assertFalse($this->query->getResultSet()); $this->assertFalse($this->query->getResultSet()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/EntityMapperTest.php ================================================ getMock('Everyman\Neo4j\Transport'); $this->client = new Client($transport); $this->mapper = new EntityMapper($this->client); } public function testGetIdFromUri_UriGiven_ReturnsInteger() { $uri = 'http://localhost:7474/db/data/node/1'; $this->assertEquals(1, $this->mapper->getIdFromUri($uri)); } public function testMakeNode_NodeDataGiven_ReturnsNode() { $data = array( 'data' => array( 'name' => 'Bob' ), 'self' => 'http://localhost:7474/db/data/node/1', ); $node = $this->mapper->makeNode($data); $this->assertInstanceOf('Everyman\Neo4j\Node', $node); $this->assertEquals(1, $node->getId()); $this->assertEquals('Bob', $node->getProperty('name')); } public function testMakeRelationship_RelationshipDataGiven_ReturnsRelationship() { $data = array( 'data' => array( 'name' => 'Bob' ), 'type' => 'KNOWS', 'start' => 'http://localhost/db/data/node/1', 'end' => 'http://localhost/db/data/node/2', 'self' => 'http://localhost:7474/db/data/relationship/3', ); $rel = $this->mapper->makeRelationship($data); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rel); $this->assertEquals(3, $rel->getId()); $this->assertEquals('KNOWS', $rel->getType()); $this->assertEquals('Bob', $rel->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $rel->getStartNode()); $this->assertInstanceOf('Everyman\Neo4j\Node', $rel->getEndNode()); $this->assertEquals(1, $rel->getStartNode()->getId()); $this->assertEquals(2, $rel->getEndNode()->getId()); } public function testPopulateNode_NodeGiven_ReturnsNode() { $data = array( 'data' => array( 'name' => 'Bob' ), ); $node = new Node($this->client); $this->mapper->populateNode($node, $data); $this->assertEquals('Bob', $node->getProperty('name')); } public function testPopulateRelationship_RelationshipGiven_ReturnsRelationship() { $data = array( 'data' => array( 'name' => 'Bob' ), 'type' => 'KNOWS', 'start' => 'http://localhost/db/data/node/1', 'end' => 'http://localhost/db/data/node/2', ); $rel = new Relationship($this->client); $this->mapper->populateRelationship($rel, $data); $this->assertEquals('KNOWS', $rel->getType()); $this->assertEquals('Bob', $rel->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $rel->getStartNode()); $this->assertInstanceOf('Everyman\Neo4j\Node', $rel->getEndNode()); $this->assertEquals(1, $rel->getStartNode()->getId()); $this->assertEquals(2, $rel->getEndNode()->getId()); } public function testPopulatePath_PathGiven_ReturnsPath() { $data = array( "nodes" => array("http://localhost:7474/db/data/node/123", "http://localhost:7474/db/data/node/341", "http://localhost:7474/db/data/node/456"), "relationships" => array("http://localhost:7474/db/data/relationship/564", "http://localhost:7474/db/data/relationship/32"), ); $path = new Path($this->client); $this->mapper->populatePath($path, $data); $rels = $path->getRelationships(); $this->assertEquals(2, count($rels)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[0]); $this->assertEquals(564, $rels[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[1]); $this->assertEquals(32, $rels[1]->getId()); $nodes = $path->getNodes(); $this->assertEquals(3, count($nodes)); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); $this->assertEquals(123, $nodes[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); $this->assertEquals(341, $nodes[1]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[2]); $this->assertEquals(456, $nodes[2]->getId()); } public function testPopulatePath_FullPath_ReturnsPath() { $data = array( "relationships" => array( array( "self" => "http://localhost:7474/db/data/relationship/2", "start" => "http://localhost:7474/db/data/node/1", "end" => "http://localhost:7474/db/data/node/3", "type" => "FOOTYPE", "data" => array( "name" => "baz", ), ), ), "nodes" => array( array( "self" => "http://localhost:7474/db/data/node/1", "data" => array( "name" => "foo", ), ), array( "self" => "http://localhost:7474/db/data/node/3", "data" => array( "name" => "bar", ), ), ), ); $path = new Path($this->client); $this->mapper->populatePath($path, $data, true); $rels = $path->getRelationships(); $this->assertEquals(1, count($rels)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[0]); $this->assertEquals(2, $rels[0]->getId()); $this->assertEquals('FOOTYPE', $rels[0]->getType()); $this->assertEquals('baz', $rels[0]->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $rels[0]->getStartNode()); $this->assertInstanceOf('Everyman\Neo4j\Node', $rels[0]->getEndNode()); $this->assertEquals(1, $rels[0]->getStartNode()->getId()); $this->assertEquals(3, $rels[0]->getEndNode()->getId()); $nodes = $path->getNodes(); $this->assertEquals(2, count($nodes)); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); $this->assertEquals(1, $nodes[0]->getId()); $this->assertEquals('foo', $nodes[0]->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); $this->assertEquals(3, $nodes[1]->getId()); $this->assertEquals('bar', $nodes[1]->getProperty('name')); } public function testGetEntityFor_RelationshipData_ReturnsRelationship() { $data = array( 'data' => array( 'name' => 'Bob' ), 'type' => 'KNOWS', 'start' => 'http://localhost/db/data/node/1', 'end' => 'http://localhost/db/data/node/2', 'self' => 'http://localhost/db/data/relationship/0' ); $rel = $this->mapper->getEntityFor($data); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rel); $this->assertEquals(0, $rel->getId()); $this->assertEquals('KNOWS', $rel->getType()); $this->assertEquals('Bob', $rel->getProperty('name')); $this->assertInstanceOf('Everyman\Neo4j\Node', $rel->getStartNode()); $this->assertInstanceOf('Everyman\Neo4j\Node', $rel->getEndNode()); $this->assertEquals(1, $rel->getStartNode()->getId()); $this->assertEquals(2, $rel->getEndNode()->getId()); } public function testGetEntityFor_NodeData_ReturnsNode() { $data = array( 'data' => array( 'name' => 'Bob' ), 'self' => 'http://localhost/db/data/node/0' ); $node = $this->mapper->getEntityFor($data); $this->assertInstanceOf('Everyman\Neo4j\Node', $node); $this->assertEquals(0, $node->getId()); $this->assertEquals('Bob', $node->getProperty('name')); } public function testGetEntityFor_PathData_ReturnsPath() { $data = array( "relationships" => array( "http://localhost:7474/db/data/relationship/2", ), "nodes" => array( "http://localhost:7474/db/data/node/1", "http://localhost:7474/db/data/node/3", ), ); $path = $this->mapper->getEntityFor($data); $this->assertInstanceOf('Everyman\Neo4j\Path', $path); $this->assertEquals(1, $path->getStartNode()->getId()); $this->assertEquals(3, $path->getEndNode()->getId()); $rels = $path->getRelationships(); $this->assertEquals(1, count($rels)); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rels[0]); $this->assertEquals(2, $rels[0]->getId()); $nodes = $path->getNodes(); $this->assertEquals(2, count($nodes)); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[0]); $this->assertEquals(1, $nodes[0]->getId()); $this->assertInstanceOf('Everyman\Neo4j\Node', $nodes[1]); $this->assertEquals(3, $nodes[1]->getId()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/GeoffTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array('runCommand')); $this->geoff = new Geoff($this->client); } public function testLoad_NotAStreamOrString_ThrowsException() { $geoffString = 123; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_IgnoreEmptyLines_ReturnsBatch() { $geoffString = "\n \n\t\n \n \n"; $batch = $this->geoff->load($geoffString); self::assertEquals(0, count($batch->getOperations())); } public function testLoad_IgnoreCommentLines_ReturnsBatch() { $geoffString = "#this is a comment\n" . " #so is this\n" . "# this too \n"; $batch = $this->geoff->load($geoffString); self::assertEquals(0, count($batch->getOperations())); } public function testLoad_LoadNodeLines_ReturnsBatch() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Phil) {"name": "Philip", "title": "Duke of Edinburgh", "birth.date": "1921-06-21"}'.PHP_EOL . '(Chaz)'; $batch = $this->geoff->load($geoffString); $ops = $batch->getOperations(); self::assertEquals(3, count($ops)); self::assertInstanceOf('Everyman\Neo4j\Batch\Save', $ops[0]); self::assertInstanceOf('Everyman\Neo4j\Node', $ops[0]->getEntity()); self::assertFalse($ops[0]->getEntity()->hasId()); self::assertEquals('Elizabeth', $ops[0]->getEntity()->getProperty('name')); self::assertEquals('Queen of the Commonwealth Realms', $ops[0]->getEntity()->getProperty('title')); self::assertEquals('1926-04-21', $ops[0]->getEntity()->getProperty('birth.date')); self::assertInstanceOf('Everyman\Neo4j\Batch\Save', $ops[1]); self::assertInstanceOf('Everyman\Neo4j\Node', $ops[1]->getEntity()); self::assertFalse($ops[1]->getEntity()->hasId()); self::assertEquals('Philip', $ops[1]->getEntity()->getProperty('name')); self::assertEquals('Duke of Edinburgh', $ops[1]->getEntity()->getProperty('title')); self::assertEquals('1921-06-21', $ops[1]->getEntity()->getProperty('birth.date')); self::assertInstanceOf('Everyman\Neo4j\Batch\Save', $ops[2]); self::assertInstanceOf('Everyman\Neo4j\Node', $ops[2]->getEntity()); self::assertFalse($ops[2]->getEntity()->hasId()); self::assertEquals(array(), $ops[2]->getEntity()->getProperties()); } public function testLoad_DuplicateNodeLines_ThrowsException() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_RelationshipEndpointsDefined_ReturnsBatch() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Phil) {"name": "Philip", "title": "Duke of Edinburgh", "birth.date": "1921-06-21"}'.PHP_EOL . '(Chaz) {"name": "Charles", "title": "Prince of Wales", "birth.date": "1948-11-14"}'.PHP_EOL . '(Liz)-[:MARRIED]->(Phil) {"marriage.place": "Westminster Abbey", "marriage.date": "1947-11-20"}'.PHP_EOL . '(Phil)-[:FATHER_OF]->(Chaz)'; $batch = $this->geoff->load($geoffString); $ops = $batch->getOperations(); self::assertEquals(5, count($ops)); $op = $ops[3]; self::assertInstanceOf('Everyman\Neo4j\Batch\Save', $op); self::assertInstanceOf('Everyman\Neo4j\Relationship', $op->getEntity()); self::assertFalse($op->getEntity()->hasId()); self::assertSame($ops[0]->getEntity(), $op->getEntity()->getStartNode()); self::assertSame($ops[1]->getEntity(), $op->getEntity()->getEndNode()); self::assertEquals('MARRIED', $op->getEntity()->getType()); self::assertEquals('Westminster Abbey', $op->getEntity()->getProperty('marriage.place')); self::assertEquals('1947-11-20', $op->getEntity()->getProperty('marriage.date')); $op = $ops[4]; self::assertInstanceOf('Everyman\Neo4j\Batch\Save', $op); self::assertInstanceOf('Everyman\Neo4j\Relationship', $op->getEntity()); self::assertFalse($op->getEntity()->hasId()); self::assertSame($ops[1]->getEntity(), $op->getEntity()->getStartNode()); self::assertSame($ops[2]->getEntity(), $op->getEntity()->getEndNode()); self::assertEquals('FATHER_OF', $op->getEntity()->getType()); self::assertEquals(array(), $op->getEntity()->getProperties()); } public function testLoad_RelationshipUndefinedStart_ThrowsException() { $geoffString = '(Chaz) {"name": "Charles", "title": "Prince of Wales", "birth.date": "1948-11-14"}'.PHP_EOL . '(Phil)-[:FATHER_OF]->(Chaz)'; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_RelationshipUndefinedEnd_ThrowsException() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Liz)-[:MARRIED]->(Phil) {"marriage.place": "Westminster Abbey", "marriage.date": "1947-11-20"}'; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_DuplicateRelationshipLines_ThrowsException() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Phil) {"name": "Philip", "title": "Duke of Edinburgh", "birth.date": "1921-06-21"}'.PHP_EOL . '(Liz)-[LizNPhil:MARRIED]->(Phil)'.PHP_EOL . '(Liz)-[LizNPhil:MARRIED]->(Phil)'; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_IndexLines_ReturnsBatch() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Phil) {"name": "Philip", "title": "Duke of Edinburgh", "birth.date": "1921-06-21"}'.PHP_EOL . '(Liz)-[LizNPhil:MARRIED]->(Phil) {"marriage.place": "Westminster Abbey", "marriage.date": "1947-11-20"}'.PHP_EOL . '{People}->(Liz) {"name": "Elizabeth"}'.PHP_EOL . '{People}->(Phil) {"name": "Philip", "title":"Duke"}'.PHP_EOL . '{Marriages}->[LizNPhil] {"wife": "Elizabeth", "husband": "Philip"}'; $batch = $this->geoff->load($geoffString); $ops = $batch->getOperations(); self::assertEquals(8, count($ops)); $op = $ops[3]; self::assertInstanceOf('Everyman\Neo4j\Batch\AddTo', $op); self::assertInstanceOf('Everyman\Neo4j\Node', $op->getEntity()); self::assertEquals('Elizabeth', $op->getEntity()->getProperty('name')); self::assertInstanceOf('Everyman\Neo4j\Index', $op->getIndex()); self::assertEquals('People', $op->getIndex()->getName()); self::assertEquals(Index::TypeNode, $op->getIndex()->getType()); self::assertEquals('name', $op->getKey()); self::assertEquals('Elizabeth', $op->getValue()); $op = $ops[4]; self::assertInstanceOf('Everyman\Neo4j\Batch\AddTo', $op); self::assertInstanceOf('Everyman\Neo4j\Node', $op->getEntity()); self::assertEquals('Philip', $op->getEntity()->getProperty('name')); self::assertInstanceOf('Everyman\Neo4j\Index', $op->getIndex()); self::assertEquals('People', $op->getIndex()->getName()); self::assertEquals(Index::TypeNode, $op->getIndex()->getType()); self::assertEquals('name', $op->getKey()); self::assertEquals('Philip', $op->getValue()); $op = $ops[5]; self::assertInstanceOf('Everyman\Neo4j\Batch\AddTo', $op); self::assertInstanceOf('Everyman\Neo4j\Node', $op->getEntity()); self::assertEquals('Philip', $op->getEntity()->getProperty('name')); self::assertInstanceOf('Everyman\Neo4j\Index', $op->getIndex()); self::assertEquals('People', $op->getIndex()->getName()); self::assertEquals(Index::TypeNode, $op->getIndex()->getType()); self::assertEquals('title', $op->getKey()); self::assertEquals('Duke', $op->getValue()); self::assertSame($ops[4]->getEntity(), $ops[5]->getEntity()); $op = $ops[6]; self::assertInstanceOf('Everyman\Neo4j\Batch\AddTo', $op); self::assertInstanceOf('Everyman\Neo4j\Relationship', $op->getEntity()); self::assertSame($ops[2]->getEntity(), $op->getEntity()); self::assertInstanceOf('Everyman\Neo4j\Index', $op->getIndex()); self::assertEquals('Marriages', $op->getIndex()->getName()); self::assertEquals(Index::TypeRelationship, $op->getIndex()->getType()); self::assertEquals('wife', $op->getKey()); self::assertEquals('Elizabeth', $op->getValue()); $op = $ops[7]; self::assertInstanceOf('Everyman\Neo4j\Batch\AddTo', $op); self::assertInstanceOf('Everyman\Neo4j\Relationship', $op->getEntity()); self::assertSame($ops[2]->getEntity(), $op->getEntity()); self::assertInstanceOf('Everyman\Neo4j\Index', $op->getIndex()); self::assertEquals('Marriages', $op->getIndex()->getName()); self::assertEquals(Index::TypeRelationship, $op->getIndex()->getType()); self::assertEquals('husband', $op->getKey()); self::assertEquals('Philip', $op->getValue()); } public function testLoad_IndexLinesInvalidNode_ThrowsException() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '{People}->(Phil) {"name": "Philip", "title":"Duke"}'; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_IndexLinesInvalidRelationship_ThrowsException() { $geoffString = '{Marriages}->[LizNPhil] {"wife": "Elizabeth", "husband": "Philip"}'; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_IndexBracketMismatch_ThrowsException() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Phil) {"name": "Philip", "title": "Duke of Edinburgh", "birth.date": "1921-06-21"}'.PHP_EOL . '(Liz)-[LizNPhil:MARRIED]->(Phil) {"marriage.place": "Westminster Abbey", "marriage.date": "1947-11-20"}'.PHP_EOL . '{Marriages}->[LizNPhil) {"wife": "Elizabeth", "husband": "Philip"}'; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_InvalidLine_ThrowsException() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . 'this line is total gibberish'.PHP_EOL . '{People}->(Liz) {"name": "Elizabeth"}'; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->load($geoffString); } public function testLoad_UseTheSameBatch_ReturnsBatch() { $geoffString = '(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}'.PHP_EOL . '(Phil) {"name": "Philip", "title": "Duke of Edinburgh", "birth.date": "1921-06-21"}'.PHP_EOL . '(Chaz)'; $initBatch = new Batch($this->client); $batch = $this->geoff->load($geoffString, $initBatch); self::assertSame($initBatch, $batch); $ops = $batch->getOperations(); self::assertEquals(3, count($ops)); $batch2 = $this->geoff->load($geoffString, $batch); self::assertSame($batch, $batch2); $ops = $batch->getOperations(); self::assertEquals(6, count($ops)); } public function testDump_PathsGiven_NoFileDescriptor_ReturnsString() { $nodeA = new Node($this->client); $nodeA->setId(123)->setProperties(array('foo' => 'bar','baz' => 'qux')); $nodeB = new Node($this->client); $nodeB->setId(456)->setProperties(array('somekey' => 'somevalue')); $nodeC = new Node($this->client); $nodeC->setId(789); $relA = new Relationship($this->client); $relA->setId(987)->setType('TEST') ->setStartNode($nodeA)->setEndNode($nodeB) ->setProperties(array('anotherkey' => 'anothervalue')); $relB = new Relationship($this->client); $relB->setId(654)->setType('TSET') ->setStartNode($nodeB)->setEndNode($nodeC); $path = new Path(); $path->appendNode($nodeA); $path->appendNode($nodeB); $path->appendNode($nodeC); $path->appendRelationship($relA); $path->appendRelationship($relB); $expected =<<(456) {"anotherkey":"anothervalue"} (456)-[654:TSET]->(789) GEOFF; $result = $this->geoff->dump($path); self::assertEquals($expected, $result); } public function testDump_PathsGiven_FileDescriptor_ReturnsDescriptor() { $nodeA = new Node($this->client); $nodeA->setId(123)->setProperties(array('foo' => 'bar','baz' => 'qux')); $nodeB = new Node($this->client); $nodeB->setId(456)->setProperties(array('somekey' => 'somevalue')); $relA = new Relationship($this->client); $relA->setId(987)->setType('TEST') ->setStartNode($nodeA)->setEndNode($nodeB) ->setProperties(array('anotherkey' => 'anothervalue')); $path = new Path(); $path->appendNode($nodeA); $path->appendNode($nodeB); $path->appendRelationship($relA); $expected =<<(456) {"anotherkey":"anothervalue"} GEOFF; $handle = fopen('data:text/plain,', 'w+'); $resultHandle = $this->geoff->dump($path, $handle); self::assertSame($handle, $resultHandle); self::assertEquals($expected, stream_get_contents($resultHandle, -1, 0)); } public function testDump_NotAStreamOrString_ThrowsException() { $handle = 123; $path = new Path(); $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->dump($path, $handle); } public function testDump_NotAPath_ThrowsException() { $handle = "file"; $notPath = "blah"; $this->setExpectedException('Everyman\Neo4j\Exception'); $batch = $this->geoff->dump($notPath); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Gremlin/QueryTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->queryString = 'i = g.v(start);i.outE.inV'; $this->params = array('start' => 123); $this->query = new Query($this->client, $this->queryString, $this->params); } public function testGetQuery_ReturnsString() { $result = $this->query->getQuery(); $this->assertEquals($result, $this->queryString); } public function testGetParameters_ReturnsArray() { $result = $this->query->getParameters(); $this->assertEquals($result, $this->params); } public function testGetResultSet_OnlyExecutesOnce_ReturnsResultSet() { $return = $this->getMock('Everyman\Neo4j\Query\ResultSet', array(), array(), '', false); $this->client->expects($this->once()) ->method('executeGremlinQuery') ->will($this->returnValue($return)); $this->assertSame($return, $this->query->getResultSet()); $this->assertSame($return, $this->query->getResultSet()); } public function testGetResultSet_ClientReturnsFalse_ReturnsFalse() { $return = false; $this->client->expects($this->once()) ->method('executeGremlinQuery') ->will($this->returnValue($return)); $this->assertFalse($this->query->getResultSet()); $this->assertFalse($this->query->getResultSet()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/IndexTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->index = new Index($this->client, Index::TypeNode, 'indexname'); } public function testSave_SavesSelfUsingClient() { $this->client->expects($this->once()) ->method('saveIndex') ->with($this->index) ->will($this->returnValue(true)); $this->assertTrue($this->index->save()); } public function testDelete_DeletesSelfUsingClient() { $this->client->expects($this->once()) ->method('deleteIndex') ->with($this->index) ->will($this->returnValue(true)); $this->assertTrue($this->index->delete()); } public function testAdd_AddsEntityUsingClient() { $node = new Node($this->client); $this->client->expects($this->once()) ->method('addToIndex') ->with($this->index, $node, 'somekey', 'somevalue') ->will($this->returnValue(true)); $this->assertTrue($this->index->add($node, 'somekey', 'somevalue')); } public function testRemove_RemovesEntityUsingClient() { $node = new Node($this->client); $this->client->expects($this->once()) ->method('removeFromIndex') ->with($this->index, $node, 'somekey', 'somevalue') ->will($this->returnValue(true)); $this->assertTrue($this->index->remove($node, 'somekey', 'somevalue')); } public function testFind_FindsNodesUsingClient() { $node = new Node($this->client); $this->client->expects($this->once()) ->method('searchIndex') ->with($this->index, 'somekey', 'somevalue') ->will($this->returnValue(array($node))); $result = $this->index->find('somekey', 'somevalue'); $this->assertEquals(1, count($result)); $this->assertSame($node, $result[0]); } public function testFindOne_FindsNodesUsingClient() { $node = new Node($this->client); $nodes = array($node, new Node($this->client)); $this->client->expects($this->once()) ->method('searchIndex') ->with($this->index, 'somekey', 'somevalue') ->will($this->returnValue($nodes)); $result = $this->index->findOne('somekey', 'somevalue'); $this->assertSame($node, $result); } public function testFindOne_NoNode_ReturnsNull() { $this->client->expects($this->once()) ->method('searchIndex') ->with($this->index, 'somekey', 'somevalue') ->will($this->returnValue(array())); $result = $this->index->findOne('somekey', 'somevalue'); $this->assertNull($result); } public function testQuery_QueriesUsingClient() { $node = new Node($this->client); $this->client->expects($this->once()) ->method('queryIndex') ->with($this->index, 'somekey:somevalue*') ->will($this->returnValue(array($node))); $result = $this->index->query('somekey:somevalue*'); $this->assertEquals(1, count($result)); $this->assertSame($node, $result[0]); } public function testQueryOne_QueriesUsingClient() { $node = new Node($this->client); $nodes = array($node, new Node($this->client)); $this->client->expects($this->once()) ->method('queryIndex') ->with($this->index, 'somekey:somevalue*') ->will($this->returnValue($nodes)); $result = $this->index->queryOne('somekey:somevalue*'); $this->assertSame($node, $result); } public function testQueryOne_NoNode_ReturnsNull() { $this->client->expects($this->once()) ->method('queryIndex') ->with($this->index, 'somekey:somevalue*') ->will($this->returnValue(array())); $result = $this->index->queryOne('somekey:somevalue*'); $this->assertNull($result); } public function testNodeIndex_CreatesNodeIndex() { $index = new Index\NodeIndex($this->client, 'testindex', array('foo'=>'bar')); $this->assertEquals(Index::TypeNode, $index->getType()); $this->assertEquals('testindex', $index->getName()); $this->assertEquals(array('foo'=>'bar'), $index->getConfig()); } public function testNodeFulltextIndex_CreatesNodeFulltextIndex() { $index = new Index\NodeFulltextIndex($this->client, 'testindex'); $this->assertEquals(Index::TypeNode, $index->getType()); $this->assertEquals('testindex', $index->getName()); $this->assertEquals(array( 'type'=>'fulltext', 'provider'=>'lucene', ), $index->getConfig()); } public function testRelationshipIndex_CreatesRelationshipIndex() { $index = new Index\RelationshipIndex($this->client, 'testindex', array('foo'=>'bar')); $this->assertEquals(Index::TypeRelationship, $index->getType()); $this->assertEquals('testindex', $index->getName()); $this->assertEquals(array('foo'=>'bar'), $index->getConfig()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/LabelTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client'); } public function dataProvider_ValidNames() { return array( array('TEST LABEL NAME'), array(123), array(123.45), ); } /** * @dataProvider dataProvider_ValidNames */ public function testContruct_ValidNameGiven_SetsNameCastAsString($name) { $label = new Label($this->client, $name); self::assertEquals($name, $label->getName()); self::assertInternalType('string', $label->getName()); } public function dataProvider_InvalidNames() { return array( array(null), array(''), array(true), array(array()), array(array('foo')), array(new \stdClass()), ); } /** * @dataProvider dataProvider_InvalidNames */ public function testContruct_InvalidNameGiven_ThrowsException($name) { $this->setExpectedException('InvalidArgumentException'); $label = new Label($this->client, $name); } public function testGetNodes_NoPropertyGiven_CallsClientMethod() { $label = new Label($this->client, 'foobar'); $this->client->expects($this->once()) ->method('getNodesForLabel') ->with($label, null, null); $label->getNodes(); } public function testGetNodes_PropertyGiven_CallsClientMethod() { $label = new Label($this->client, 'foobar'); $property = 'baz'; $value = 'qux'; $this->client->expects($this->once()) ->method('getNodesForLabel') ->with($label, $property, $value); $label->getNodes($property, $value); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/NodeTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array( 'saveNode', 'deleteNode', 'addLabels', 'removeLabels', 'getLabels', 'loadNode', 'getNodeRelationships', 'runCommand', )); $this->node = new Node($this->client); } public function testSave_SavesSelfUsingClient() { $expected = $this->node; $matched = false; $this->client->expects($this->once()) ->method('saveNode') // Have to do it this way because PHPUnit clones object parameters ->will($this->returnCallback(function (Node $actual) use ($expected, &$matched) { $matched = $expected->getId() == $actual->getId(); return true; })); $this->node->setId(123); $this->assertSame($this->node, $this->node->save()); $this->assertTrue($matched); } public function testGetLabels_DelegatesToClient() { $expected = $this->node; $matched = false; $label = new Label($this->client, 'FOOBAR'); $this->client->expects($this->once()) ->method('getLabels') // Have to do it this way because PHPUnit clones object parameters ->will($this->returnCallback(function (Node $actual) use ($expected, $label, &$matched) { $matched = $expected->getId() == $actual->getId(); return array($label); })); $labels = $this->node->getLabels(); $this->assertEquals(1, count($labels)); $this->assertSame($label, $labels[0]); } public function testAddLabels_DelegatesToClient() { $expected = $this->node; $expected->setId(123); $matched = false; $label = new Label($this->client, 'FOOBAR'); $this->client->expects($this->once()) ->method('addLabels') // Have to do it this way because PHPUnit clones object parameters ->will($this->returnCallback(function (Node $actual, $labels) use ($expected, $label, &$matched) { $matched = $expected->getId() == $actual->getId(); $matched = $matched && $label->getName() == $labels[0]->getName(); return array($label); })); $labels = $this->node->addLabels(array($label)); $this->assertEquals(1, count($labels)); $this->assertSame($label, $labels[0]); } public function testRemoveLabels_DelegatesToClient() { $expected = $this->node; $expected->setId(123); $matched = false; $label = new Label($this->client, 'FOOBAR'); $this->client->expects($this->once()) ->method('removeLabels') // Have to do it this way because PHPUnit clones object parameters ->will($this->returnCallback(function (Node $actual, $labels) use ($expected, $label, &$matched) { $matched = $expected->getId() == $actual->getId(); $matched = $matched && $label->getName() == $labels[0]->getName(); return array($label); })); $labels = $this->node->removeLabels(array($label)); $this->assertEquals(1, count($labels)); $this->assertSame($label, $labels[0]); } /** * Test for https://github.com/jadell/neo4jphp/issues/58 */ public function testSave_FollowedByPropertyGet_DoesNotLazyLoad() { $this->client->expects($this->once()) ->method('saveNode') ->will($this->returnValue(true)); $this->client->expects($this->never()) ->method('loadNode'); $this->node->setId(123); $this->node->save(); $this->node->getProperty('foo'); } public function testDelete_DeletesSelfUsingClient() { $this->client->expects($this->once()) ->method('deleteNode') ->with($this->node) ->will($this->returnValue(true)); $this->assertSame($this->node, $this->node->delete()); } public function testLoad_LoadsSelfUsingClient() { $this->client->expects($this->once()) ->method('loadNode') ->with($this->node) ->will($this->returnValue(true)); $this->assertSame($this->node, $this->node->load()); } public function testGetRelationships_ReturnsArrayOfRelationships() { $dir = Relationship::DirectionOut; $types = array('FOOTYPE','BARTYPE'); $returnRels = array( new Relationship($this->client), new Relationship($this->client), ); $this->client->expects($this->once()) ->method('getNodeRelationships') ->with($this->node, $types, $dir) ->will($this->returnValue($returnRels)); $rels = $this->node->getRelationships($types, $dir); $this->assertEquals($returnRels, $rels); } public function testGetFirstRelationship_ReturnsRelationship() { $dir = Relationship::DirectionOut; $types = array('FOOTYPE','BARTYPE'); $returnRels = array( new Relationship($this->client), new Relationship($this->client), ); $this->client->expects($this->once()) ->method('getNodeRelationships') ->with($this->node, $types, $dir) ->will($this->returnValue($returnRels)); $rel = $this->node->getFirstRelationship($types, $dir); $this->assertSame($returnRels[0], $rel); } public function testGetFirstRelationship_NoneFound_ReturnsNull() { $dir = Relationship::DirectionOut; $types = array('FOOTYPE','BARTYPE'); $returnRels = array(); $this->client->expects($this->once()) ->method('getNodeRelationships') ->with($this->node, $types, $dir) ->will($this->returnValue($returnRels)); $rel = $this->node->getFirstRelationship($types, $dir); $this->assertNull($rel); } public function testRelateTo_ReturnsRelationship() { $toNode = new Node($this->client); $type = 'FOOTYPE'; $rel = $this->node->relateTo($toNode, $type); $this->assertInstanceOf('Everyman\Neo4j\Relationship', $rel); $this->assertSame($this->client, $rel->getClient()); $this->assertSame($this->node, $rel->getStartNode()); $this->assertSame($toNode, $rel->getEndNode()); $this->assertEquals($type, $rel->getType()); } public function testFindPathsTo_ReturnsPathFinder() { $toNode = new Node($this->client); $type = 'FOOTYPE'; $dir = Relationship::DirectionOut; $finder = $this->node->findPathsTo($toNode, $type, $dir); $this->assertInstanceOf('Everyman\Neo4j\PathFinder', $finder); $this->assertSame($this->node, $finder->getStartNode()); $this->assertSame($toNode, $finder->getEndNode()); $this->assertEquals($dir, $finder->getDirection()); $this->assertEquals($type, $finder->getType()); } public function testSerialize_KeepsLabels() { $fooLabel = $this->client->makeLabel('foo'); $barLabel = $this->client->makeLabel('bar'); $expectedLabels = array($fooLabel, $barLabel); $this->client->expects($this->once()) ->method('addLabels') ->with($this->node, $expectedLabels) ->will($this->returnValue($expectedLabels)); $this->node->addLabels($expectedLabels); $data = serialize($this->node); $node = unserialize($data); // we must reset the client $node->setClient($this->client); $this->assertEquals($this->node, $node, 'The node is restored by unserialize'); $this->assertEquals($expectedLabels, $node->getLabels(), 'The labels should be restored by unserialize'); $this->assertSame($this->client, $expectedLabels[0]->getClient(), 'The labels should have their client set'); $this->assertSame($this->client, $expectedLabels[1]->getClient(), 'The labels should have their client set'); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/PagerTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->traversal = new Traversal($this->client); $this->node = new Node($this->client); $this->node->setId(123); $this->returnType = Traversal::ReturnTypeNode; $this->pager = new Pager($this->traversal, $this->node, $this->returnType); } public function testConstruct_SetsParametersCorrectly_ReturnsCorrectValues() { $this->assertSame($this->traversal, $this->pager->getTraversal()); $this->assertSame($this->node, $this->pager->getStartNode()); $this->assertEquals($this->returnType, $this->pager->getReturnType()); } public function testPageSize_NoneGiven_ReturnsNull() { $this->assertNull($this->pager->getPageSize()); } public function testPageSize_PageSizeGiven_ReturnsInteger() { $this->pager->setPageSize(10); $this->assertEquals(10, $this->pager->getPageSize()); } public function testLeaseTime_NoneGiven_ReturnsNull() { $this->assertNull($this->pager->getLeaseTime()); } public function testLeaseTime_LeaseTimeGiven_ReturnsInteger() { $this->pager->setLeaseTime(30); $this->assertEquals(30, $this->pager->getLeaseTime()); } public function testId_NoneGiven_ReturnsNull() { $this->assertNull($this->pager->getId()); } public function testId_IdGiven_ReturnsString() { $this->pager->setId('thisistheid'); $this->assertEquals('thisistheid', $this->pager->getId()); } public function testGetNextResults_PassesThroughToClient() { $expectedNodes = array(new Node($this->client), new Node($this->client)); $this->client->expects($this->once()) ->method('executePagedTraversal') ->with($this->pager) ->will($this->returnValue($expectedNodes)); $nodes = $this->pager->getNextResults(); $this->assertEquals($expectedNodes, $nodes); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/PathFinderTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->finder = new PathFinder($this->client); } public function testGetClient_ClientSetCorrectly_ReturnsClient() { $this->assertSame($this->client, $this->finder->getClient()); } public function testGetPaths_PassesThroughToClient() { $expectedPaths = array(new Path($this->client), new Path($this->client)); $this->client->expects($this->once()) ->method('getPaths') ->with($this->finder) ->will($this->returnValue($expectedPaths)); $paths = $this->finder->getPaths(); $this->assertEquals($expectedPaths, $paths); } public function testGetSinglePath_PassesThroughToClient() { $firstPath = new Path($this->client); $expectedPaths = array($firstPath, new Path($this->client)); $this->client->expects($this->once()) ->method('getPaths') ->with($this->finder) ->will($this->returnValue($expectedPaths)); $path = $this->finder->getSinglePath(); $this->assertEquals($firstPath, $path); } public function testGetSinglePath_NoPaths_ReturnsNull() { $this->client->expects($this->once()) ->method('getPaths') ->with($this->finder) ->will($this->returnValue(array())); $path = $this->finder->getSinglePath(); $this->assertNull($path); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/PathTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->path = new Path($this->client); $rel = new Relationship($this->client); $rel->setStartNode(new Node($this->client)); $rel->setEndNode(new Node($this->client)); $this->path->appendRelationship($rel); $this->rels[0] = $rel; $rel = new Relationship($this->client); $rel->setStartNode(new Node($this->client)); $rel->setEndNode(new Node($this->client)); $this->path->appendRelationship($rel); $this->rels[1] = $rel; $node = new Node($this->client); $this->path->appendNode($node); $this->nodes[0] = $node; $node = new Node($this->client); $this->path->appendNode($node); $this->nodes[1] = $node; $node = new Node($this->client); $this->path->appendNode($node); $this->nodes[2] = $node; $node = new Node($this->client); $this->path->appendNode($node); $this->nodes[3] = $node; } public function testGetLength_ReturnsInteger() { $this->assertEquals(count($this->nodes), $this->path->getLength()); $this->assertEquals(count($this->nodes), count($this->path)); $this->path->setContext(Path::ContextRelationship); $this->assertEquals(count($this->rels), $this->path->getLength()); $this->assertEquals(count($this->rels), count($this->path)); } public function testEndpoints_ReturnsCorrectNodes() { $this->assertSame($this->nodes[0], $this->path->getStartNode()); $this->assertSame($this->nodes[3], $this->path->getEndNode()); } public function testEndpoints_NoRelationship_ReturnsNull() { $this->path = new Path($this->client); $this->assertNull($this->path->getStartNode()); $this->assertNull($this->path->getEndNode()); } public function testGetRelationships_ReturnsArray() { $rels = $this->path->getRelationships(); $this->assertEquals(count($this->rels), count($rels)); $this->assertSame($this->rels[0], $rels[0]); $this->assertSame($this->rels[1], $rels[1]); } public function testGetNodes_ReturnsArray() { $nodes = $this->path->getNodes(); $this->assertEquals(count($this->nodes), count($nodes)); $this->assertSame($this->nodes[0], $nodes[0]); $this->assertSame($this->nodes[1], $nodes[1]); $this->assertSame($this->nodes[2], $nodes[2]); $this->assertSame($this->nodes[3], $nodes[3]); } public function testIteration_PathCanBeIteratedOver() { $this->assertInstanceOf('Traversable', $this->path); foreach ($this->path as $i => $node) { $this->assertSame($this->nodes[$i], $node); } $this->path->setContext(Path::ContextRelationship); foreach ($this->path as $i => $rel) { $this->assertSame($this->rels[$i], $rel); } } public function testContext_UnknownContextSet_SetsContextToNode() { $this->path->setContext('FOO'); $this->assertEquals(Path::ContextNode, $this->path->getContext()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/PropertyContainerTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->entity = $this->getMock('Everyman\Neo4j\PropertyContainer', array('delete','save','load'), array($this->client)); } public function testProperties_MagicNotSet_ReturnsNull() { $this->assertNull($this->entity->notset); } public function testProperties_MagicSet_ReturnsValue() { $this->entity->somekey = 'someval'; $this->assertEquals('someval', $this->entity->getProperty('somekey')); } public function testProperties_MagicRemoved_ReturnsNull() { $this->entity->setProperty('somekey', 'someval'); unset($this->entity->somekey); $this->assertNull($this->entity->getProperty('somekey')); } public function testProperties_PropertyNotSet_ReturnsNull() { $this->assertNull($this->entity->getProperty('notset')); } public function testProperties_PropertySet_ReturnsValue() { $this->entity->setProperty('somekey','someval'); $this->assertEquals('someval', $this->entity->getProperty('somekey')); } public function testProperties_PropertyRemoved_ReturnsNull() { $this->entity->setProperty('somekey','someval'); $this->entity->removeProperty('somekey'); $this->assertNull($this->entity->getProperty('somekey')); } public function testProperties_BatchSet_ReturnsValues() { $this->entity->setProperties(array( 'somekey' => 'someval', 'yakey' => 'yaval', )); $this->assertEquals('someval', $this->entity->getProperty('somekey')); $this->assertEquals('yaval', $this->entity->getProperty('yakey')); } public function testProperties_GetAllProperties_ReturnsValues() { $this->entity->setProperties(array( 'somekey' => 'someval', 'yakey' => 'yaval', )); $this->assertEquals(array( 'somekey' => 'someval', 'yakey' => 'yaval', ), $this->entity->getProperties()); } public function testProperties_SetPropertyNullValue_ReturnsNullAndPropertyRemoved() { $this->entity->setProperties(array( 'somekey' => 'someval', 'yakey' => 'yaval', )); $this->entity->setProperty('somekey', null); $this->assertNull($this->entity->getProperty('somekey')); $this->assertEquals(array( 'yakey' => 'yaval', ), $this->entity->getProperties()); } public function testProperties_LazyLoad_OnlyLoadsTheFirstTime() { $this->entity->expects($this->once()) ->method('load'); $this->entity->setId(123); $this->entity->getProperties(); $this->entity->getProperties(); } public function testSetGetId_IntegerId_ReturnsInteger() { $this->entity->setId(123); $this->assertTrue($this->entity->hasId()); $this->assertEquals(123, $this->entity->getId()); } public function testSetGetId_ZeroIdIsValid_ReturnsInteger() { $this->entity->setId(0); $this->assertTrue($this->entity->hasId()); $this->assertEquals(0, $this->entity->getId()); } public function testSetGetId_NullValid_ReturnsNull() { $this->entity->setId(null); $this->assertFalse($this->entity->hasId()); $this->assertNull($this->entity->getId()); } public function testSetGetId_NonIntegerCastToInteger_ReturnsInteger() { $this->entity->setId('temp'); $this->assertTrue($this->entity->hasId()); $this->assertEquals(0, $this->entity->getId()); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Query/ResultSetTest.php ================================================ client = new Client($this->getMock('Everyman\Neo4j\Transport')); } public function testCount() { $data = array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14) ) ); $result = new ResultSet($this->client, $data); $this->assertEquals(3, count($result)); } public function testIterate() { $data = array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14) ) ); $result = new ResultSet($this->client, $data); foreach($result as $index => $row) { $this->assertEquals($data['data'][$index][0], $row['name']); $this->assertEquals($data['data'][$index][0], $row[0]); $this->assertTrue($row instanceof Row); } } public function testArrayAccess() { $data = array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14), array('Jimmy', null) ) ); $result = new ResultSet($this->client, $data); for($i=0,$l=4; $i<$l; $i++) { $this->assertEquals(true, isset($result[$i])); $this->assertEquals($data['data'][$i][0], $result[$i][0]); } //issue #83 $this->assertFalse(isset($result[3]['age'])); $this->assertTrue(is_null($result[3]['age'])); $this->assertEquals(null, $result[3]['age']); $this->assertEquals(false, isset($result[4])); } public function testArrayAccess_CacheResultRows() { $data = array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14) ) ); $result = new ResultSet($this->client, $data); $row = $result[0]; $again = $result[0]; $this->assertSame($row, $again); } public function testArrayAccess_Set_ThrowsException() { $data = array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14) ) ); $result = new ResultSet($this->client, $data); $this->setExpectedException('BadMethodCallException'); $result[3] = 'value'; } public function testArrayAccess_Unset_ThrowsException() { $data = array( 'columns' => array('name','age'), 'data' => array( array('Bob', 12), array('Lotta', 0), array('Brenda', 14) ) ); $result = new ResultSet($this->client, $data); $this->setExpectedException('BadMethodCallException'); unset($result[0]); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/Query/RowTest.php ================================================ client = new Client($this->getMock('Everyman\Neo4j\Transport', array(), array(), '', false)); } public function testCount() { $columns = array('name','age'); $data = array('Brenda', 14); $row = new Row($this->client, $columns, $data); $this->assertEquals(2, count($row)); } public function testIterate() { $columns = array('name','age'); $data = array('Brenda', 14); $row = new Row($this->client, $columns, $data); $i = 0; foreach($row as $columnName => $fieldValue) { $this->assertEquals($columns[$i], $columnName); $this->assertEquals($data[$i], $fieldValue); $i++; } } public function testIterateWithNull() { $columns = array('name', 'undefined content', 'age'); $data = array('Brenda', NULL, 14); $row = new Row($this->client, $columns, $data); $i = 0; foreach($row as $columnName => $fieldValue) { $this->assertEquals($columns[$i], $columnName); $this->assertEquals($data[$i], $fieldValue); $i++; } $this->assertEquals(count($columns), $i, 'did not iterate over all data'); } public function testArrayAccess() { $columns = array('name','age'); $data = array('Brenda', 14); $row = new Row($this->client, $columns, $data); $i = 0; foreach($columns as $column) { $this->assertEquals(true, isset($row[$column])); $this->assertEquals(true, isset($row[$i])); $this->assertEquals($row[$column], $data[$i]); $this->assertEquals($row[$i], $data[$i]); $i++; } $this->assertEquals(false, isset($row['blah'])); $this->assertEquals(false, isset($row[3])); } public function testArrayAccess_Set_ThrowsException() { $columns = array('name','age'); $data = array('Brenda', 14); $row = new Row($this->client, $columns, $data); $this->setExpectedException('BadMethodCallException'); $row['test'] = 'value'; } public function testArrayAccess_Unset_ThrowsException() { $columns = array('name','age'); $data = array('Brenda', 14); $row = new Row($this->client, $columns, $data); $this->setExpectedException('BadMethodCallException'); unset($row['name']); } public function testNodeCasting() { $columns = array('user'); $data = array( array( 'data' => array( 'name' => 'Bob' ), 'self' => 'http://localhost/db/data/node/0' )); $row = new Row($this->client, $columns, $data); $i = 0; $this->assertTrue($row['user'] instanceof Node); } public function testRelationshipCasting() { $columns = array('user'); $data = array( array( 'data' => array( 'name' => 'Bob' ), 'type' => 'KNOWS', 'start' => 'http://localhost/db/data/node/0', 'end' => 'http://localhost/db/data/node/1', 'self' => 'http://localhost/db/data/relationship/0' )); $row = new Row($this->client, $columns, $data); $this->assertTrue($row['user'] instanceof Relationship); } public function testValueArray_ReturnsAsANewRowObject() { $columns = array('a', 'b'); $data = array( // 'a' is a node value array( 'data' => array('name' => 'Alice'), 'self' => 'http://localhost/db/data/node/0' ), // 'b' is a collection of node values array( array( 'data' => array('name' => 'Bob'), 'self' => 'http://localhost/db/data/node/1' ), array( 'data' => array('name' => 'Cathy'), 'self' => 'http://localhost/db/data/node/2' ), array( 'data' => array('name' => 'David'), 'self' => 'http://localhost/db/data/node/3' ), ), ); $row = new Row($this->client, $columns, $data); $this->assertInstanceOf('Everyman\Neo4j\Node', $row['a']); $this->assertInstanceOf('Everyman\Neo4j\Query\Row', $row['b']); foreach ($row['b'] as $innerValue) { $this->assertInstanceOf('Everyman\Neo4j\Node', $innerValue); } $this->assertEquals($data[1][1]['data']['name'], $row['b'][1]->getProperty('name')); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/RelationshipTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->relationship = new Relationship($this->client); } public function testSave_SavesSelfUsingClient() { $expected = $this->relationship; $matched = false; $this->client->expects($this->once()) ->method('saveRelationship') // Have to do it this way because PHPUnit clones object parameters ->will($this->returnCallback(function (Relationship $actual) use ($expected, &$matched) { $matched = $expected->getId() == $actual->getId(); return true; })); $this->assertSame($this->relationship, $this->relationship->save()); $this->assertTrue($matched); } /** * Test for https://github.com/jadell/neo4jphp/issues/58 */ public function testSave_FollowedByPropertyGet_DoesNotLazyLoad() { $this->client->expects($this->once()) ->method('saveRelationship') ->will($this->returnValue(true)); $this->client->expects($this->never()) ->method('loadRelationship'); $this->relationship->setId(123); $this->relationship->save(); $this->relationship->getProperty('foo'); } public function testDelete_DeletesSelfUsingClient() { $this->client->expects($this->once()) ->method('deleteRelationship') ->with($this->relationship) ->will($this->returnValue(true)); $this->assertSame($this->relationship, $this->relationship->delete()); } public function testLoad_LoadsSelfUsingClient() { $this->client->expects($this->once()) ->method('loadRelationship') ->with($this->relationship) ->will($this->returnValue(true)); $this->assertSame($this->relationship, $this->relationship->load()); } public function testGetStartNode_NodeNotSet_LazyLoad() { $this->relationship->setId(123); $this->client->expects($this->once()) ->method('loadRelationship'); $this->relationship->getStartNode(); } public function testGetEndNode_NodeNotSet_LazyLoad() { $this->relationship->setId(123); $this->client->expects($this->once()) ->method('loadRelationship'); $this->relationship->getEndNode(); } public function testGetStartAndEndNode_NodesSet_DoesNotLazyLoad() { $startNode = new Node($this->client); $endNode = new Node($this->client); $this->relationship->setId(123); $this->relationship->setStartNode($startNode); $this->relationship->setEndNode($endNode); $this->client->expects($this->never()) ->method('loadRelationship'); $this->assertSame($startNode, $this->relationship->getStartNode()); $this->assertSame($endNode, $this->relationship->getEndNode()); } public function testSerialize_KeepsStartEndAndType() { $expectedStart = new Node($this->client); $expectedStart->setId(123); $expectedEnd = new Node($this->client); $expectedEnd->setId(456); $this->relationship ->setType($this->type) ->setStartNode($expectedStart) ->setEndNode($expectedEnd); // serialize and unserialize $data = serialize($this->relationship); $rel = unserialize($data); // we must reset the client $rel->setClient($this->client); $start = $rel->getStartNode(); $end = $rel->getEndNode(); $this->assertEquals($this->relationship, $rel, 'The relationship is restored by unserialize'); $this->assertEquals($expectedStart, $start, 'The start node should be restored by unserialize'); $this->assertEquals($expectedEnd, $end, 'The end node should be restored by unserialize'); $this->assertEquals($this->type, $rel->getType(), 'The type should be restored by unserialize'); $this->assertEquals($this->client, $start->getClient(), 'The client should be restored in the start node by setClient on the relation'); $this->assertEquals($this->client, $end->getClient(), 'The client should be restored in the end node by setClient on the relation'); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/TransactionTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client'); $this->transaction = new Transaction($this->client); $this->transaction->setId($this->transactionId); } public function testSetId_CorrectlySetsId() { self::assertEquals($this->transactionId, $this->transaction->getId()); } public function testSetId_SameIdSetAgain_CorrectlySetsId() { $result = $this->transaction->setId($this->transactionId); self::assertEquals($this->transactionId, $this->transaction->getId()); self::assertSame($this->transaction, $result); } public function testSetId_DifferentIdSet_ThrowsException() { $idDifferent = $this->transactionId+1000; $this->setExpectedException('InvalidArgumentException', 'new id'); $this->transaction->setId($idDifferent); } public function testCommit_DelegatesToClient() { $this->client->expects($this->once()) ->method('addStatementsToTransaction') ->with($this->transaction, array(), true); $result = $this->transaction->commit(); self::assertSame($this->transaction, $result); self::assertTrue($this->transaction->isClosed()); } public function testCommit_NoId_NoopAndMarksTransactionClosed() { $transaction = new Transaction($this->client); $this->client->expects($this->never()) ->method('addStatementsToTransaction'); $result = $transaction->commit(); self::assertSame($transaction, $result); self::assertTrue($transaction->isClosed()); } public function testCommit_ClosedTransaction_ThrowsException() { $result = $this->transaction->commit(); $this->setExpectedException('\Everyman\Neo4j\Exception', 'already closed'); $this->transaction->commit(); } public function testCommit_ClientException_MarksTransactionClosedAndErrorAndThrowsException() { $exception = new \Everyman\Neo4j\Exception('some client error'); $this->client->expects($this->any()) ->method('addStatementsToTransaction') ->will($this->throwException($exception)); try { $this->transaction->commit(); $this->fail('Expected exception not thrown'); } catch (\Everyman\Neo4j\Exception $e) { self::assertSame($exception, $e); self::assertTrue($this->transaction->isClosed()); self::assertTrue($this->transaction->isError()); } } public function testRollback_DelegatesToClient() { $this->client->expects($this->once()) ->method('rollbackTransaction') ->with($this->transaction); $result = $this->transaction->rollback(); self::assertSame($this->transaction, $result); self::assertTrue($this->transaction->isClosed()); } public function testRollback_NoTransactionId_NoopAndMarksTransactionClosed() { $transaction = new Transaction($this->client); $this->client->expects($this->never()) ->method('rollbackTransaction'); $result = $transaction->rollback(); self::assertSame($transaction, $result); self::assertTrue($transaction->isClosed()); } public function testRollback_ClosedTransaction_ThrowsException() { $result = $this->transaction->commit(); $this->setExpectedException('\Everyman\Neo4j\Exception', 'already closed'); $this->transaction->rollback(); } public function testRollback_ClientException_MarksTransactionClosedAndErrorAndThrowsException() { $exception = new \Everyman\Neo4j\Exception('some client error'); $this->client->expects($this->any()) ->method('rollbackTransaction') ->will($this->throwException($exception)); try { $this->transaction->rollback(); $this->fail('Expected exception not thrown'); } catch (\Everyman\Neo4j\Exception $e) { self::assertSame($exception, $e); self::assertTrue($this->transaction->isClosed()); self::assertTrue($this->transaction->isError()); } } public function testKeepAlive_DelegatesToClient() { $this->client->expects($this->once()) ->method('addStatementsToTransaction') ->with($this->transaction, array(), false); $result = $this->transaction->keepAlive(); self::assertSame($this->transaction, $result); self::assertFalse($this->transaction->isClosed()); } public function testKeepAlive_NoTransactionId_Noop() { $transaction = new Transaction($this->client); $this->client->expects($this->never()) ->method('addStatementsToTransaction'); $result = $transaction->keepAlive(); self::assertSame($transaction, $result); self::assertFalse($transaction->isClosed()); } public function testKeepAlive_ClosedTransaction_ThrowsException() { $result = $this->transaction->commit(); $this->setExpectedException('\Everyman\Neo4j\Exception', 'already closed'); $this->transaction->keepAlive(); } public function testKeepAlive_ClientException_MarksTransactionClosedAndErrorAndThrowsException() { $exception = new \Everyman\Neo4j\Exception('some client error'); $this->client->expects($this->any()) ->method('addStatementsToTransaction') ->will($this->throwException($exception)); try { $this->transaction->keepAlive(); $this->fail('Expected exception not thrown'); } catch (\Everyman\Neo4j\Exception $e) { self::assertSame($exception, $e); self::assertTrue($this->transaction->isClosed()); self::assertTrue($this->transaction->isError()); } } public function testAddStatements_NoId_DelegatesToClient() { $transaction = new Transaction($this->client); $statements = array( new Query($this->client, 'foo'), new Query($this->client, 'bar'), ); $commit = false; $expectedResult = new ResultSet($this->client, array()); $expected = array($expectedResult); $this->client->expects($this->once()) ->method('addStatementsToTransaction') ->with($transaction, $statements, $commit) ->will($this->returnValue($expected)); $result = $transaction->addStatements($statements, $commit); self::assertSame($expected[0], $result[0]); self::assertFalse($transaction->isClosed()); } public function testAddStatements_DelegatesToClient() { $statements = array( new Query($this->client, 'foo'), new Query($this->client, 'bar'), ); $commit = true; $expectedResult = new ResultSet($this->client, array()); $expected = array($expectedResult); $this->client->expects($this->once()) ->method('addStatementsToTransaction') ->with($this->transaction, $statements, $commit) ->will($this->returnValue($expected)); $result = $this->transaction->addStatements($statements, $commit); self::assertSame($expected[0], $result[0]); self::assertTrue($this->transaction->isClosed()); } public function testAddStatements_SingleQuery_WrapsQueryInArrayBeforeSendingToClient() { $statement = new Query($this->client, 'foo'); $expectedResult = new ResultSet($this->client, array()); $expected = array($expectedResult); $this->client->expects($this->once()) ->method('addStatementsToTransaction') ->with($this->transaction, array($statement)) ->will($this->returnValue($expected)); $result = $this->transaction->addStatements($statement); self::assertSame($expected[0], $result); } public function testAddStatements_NoCommit_TransactionOpen() { $statements = array(new Query($this->client, 'foo')); $this->client->expects($this->once()) ->method('addStatementsToTransaction') ->with($this->transaction, $statements, false); $this->transaction->addStatements($statements); self::assertFalse($this->transaction->isClosed()); } public function testAddStatements_ClosedTransaction_ThrowsException() { $result = $this->transaction->commit(); $this->setExpectedException('\Everyman\Neo4j\Exception', 'already closed'); $this->transaction->addStatements(array( new Query($this->client, 'foo'), new Query($this->client, 'bar'), )); } public function testAddStatements_ClientException_MarksTransactionClosedAndErrorAndThrowsException() { $exception = new \Everyman\Neo4j\Exception('some client error'); $this->client->expects($this->any()) ->method('addStatementsToTransaction') ->will($this->throwException($exception)); try { $this->transaction->addStatements(array(new Query($this->client, 'foo'))); $this->fail('Expected exception not thrown'); } catch (\Everyman\Neo4j\Exception $e) { self::assertSame($exception, $e); self::assertTrue($this->transaction->isClosed()); self::assertTrue($this->transaction->isError()); } } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/TransportTest.php ================================================ transport = $this->getMock('Everyman\Neo4j\Transport', array('makeRequest'), array($this->host, $this->port)); } public function testConstants_MakeSureNothingSillyHappensLikeMisnamingTheConstants_ReturnsCorrectString() { $this->assertEquals('GET', Transport::GET); $this->assertEquals('POST', Transport::POST); $this->assertEquals('PUT', Transport::PUT); $this->assertEquals('DELETE', Transport::DELETE); } public function testGetEndpoint_ReturnsCorrectEndpointUrl() { $this->assertEquals("http://{$this->host}:{$this->port}/db/data", $this->transport->getEndpoint()); } public function testGetEndpoint_UseHttps_ReturnsCorrectEndpointUrl() { $this->transport->useHttps(); $this->assertEquals("https://{$this->host}:{$this->port}/db/data", $this->transport->getEndpoint()); } public function testDelete_MakesRequestWithCorrectParams() { $expected = array('code'=>200,'headers'=>array('Location'=>'somewhere'),'data'=>array('key'=>'val')); $this->transport->expects($this->once()) ->method('makeRequest') ->with(Transport::DELETE, '/path') ->will($this->returnValue($expected)); $this->assertEquals($expected, $this->transport->delete('/path')); } public function testPut_MakesRequestWithCorrectParams() { $expected = array('code'=>200,'headers'=>array('Location'=>'somewhere'),'data'=>array('key'=>'val')); $this->transport->expects($this->once()) ->method('makeRequest') ->with(Transport::PUT, '/path', 'somedata') ->will($this->returnValue($expected)); $this->assertEquals($expected, $this->transport->put('/path','somedata')); } public function testPost_MakesRequestWithCorrectParams() { $expected = array('code'=>200,'headers'=>array('Location'=>'somewhere'),'data'=>array('key'=>'val')); $this->transport->expects($this->once()) ->method('makeRequest') ->with(Transport::POST, '/path', 'somedata') ->will($this->returnValue($expected)); $this->assertEquals($expected, $this->transport->post('/path','somedata')); } public function testGet_MakesRequestWithCorrectParams() { $expected = array('code'=>200,'headers'=>array('Location'=>'somewhere'),'data'=>array('key'=>'val')); $this->transport->expects($this->once()) ->method('makeRequest') ->with(Transport::GET, '/path', 'somedata') ->will($this->returnValue($expected)); $this->assertEquals($expected, $this->transport->get('/path','somedata')); } public function testEncodeData_StringGiven_ReturnsString() { $data = 'http://localhost:7474/db/data/node/19'; $expected = '"http:\/\/localhost:7474\/db\/data\/node\/19"'; $result = $this->transport->encodeData($data); $this->assertEquals($expected, $result); } public function testEncodeData_ArrayWithNonNumericKeys_ReturnsString() { $obj = new \stdClass(); $obj->s = "hi"; $obj->i = 9; $obj->a = array(7,8); $data = array( 'string' => 'http://localhost:7474/db/data/node/19', 'int' => 123, 'array' => array(4,5,6), 'object' => $obj, ); $expected = '{"string":"http:\/\/localhost:7474\/db\/data\/node\/19","int":123,"array":[4,5,6],"object":{"s":"hi","i":9,"a":[7,8]}}'; $result = $this->transport->encodeData($data); $this->assertEquals($expected, $result); } public function testEncodeData_ArrayWithNumericKeys_ReturnsString() { $obj = new \stdClass(); $obj->s = "hi"; $obj->i = 9; $obj->a = array(7,8); $data = array( 'http://localhost:7474/db/data/node/19', 123, array(4,5,6), $obj, ); $expected = '["http:\/\/localhost:7474\/db\/data\/node\/19",123,[4,5,6],{"s":"hi","i":9,"a":[7,8]}]'; $result = $this->transport->encodeData($data); $this->assertEquals($expected, $result); } public function testEncodeData_EmptyArray_ReturnsString() { $data = array(); $expected = '{}'; $result = $this->transport->encodeData($data); $this->assertEquals($expected, $result); } } ================================================ FILE: tests/unit/lib/Everyman/Neo4j/TraversalTest.php ================================================ client = $this->getMock('Everyman\Neo4j\Client', array(), array(), '', false); $this->traversal = new Traversal($this->client); } public function testGetClient_ClientSetCorrectly_ReturnsClient() { $this->assertSame($this->client, $this->traversal->getClient()); } public function testOrder_NoneGiven_ReturnsNull() { $this->assertNull($this->traversal->getOrder()); } public function testOrder_OrderGiven_ReturnsString() { $this->traversal->setOrder(Traversal::OrderDepthFirst); $this->assertEquals(Traversal::OrderDepthFirst, $this->traversal->getOrder()); } public function testUniqueness_NoneGiven_ReturnsNull() { $this->assertNull($this->traversal->getUniqueness()); } public function testUniqueness_UniquenessGiven_ReturnsString() { $this->traversal->setUniqueness(Traversal::UniquenessNodeGlobal); $this->assertEquals(Traversal::UniquenessNodeGlobal, $this->traversal->getUniqueness()); } public function testMaxDepth_NoneGiven_ReturnsNull() { $this->assertNull($this->traversal->getMaxDepth()); } public function testMaxDepth_MaxDepthGiven_ReturnsInteger() { $this->traversal->setMaxDepth(3); $this->assertEquals(3, $this->traversal->getMaxDepth()); } public function testRelationships_NoneGiven_ReturnsEmptyArray() { $relationships = $this->traversal->getRelationships(); $this->assertEquals(array(), $relationships); } public function testRelationships_TypeGivenAndDirectionGiven_ReturnsArray() { $this->traversal->addRelationship('FOOTYPE'); $this->traversal->addRelationship('BARTYPE', Relationship::DirectionOut); $relationships = $this->traversal->getRelationships(); $this->assertEquals(array( array('type'=>'FOOTYPE'), array('type'=>'BARTYPE', 'direction'=>Relationship::DirectionOut), ), $relationships); } public function testPruneEvaluator_NoneGiven_ReturnsNull() { $this->assertNull($this->traversal->getPruneEvaluator()); } public function testPruneEvaluator_LanguageAndBody_ReturnsArray() { $this->traversal->setPruneEvaluator('javascript', 'return true;'); $evaluator = $this->traversal->getPruneEvaluator(); $this->assertEquals('javascript', $evaluator['language']); $this->assertEquals('return true;', $evaluator['body']); } public function testPruneEvaluator_BuiltIn_ReturnsArray() { $this->traversal->setPruneEvaluator(Traversal::PruneNone); $evaluator = $this->traversal->getPruneEvaluator(); $this->assertEquals('builtin', $evaluator['language']); $this->assertEquals(Traversal::PruneNone, $evaluator['body']); } public function testPruneEvaluator_Reset_ReturnsNull() { $this->traversal->setPruneEvaluator('javascript', 'return true;'); $this->traversal->setPruneEvaluator(); $this->assertNull($this->traversal->getPruneEvaluator()); } public function testReturnFilter_NoneGiven_ReturnsNull() { $this->assertNull($this->traversal->getReturnFilter()); } public function testReturnFilter_LanguageAndBody_ReturnsArray() { $this->traversal->setReturnFilter('javascript', 'return true;'); $filter = $this->traversal->getReturnFilter(); $this->assertEquals('javascript', $filter['language']); $this->assertEquals('return true;', $filter['body']); } public function testReturnFilter_BuiltIn_ReturnsArray() { $this->traversal->setReturnFilter(Traversal::ReturnAllButStart); $filter = $this->traversal->getReturnFilter(); $this->assertEquals('builtin', $filter['language']); $this->assertEquals(Traversal::ReturnAllButStart, $filter['body']); } public function testReturnFilter_Reset_ReturnsNull() { $this->traversal->setReturnFilter('javascript', 'return true;'); $this->traversal->setReturnFilter(); $this->assertNull($this->traversal->getPruneEvaluator()); } public function testGetResults_PassesThroughToClient() { $startNode = new Node($this->client); $expectedNodes = array(new Node($this->client), new Node($this->client)); $this->client->expects($this->once()) ->method('executeTraversal') ->with($this->traversal, $startNode, Traversal::ReturnTypeNode) ->will($this->returnValue($expectedNodes)); $nodes = $this->traversal->getResults($startNode, Traversal::ReturnTypeNode); $this->assertEquals($expectedNodes, $nodes); } public function testGetSingleResult_PassesThroughToClient() { $startNode = new Node($this->client); $firstResult = new Node($this->client); $expectedNodes = array($firstResult, new Node($this->client)); $this->client->expects($this->once()) ->method('executeTraversal') ->with($this->traversal, $startNode, Traversal::ReturnTypeNode) ->will($this->returnValue($expectedNodes)); $result = $this->traversal->getSingleResult($startNode, Traversal::ReturnTypeNode); $this->assertSame($firstResult, $result); } public function testGetSingleResult_NoResults_ReturnsNull() { $startNode = new Node($this->client); $expectedNodes = array(); $this->client->expects($this->once()) ->method('executeTraversal') ->with($this->traversal, $startNode, Traversal::ReturnTypeNode) ->will($this->returnValue($expectedNodes)); $result = $this->traversal->getSingleResult($startNode, Traversal::ReturnTypeNode); $this->assertNull($result); } }