PK 9AV' ' LICENSEnu W+A
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
PK 9AVǴ generate-docs.phpnu W+A loadHTMLFile("./docs/index.html");
$xpath = new DomXpath($dom);
// Remove "Global" namespace
$result = $xpath->query('//li/a[@href="namespaces/default.html"]');
if ($result->length > 0) {
$node = $result->item(0);
$node->parentNode->parentNode->removeChild($node->parentNode);
}
// Remove Packages
$result = $xpath->query('//div[@class="well"][2]');
if ($result->length > 0) {
$node = $result->item(0);
$node->parentNode->removeChild($node);
}
$dom->saveHTMLFile('./docs/index.html');
PK 9AVb{+ .travis.ymlnu W+A language: "php"
install:
- composer install
notifications:
webhooks: http://basho-engbot.herokuapp.com/travis?key=8d594c660ec46f616e37e24fd941c0ea1fc67963
email: "clients@basho.com"
php:
- "5.3"
- "5.4"
services:
- "riak"
script: "php -q tests/integration/test.php"PK 9AV:
composer.jsonnu W+A {
"name": "basho/riak",
"description": "Official Riak PHP client for PHP 5.3",
"keywords": ["riak", "client", "driver", "database", "nosql"],
"homepage": "http://basho.com/riak/",
"license": "Apache-2.0",
"authors": [
{
"name": "Riak Team",
"homepage": "https://github.com/basho/riak-php-client/contributors"
}
],
"autoload": {
"psr-0": { "Basho": "src/" }
},
"require": {
"php": ">=5.3.0",
"ext-curl": "*"
}
}
PK 9AVT T
phpdoc.xmlnu W+A
Riak PHP Client
docs
- TODO
- FIXME
php
phtml
docs
warn
{APP_ROOT}/data/log/{DATE}.log
{APP_ROOT}/data/log/{DATE}.errors.log
src/Basho/Riak
PK 9AVUY Y tests/integration/TestSuite.phpnu W+A so we can send you a copy immediately.
*
* @category Riak
* @package TestSuite
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Integration;
use Basho\Riak\Exception;
use Basho\Riak\Riak;
/**
* TestSuite
*
* @category Riak
* @package TestSuite
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class TestSuite
{
const HOST = 'localhost';
const PORT = 8098;
const VERBOSE = true;
private $_passed = 0;
private $_failed = 0;
private function _test($method)
{
try {
$this->$method();
$this->_passed++;
$this->_printLine(" [+] TEST PASSED: $method");
} catch (Exception $e) {
$this->_failed++;
$this->_printLine("[-] TEST FAILED: $method.", false);
$this->_printLine("{$e->getMessage()}", false);
$this->_printLine("{$e->getTraceAsString()}\n", false);
}
}
private function _summary()
{
if (!$this->_failed) {
$this->_printLine("\nSUCCESS: Passed all $this->_passed tests.");
} else {
$test_total = $this->_passed + $this->_failed;
$this->_printLine("\nFAILURE: Failed $this->_failed of $test_total tests!", false);
// exit with a 1 to signal to Travis CI that the tests failed
exit(1);
}
}
public function _printLine($msg, $pass = true)
{
$color = $pass ? '0;32' : '0;31';
echo "\033[{$color}m{$msg}\033[0m\n";
}
public function run()
{
print("Starting Integration Tests\n---\n");
$this->_test('testIsAlive');
$this->_test('testNotHasKey');
$this->_test('testHasKey');
$this->_test('testStoreAndGet');
$this->_test('testStoreAndGetWithoutKey');
$this->_test('testBinaryStoreAndGet');
$this->_test('testMissingObject');
$this->_test('testDelete');
$this->_test('testSetBucketProperties');
$this->_test('testSiblings');
$this->_test('testGetKeys');
$this->_test('testJavascriptArgMapReduce');
$this->_test('testJavascriptBucketMapReduce');
$this->_test('testJavascriptNamedMap');
$this->_test('testJavascriptNamedMapReduce');
$this->_test('testJavascriptSourceMap');
$this->_test('testJavascriptSourceMapReduce');
$this->_test('testErlangMapReduce');
$this->_test('testMapReduceFromObject');
$this->_test('testKeyFilter');
$this->_test('testKeyFilterOperator');
$this->_test('testStoreAndGetLinks');
$this->_test('testLinkWalking');
// broken, not sure why, will investigate later
#$this->_test('testSearchIntegration');
$this->_test('testSecondaryIndexes');
$this->_test('testMetaData');
$this->_summary();
}
public function testIsAlive()
{
$client = new Riak(self::HOST, self::PORT);
$this->_assert($client->isAlive());
}
public function testStoreAndGet()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
$rand = rand();
$obj = $bucket->newObject('foo', $rand);
$obj->store();
$obj = $bucket->get('foo');
$this->_assert($obj->exists());
$this->_assert($obj->getBucket()->getName() == 'bucket');
$this->_assert($obj->getKey() == 'foo');
$this->_assert($obj->getData() == $rand);
}
public function testStoreAndGetWithoutKey()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
$rand = rand();
$obj = $bucket->newObject(null, $rand);
$obj->store();
$key = $obj->key;
$obj = $bucket->get($key);
$this->_assert($obj->exists());
$this->_assert($obj->getBucket()->getName() == 'bucket');
$this->_assert($obj->getKey() == $key);
$this->_assert($obj->getData() == $rand);
}
public function testBinaryStoreAndGet()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
# Store as binary, retrieve as binary, then compare...
$rand = rand();
$obj = $bucket->newBinary('foo1', $rand);
$obj->store();
$obj = $bucket->getBinary('foo1');
$this->_assert($obj->exists());
$this->_assert($obj->getData() == $rand);
# Store as JSON, retrieve as binary, JSON-decode, then compare...
$data = array(rand(), rand(), rand());
$obj = $bucket->newObject('foo2', $data);
$obj->store();
$obj = $bucket->getBinary('foo2');
$this->_assert($data == json_decode($obj->getData()));
}
public function testMissingObject()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
$obj = $bucket->get("missing");
$this->_assert(!$obj->exists());
$this->_assert($obj->getData() == null);
}
public function testDelete()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
$rand = rand();
$obj = $bucket->newObject('foo', $rand);
$obj->store();
$obj = $bucket->get('foo');
$this->_assert($obj->exists());
$obj->delete();
$obj->reload();
$this->_assert(!$obj->exists());
}
public function testSetBucketProperties()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
# Test setting allow mult...
$bucket->setAllowMultiples(true);
$this->_assert($bucket->getAllowMultiples());
# Test setting nval...
$bucket->setNVal(3);
$this->_assert($bucket->getNVal() == 3);
# Test setting multiple properties...
$bucket->setProperties(array("allow_mult" => false, "n_val" => 2));
$this->_assert(!$bucket->getAllowMultiples());
$this->_assert($bucket->getNVal() == 2);
}
public function testSiblings()
{
# Set up the bucket, clear any existing object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('multiBucket');
$bucket->setAllowMultiples('true');
$obj = $bucket->get('foo');
$obj->delete();
# Store the same object multiple times...
for ($i = 0; $i < 5; $i++) {
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('multiBucket');
$obj = $bucket->newObject('foo', rand());
$obj->store();
}
# Make sure the object has 5 siblings...
$this->_assert($obj->hasSiblings());
$this->_assert($obj->getSiblingCount() == 5);
# Test getSibling()/getSiblings()...
$siblings = $obj->getSiblings();
$obj3 = $obj->getSibling(3);
$this->_assert($siblings[3]->getData() == $obj3->getData());
# Resolve the conflict, and then do a get...
$obj3 = $obj->getSibling(3);
$obj3->store();
$obj->reload();
$this->_assert($obj->getData() == $obj3->getData());
# Clean up for next tests...
$obj->delete();
}
public function testJavascriptSourceMap()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->store();
# Run the map...
$result = $client->
add("bucket", "foo")->
map("function (v) { return [JSON.parse(v.values[0].data)]; }")->
run();
$this->_assert($result == array(2));
}
public function testJavascriptNamedMap()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->store();
# Run the map...
$result = $client->
add("bucket", "foo")->
map("Riak.mapValuesJson")->
run();
$this->_assert($result == array(2));
}
public function testJavascriptSourceMapReduce()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->store();
$bucket->newObject("bar", 3)->store();
$bucket->newObject("baz", 4)->store();
# Run the map...
$result = $client->
add("bucket", "foo")->
add("bucket", "bar")->
add("bucket", "baz")->
map("function (v) { return [1]; }")->
reduce("Riak.reduceSum")->
run();
$this->_assert($result[0] == 3);
}
public function testJavascriptNamedMapReduce()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->store();
$bucket->newObject("bar", 3)->store();
$bucket->newObject("baz", 4)->store();
# Run the map...
$result = $client->
add("bucket", "foo")->
add("bucket", "bar")->
add("bucket", "baz")->
map("Riak.mapValuesJson")->
reduce("Riak.reduceSum")->
run();
$this->_assert($result == array(9));
}
public function testJavascriptBucketMapReduce()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket_" . rand());
$bucket->newObject("foo", 2)->store();
$bucket->newObject("bar", 3)->store();
$bucket->newObject("baz", 4)->store();
# Run the map...
$result = $client->
add($bucket->name)->
map("Riak.mapValuesJson")->
reduce("Riak.reduceSum")->
run();
$this->_assert($result == array(9));
}
public function testJavascriptArgMapReduce()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->store();
# Run the map...
$result = $client->
add("bucket", "foo", 5)->
add("bucket", "foo", 10)->
add("bucket", "foo", 15)->
add("bucket", "foo", -15)->
add("bucket", "foo", -5)->
map("function(v, arg) { return [arg]; }")->
reduce("Riak.reduceSum")->
run();
$this->_assert($result == array(10));
}
public function testErlangMapReduce()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->store();
$bucket->newObject("bar", 2)->store();
$bucket->newObject("baz", 4)->store();
# Run the map...
$result = $client->
add("bucket", "foo")->
add("bucket", "bar")->
add("bucket", "baz")->
map(array("riak_kv_mapreduce", "map_object_value"))->
reduce(array("riak_kv_mapreduce", "reduce_set_union"))->
run();
$this->_assert(count($result) == 2);
}
public function testMapReduceFromObject()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->store();
$obj = $bucket->get("foo");
$result = $obj->map("Riak.mapValuesJson")->run();
$this->_assert($result = array(2));
}
public function testKeyFilter()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("filter_bucket");
$bucket->newObject("foo_one", array("foo" => "one"))->store();
$bucket->newObject("foo_two", array("foo" => "two"))->store();
$bucket->newObject("foo_three", array("foo" => "three"))->store();
$bucket->newObject("foo_four", array("foo" => "four"))->store();
$bucket->newObject("moo_five", array("foo" => "five"))->store();
$mapred = $client
->add($bucket->name)
->key_filter(array('tokenize', '_', 1), array('eq', 'foo'));
$results = $mapred->run();
$this->_assert(count($results) == 4);
}
public function testKeyFilterOperator()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("filter_bucket");
$bucket->newObject("foo_one", array("foo" => "one"))->store();
$bucket->newObject("foo_two", array("foo" => "two"))->store();
$bucket->newObject("foo_three", array("foo" => "three"))->store();
$bucket->newObject("foo_four", array("foo" => "four"))->store();
$bucket->newObject("moo_five", array("foo" => "five"))->store();
$mapred = $client
->add($bucket->name)
->key_filter(array('starts_with', 'foo'))
->key_filter_or(array('ends_with', 'five'));
$results = $mapred->run();
$this->_assert(count($results) == 5);
}
public function testStoreAndGetLinks()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->
addLink($bucket->newObject("foo1"))->
addLink($bucket->newObject("foo2"), "tag")->
addLink($bucket->newObject("foo3"), "tag2!@#$%^&*")->
store();
$obj = $bucket->get("foo");
$links = $obj->getLinks();
$this->_assert(count($links) == 3);
}
public function testLinkWalking()
{
# Create the object...
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("bucket");
$bucket->newObject("foo", 2)->
addLink($bucket->newObject("foo1", "test1")->store())->
addLink($bucket->newObject("foo2", "test2")->store(), "tag")->
addLink($bucket->newObject("foo3", "test3")->store(), "tag2!@#$%^&*")->
store();
$obj = $bucket->get("foo");
$results = $obj->link("bucket")->run();
$this->_assert(count($results) == 3);
$results = $obj->link("bucket", "tag")->run();
$this->_assert(count($results) == 1);
}
public function testSearchIntegration()
{
// bucket to use
$bucket_name = 'searchbucket';
// spin up client & grab bucket
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket($bucket_name);
// turn on search for this bucket
$bucket->setProperty('search', true);
// create searchable objects
$bucket->newObject("one", array("foo" => "one", "bar" => "red"))->store();
$bucket->newObject("two", array("foo" => "two", "bar" => "green"))->store();
$bucket->newObject("three", array("foo" => "three", "bar" => "blue"))->store();
$bucket->newObject("four", array("foo" => "four", "bar" => "orange"))->store();
$bucket->newObject("five", array("foo" => "five", "bar" => "yellow"))->store();
#sleep(5);
// search test 1
$results = $client->search($bucket_name, "foo:one OR foo:two")->run();
if (count($results) == 0) {
print "\n\nNot running tests \"testSearchIntegration()\".\n";
print "Please ensure that you have installed the Riak Search hook on bucket \"searchbucket\" by running
\"bin/search-cmd install searchbucket\".\n\n";
return;
}
$this->_assert(count($results) == 2, "Search integration result = " . count($results) . ' but should be 2.');
// search test 2
$results = $client->search(
"searchbucket",
"(foo:one OR foo:two OR foo:three OR foo:four) AND (NOT bar:green)"
)->run();
$this->_assert(count($results) == 3, "Search integration result = " . count($results) . ' but should be 3.');
}
public function testSecondaryIndexes()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("indextest");
# Immediate tests to see if 2i is even supported w/ the backend
try {
$bucket->indexSearch("foo", "bar_bin", "baz");
} catch (Exception $e) {
if (strpos($e->__toString(), "indexes_not_supported") !== false) {
return true;
} else {
throw $e;
}
}
# Okay, continue with the rest of the tests
$bucket
->newObject("one", array("foo" => 1, "bar" => "red"))
->addIndex("number", "int", 1)
->addIndex("text", "bin", "apple")
->addAutoIndex("foo", "int")
->addAutoIndex("bar", "bin")
->store();
$bucket
->newObject("two", array("foo" => 2, "bar" => "green"))
->addIndex("number", "int", 2)
->addIndex("text", "bin", "avocado")
->addAutoIndex("foo", "int")
->addAutoIndex("bar", "bin")
->store();
$bucket
->newObject("three", array("foo" => 3, "bar" => "blue"))
->addIndex("number", "int", 3)
->addIndex("text", "bin", "blueberry")
->addAutoIndex("foo", "int")
->addAutoIndex("bar", "bin")
->store();
$bucket
->newObject("four", array("foo" => 4, "bar" => "orange"))
->addIndex("number", "int", 4)
->addIndex("text", "bin", "citrus")
->addAutoIndex("foo", "int")
->addAutoIndex("bar", "bin")
->store();
$bucket
->newObject("five", array("foo" => 5, "bar" => "yellow"))
->addIndex("number", "int", 5)
->addIndex("text", "bin", "banana")
->addAutoIndex("foo", "int")
->addAutoIndex("bar", "bin")
->store();
$bucket
->newObject("six", array("foo" => 6, "bar" => "purple"))
->addIndex("number", "int", 6)
->addIndex("number", "int", 7)
->addIndex("number", "int", 8)
->setIndex("text", "bin", array("x", "y", "z"))
->store();
# Exact matches
$results = $bucket->indexSearch("number", "int", 5);
$this->_assert(count($results) == 1);
$results = $bucket->indexSearch("text", "bin", "apple");
$this->_assert(count($results) == 1);
# Range searches
$results = $bucket->indexSearch("foo", "int", 1, 3);
$this->_assert(count($results) == 3);
$results = $bucket->indexSearch("bar", "bin", "blue", "orange");
$this->_assert(count($results) == 3);
# Test duplicate key de-duping
$results = $bucket->indexSearch("number", "int", 6, 8, true);
$this->_assert(count($results) == 1);
$results = $bucket->indexSearch("text", "bin", "x", "z", true);
$this->_assert(count($results) == 1);
# Test auto indexes don't leave cruft indexes behind, and regular
# indexes are preserved
$object = $bucket->get("one");
$object->setData(array("foo" => 9, "bar" => "plaid"));
$object->store();
# Auto index updates
$results = $bucket->indexSearch("foo", "int", 9);
$this->_assert(count($results) == 1);
# Auto index leaves no cruft
$results = $bucket->indexSearch("foo", "int", 1);
$this->_assert(count($results) == 0);
# Normal index is preserved
$results = $bucket->indexSearch("number", "int", 1);
$this->_assert(count($results) == 1);
# Test proper collision handling on autoIndex and regular index on same field
$bucket
->newObject("seven", array("foo" => 7))
->addAutoIndex("foo", "int")
->addIndex("foo", "int", 7)
->store();
$results = $bucket->indexSearch("foo", "int", 7);
$this->_assert(count($results) == 1);
$object = $bucket->get("seven");
$object->setData(array("foo" => 8));
$object->store();
$results = $bucket->indexSearch("foo", "int", 8);
$this->_assert(count($results) == 1);
$results = $bucket->indexSearch("foo", "int", 7);
$this->_assert(count($results) == 1);
}
public function testMetaData()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket("metatest");
# Set some meta
$bucket->newObject("metatest", array("foo" => 'bar'))
->setMeta("foo", "bar")->store();
# Test that we load the meta back
$object = $bucket->get("metatest");
$this->_assert($object->getMeta("foo") == "bar");
# Test that the meta is preserved when we rewrite the object
$bucket->get("metatest")->store();
$object = $bucket->get("metatest");
$this->_assert($object->getMeta("foo") == "bar");
# Test that we remove meta
$object->removeMeta("foo")->store();
$anotherObject = $bucket->get("metatest");
$this->_assert($anotherObject->getMeta("foo") === null);
}
public function testNotHasKey()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
$exists = $bucket->hasKey('missing');
$this->_assert(!$exists);
}
public function testHasKey()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
$rand = rand();
$obj = $bucket->newObject('foo', $rand);
$obj->store();
$exists = $bucket->hasKey('foo');
$this->_assert($exists);
}
public function testGetKeys()
{
$client = new Riak(self::HOST, self::PORT);
$bucket = $client->bucket('bucket');
$obj = $bucket->newObject('hello%3Aworld', 'some data');
$obj->store();
$keys = $bucket->getKeys();
$this->_assert(in_array('hello%3Aworld', $keys));
}
private function _assert($bool, $msg = '')
{
if (!$bool) {
throw new Exception($msg);
}
}
}
PK 9AV8 tests/integration/test.phpnu W+A #!/usr/bin/env php
run();PK 9AV
-~
.gitignorenu W+A .idea
PK 9AVBR0B 0B README.mdnu W+A # Riak PHP Client #
This is the official PHP client for Riak.
[![Build Status](https://secure.travis-ci.org/basho/riak-php-client.png?branch=master)](http://travis-ci.org/basho/riak-php-client)
## Contributing
This is an open source project licensed under the Apache 2.0 License. We encourage and welcome contributions to the
project from the community. We ask that you keep in mind these considerations when planning your contribution.
* Whether your contribution is for a bug fix or a feature request, create an Issue and let us know what you are thinking.
* For bugs, if you have already found a fix, feel free to submit a Pull Request referencing the Issue you created.
* For feature requests, we want to improve upon the library incrementally which means small changes at a time. In order ensure your PR can be reviewed in a timely manner, please keep PRs small, e.g. <10 files and <500 lines changed. If you think this is unrealistic, then mention that within the GH Issue and we can discuss it.
* Before you open the PR, please review the following regarding Coding Standards, Docblock comments and unit / integration tests to reduce delays in getting your changes approved.
### Coding Standards
Here are the standards we expect to see when considering pull requests
* [PSR-2 Coding Style Guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
* [PHP / Pear Docblock Guide](http://pear.php.net/manual/en/standards.sample.php)
* [PHPUnit Tests](https://phpunit.de/manual/current/en/phpunit-book.html)
* Please suffix all Interfaces and Traits with the descriptors Interface and Trait, e.g. ObjectInterface & ObjectTrait
### Docblock Comments
Complete docblock comments that follow the Pear / PHP standard not only assist in generating documentation, but also development, as IDE's like PHPStorm, ZendStudio, NetBeans, etc use the information found in the comments to improve the development experience. It is expected that any new code in the library is committed with complete docblock comments.
This includes:
* Short & long descriptions for all new classes and all class members, properties and constants.
* @package, @author, @copyright, @license, and @since need to be included on all new classes.
* @var tag on every class property
* A @param tag for every parameter on a class method
* A @return tag for every class method that returns a value
Here is an example of a class docblock:
```php
/**
* Class Riak
*
* A more elaborate description of what this class does. It may include warnings, limitations or examples.
*
* @package Basho\Riak
* @author Author Name
* @copyright 2011-2014 Basho Technologies, Inc.
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache 2.0 License
* @since 2.0
*/
```
## Documentation ##
API documentation for this library can be found at
(See **Documentation Maintenance** at the bottom of the README for instructions on updating the docs.)
Documentation for use of Riak clients in general can be found at
## Repositories ##
The official source code for this client can be retrieved from
Riak can be obtained pre-built from
or as source from
## Installation ##
Clone this repository to fetch the latest version of this client
git clone git://github.com/basho/riak-php-client.git
## Quick start ##
PHP must be compiled with cURL support, i.e. `./configure --with-curl`. We can verify cURL functions are available by running `php -m | grep curl`.
The following example assumes that we have a local Riak cluster running on port 8098 and our dependencies are installed by [Composer](https://getcomposer.org).
```php
# Import dependencies
require 'vendor/autoload.php';
# Connect to Riak
$client = new Basho\Riak\Riak('127.0.0.1', 8098);
# Choose a bucket name
$bucket = $client->bucket('test');
# Supply a key under which to store your data
$person = $bucket->newObject('riak_developer_1', array(
'name' => 'John Smith',
'age' => 28,
'company' => 'Facebook'
));
# Save the object to Riak
$person->store();
# Fetch the object
$person = $bucket->get('riak_developer_1');
# Update the object
$person->data['company'] = 'Google';
$person->store();
```
## Connecting ##
Connect to a Riak server by specifying the address or hostname and port:
# Connect to Riak
$client = new Basho\Riak\Riak('127.0.0.1', 8098);
This method returns a [Riak](http://basho.github.io/riak-php-client/classes/Basho.Riak.Riak.html) object.
## Using Buckets ##
To select a bucket, use the Riak::bucket() method
# Choose a bucket name
$bucket = $client->bucket('test');
or using the Basho\Riak\Bucket() constructor
# Create a bucket
$bucket = new Basho\Riak\Bucket($client, 'test');
If a bucket by this name does not already exist, a new one will be created for you when you store your first key.
This method returns a [Bucket](http://basho.github.io/riak-php-client/classes/Basho.Riak.Bucket.html)
## Creating Objects ##
Objects can be created using the Basho\Riak\Bucket::newObject() method
# Create an object for future storage and populate it with some data
$person = $bucket->newObject('riak_developer_1');
or using the Basho\Riak\Object() constructor
# Create an object for future storage
$person = new Basho\Riak\Object($client, $bucket, 'riak_developer_1');
Both methods return an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Setting Object Values ##
Object data can be set using the Object::setData() method
# Populate object with some data
$person->setData(array(
'name' => 'John Smith',
'age' => 28,
'company' => 'Facebook'
));
or you may modify the object's data property directly (not recommended)
# Populate object with some data
$person->data = array(
'name' => 'John Smith',
'age' => 28,
'company' => 'Facebook'
);
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Storing Objects ##
Objects can be stored using the Object::store() method
# Save the object to Riak
$person->store();
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Chaining ##
For methods like newObject(), setData() and store() which return objects of a similar class (in this case Object), chaining can be used to perform multiple operations in a single statement.
# Create, set, and store an object
$data = array(
'name' => "John Smith",
'age' => 28,
'company' => "Facebook"
);
$bucket->newObject('riak_developer_1')->setData($data)->store();
or
# Another way to create, set, and store an object
$data = array(
'name' => "John Smith",
'age' => 28,
'company' => "Facebook"
);
$bucket->newObject('riak_developer_1',$data)->store();
## Fetching Objects ##
Objects can be retrieved from a bucket using the Bucket::get() method
# Retrieve the object from a bucket
$person = $bucket->get('riak_developer_1');
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Modifying Objects ##
Objects can be modified using the Object::store() method
# Update the object
$person = $bucket->get('riak_developer_1');
$person->data['company'] = "Google";
$person->store();
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Deleting Objects ##
Objects can be deleted using the Object::delete() method
# Delete the object
$person = $bucket->get('riak_developer_1');
$person->delete();
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Adding a Link ##
Links can be added using Object::addLink()
# Add a link from John to Dave
$john = $bucket->get('riak_developer_1');
$dave = $bucket->get('riak_developer_2');
$john->addLink($dave, 'friend')->store();
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Removing a Link ##
Links can be removed using Object::removeLink()
# Remove the link from John to Dave
$john = $bucket->get('riak_developer_1');
$dave = $bucket->get('riak_developer_2');
$john->removeLink($dave, 'friend')->store();
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Retrieving Links ##
An object's links can be retrieved using Object::getLinks()
# Retrieve all of John's links
$john = $bucket->get('riak_developer_1');
$links = $john->getLinks();
This method returns an array of [Link](http://basho.github.io/riak-php-client/classes/Basho.Riak.Link.html)s
## Linkwalking ##
Linkwalking can be done using the Object::link() method
# Retrieve all of John's friends
$john = $bucket->get('riak_developer_1');
$friends = $john->link($bucket->name, "friend")->run();
This method returns an array of [Link](http://basho.github.io/riak-php-client/classes/Basho.Riak.Link.html)s
## Dereferencing Links ##
Links can be dereferenced to the linked object using the Link::get() method
# Retrieve all of John's friends
$john = $bucket->get('riak_developer_1');
$dave = $bucket->get('riak_developer_2');
$john->addLink($dave, 'friend')->store();
$friends = $john->link($bucket->name, "friend")->run();
$dave = $friends[0]->get();
This method returns an [Object](http://basho.github.io/riak-php-client/classes/Basho.Riak.Object.html)
## Fetching Data With Map/Reduce ##
Data can be fetched by Map and Reduce using the Riak::add() method
# Fetch a sorted list of all keys in a bucket
$result = $client->add($bucket->name)
->map("function (v) { return [v.key]; }")
->reduce("Riak.reduceSort")
->run();
This method returns an array of data representing the result of the Map/Reduce functions.
*More examples of Map/Reduce can be found in TestSuite.php
*
## Using Key Filters With Map/Reduce ##
When using Map/Reduce on a bucket, you can use key filters to determine the applicable key set using the MapReduce::key_filter(), MapReduce::key_filter_and(), and MapReduce::key_filter_or() methods.
# Retrieve the keys of all invoices from May 30, 2010
$result = $client->add($bucket->name)
->key_filter(array('tokenize', '.', 1), array('eq', 'invoice'))
->key_filter_and(array('tokenize', '.', 2), array('ends_with', '20100530'))
->map("function (v) { return [v.key]; }")
->reduce("Riak.reduceSort")
->run();
This method returns an array of data representing the result of the Map/Reduce functions.
## Using Search ##
Searches can be executed using the Riak::search() method
# Create some test data
$bucket = $client->bucket("searchbucket");
$bucket->newObject("one", array("foo"=>"one", "bar"=>"red"))->store();
$bucket->newObject("two", array("foo"=>"two", "bar"=>"green"))->store();
# Execute a search for all objects with matching properties
$results = $client->search("searchbucket", "foo:one OR foo:two")->run();
This method will return null unless executed against a Riak Search cluster.
## Meta Data ##
You can provide meta data on objects using Object::getMeta() and Object::setMeta()
# Set some new meta data
$object->setMeta("some-meta", "some-value");
# Get some meta data (returns null if not found)
$object->getMeta("some-meta");
# Get all meta data (an array keyed by meta name)
$object->getAllMeta()
Remove existing metadata
# Remove a single value
$object->removeMeta("some-meta");
# Remove all meta data
$object->removeAllMeta();
## Secondary Indexes ##
### Adding Secondary Indexes ###
Secondary indexes can be added using the Object::addIndex() and Object::addAutoIndex() methods.
Auto indexes are kept fresh with the associated field automatically, so if you read an object, modify its data, and write it back, the auto index will reflect the new value from the object. Traditional indexes are fixed and must be manually managed. *NOTE* that auto indexes are a function of the Riak PHP client, and are not part of native Riak functionality. Other clients writing the same object must manage the index manually.
# Create some test data
$bucket = $client->bucket("indextest");
$bucket
->newObject("one", array("some_field"=>1, "bar"=>"red"))
->addIndex("index_name", "int", 1)
->addIndex("index_name", "int", 2)
->addIndex("text_index", "bin", "apple")
->addAutoIndex("some_field", "int")
->addAutoIndex("bar", "bin")
->store();
You can remove a specific value from an index, all values from an index, or all indexes:
# Remove just a single value
$object->removeIndex("index_name", "int", 2);
# Remove all values from an index
$object->removeAllIndexes("index_name", "int");
# Remove all index types for a given index name
$object->removeAllIndexes("index_name");
# Remove all indexes
$object->removeAllIndexes();
Likewise you can remove auto indexes:
# Just the "foo" index
$object->removeAutoIndex("foo", "int");
# All auto indexes
$object->removeAllAutoIndexes("foo", "int");
# All auto indexes
$object->removeAllAutoIndexes();
Mass load indexes, or just replace an existing index:
$object->setIndex("index_name", "int", array(1, 2, 3));
$object->setIndex("text_index", "bin", "foo");
### Querying a Bucket's secondary index ###
Secondary indexes can be queried using the Bucket::indexSearch() method. This returns an array of Link objects.
# Exact Match
$results = $bucket->indexSearch("index_name", "int", 1);
foreach ($results as $link) {
echo "Key: {$link->getKey()}
";
$object = $link->get();
}
# Range Search
$results = $bucket->indexSearch("index_name", "int", 1, 10);
Duplicate entries may be found in a ranged index search if a given index has multiple values that fall within the range. You can request that these duplicates be eliminated in the result.
$results = $bucket->indexSearch("index_name", "int", 1, 10, true);
### Secondary Indexes in Map/Reduce ###
The same search format used for Bucket::indexSearch() may be used during Map/Reduce operations during the input phase. This is only valid for bucket-level operations, and cannot be combined with other filtration methods such as key filters.
# Use secondary indexes to speed up our Map/Reduce operation
$result = $client
->add("bucket_name") // Begin Map/Reduce
->indexSearch("index_name", "int", 1)
->map("function (v) { return [v.key]; }")
->reduce("Riak.reduceSort")
->run();
## Additional Resources ##
See TestSuite.php for more examples.
## Documentation Maintenance
The PHP API documentation should be regenerated upon each new client release or each new non-trivial API change.
Currently the docs are generated using a tool called [phpDocumentor2](http://www.phpdoc.org), stored in the gh-pages branch of this repo, and are hosted at [http://basho.github.com/riak-php-client/](basho.github.io/riak-php-client/).
### Generating the PHP Documentation
1. Make sure your local copy of this repository is up to date with the latest release/changes.
2. Install phpDocumentor2 (at least 2.0.0b7).
$ pear channel-discover pear.phpdoc.org
$ pear install phpdoc/phpDocumentor-beta
3. Install [GraphViz](http://www.graphviz.org/Download..php) (see link for documentation/downloads)
4. Now that you've got phpDocumentor2 (and GraphViz) installed, generating the new documentation is easy. The configuration is specified in the file "phpdoc.xml", and will be used automatically.
$ php generate-docs.php
5. This should produce a new "docs" directory packed with all sorts of goodness. The next step is to update the "gh-pages" branch:
$ mv docs /tmp/riak-php-docs
$ git checkout gh-pages
$ git rm -rf *
$ mv /tmp/riak-php-docs/* . && rm -rf /tmp/riak-php-docs
$ rm -Rf docs/phpdoc-cache-*
6. Add, commit and push everything:
$ git add .
$ git commit -m "updated docs"
$ git push origin gh-pages
Once you push your changes to the gh-pages branch they will be synced to [http://basho.github.com/riak-php-client/](http://basho.github.com/riak-php-client/)
PK 9AVD< src/Basho/Riak/Link/Phase.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak\Link;
/**
* Phase
*
* @category Basho
* @author debo (https://github.com/MarcoDeBortoli)
*/
class Phase
{
/**
* Construct a Phase object.
* @param string $bucket - The bucket name.
* @param string $tag - The tag.
* @param boolean $keep - True to return results of this phase.
*/
public function __construct($bucket, $tag, $keep)
{
$this->bucket = $bucket;
$this->tag = $tag;
$this->keep = $keep;
}
/**
* Convert the Phase to an associative array. Used
* internally.
*/
public function to_array()
{
$stepdef = array(
"bucket" => $this->bucket,
"tag" => $this->tag,
"keep" => $this->keep
);
return array("link" => $stepdef);
}
}PK 9AV`% " src/Basho/Riak/MapReduce/Phase.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak\MapReduce;
/**
* MapReducePhase
*
* @category Basho
* @author debo (https://github.com/MarcoDeBortoli)
*/
class Phase
{
/**
* Construct a Phase object.
* @param string $type - "map" or "reduce"
* @param mixed $function - string or array()
* @param string $language - "javascript" or "erlang"
* @param boolean $keep - True to return the output of this phase in
* the results.
* @param mixed $arg - Additional value to pass into the map or
* reduce function.
*/
public function __construct($type, $function, $language, $keep, $arg)
{
$this->type = $type;
$this->language = $language;
$this->function = $function;
$this->keep = $keep;
$this->arg = $arg;
}
/**
* Convert the Phase to an associative array. Used
* internally.
*/
public function to_array()
{
$stepdef = array(
"keep" => $this->keep,
"language" => $this->language,
"arg" => $this->arg
);
if ($this->language == "javascript" && is_array($this->function)) {
$stepdef["bucket"] = $this->function[0];
$stepdef["key"] = $this->function[1];
} else {
if ($this->language == "javascript" && is_string($this->function)) {
if (strpos($this->function, "{") == false) {
$stepdef["name"] = $this->function;
} else {
$stepdef["source"] = $this->function;
}
} else {
if ($this->language == "erlang" && is_array($this->function)) {
$stepdef["module"] = $this->function[0];
$stepdef["function"] = $this->function[1];
}
}
}
return array(($this->type) => $stepdef);
}
}PK 9AV~f- src/Basho/Riak/Link.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc, and contributors.
*/
namespace Basho\Riak;
/**
* Link
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class Link
{
/**
* @var Riak|null
*/
public $client = null;
/**
* Construct a Link object.
* @param string $bucket - The bucket name.
* @param string $key - The key.
* @param string $tag - The tag.
*/
public function __construct($bucket, $key, $tag = null)
{
$this->bucket = $bucket;
$this->key = $key;
$this->tag = $tag;
$this->client = null;
}
/**
* Retrieve the Object to which this link points.
* @param integer $r - The R-value to use.
* @return Object
*/
public function get($r = null)
{
return $this->client->bucket($this->bucket)->get($this->key, $r);
}
/**
* Retrieve the Object to which this link points, as a binary.
* @param integer $r - The R-value to use.
* @return Object
*/
public function getBinary($r = null)
{
return $this->client->bucket($this->bucket)->getBinary($this->key, $r);
}
/**
* Get the bucket name of this link.
* @return string
*/
public function getBucket()
{
return $this->bucket;
}
/**
* Set the bucket name of this link.
* @param $bucket
* @return $this
*/
public function setBucket($bucket)
{
$this->bucket = $bucket;
return $this;
}
/**
* Get the key of this link.
* @return string
*/
public function getKey()
{
return $this->key;
}
/**
* Set the key of this link.
* @param string $key - The key.
* @return $this
*/
public function setKey($key)
{
$this->key = $key;
return $this;
}
/**
* Get the tag of this link.
* @return string
*/
public function getTag()
{
if ($this->tag == null) {
return $this->bucket;
} else {
return $this->tag;
}
}
/**
* Set the tag of this link.
* @param string $tag - The tag.
* @return $this
*/
public function setTag($tag)
{
$this->tag = $tag;
return $this;
}
/**
* Convert this Link object to a link header string. Used internally.
*/
public function toLinkHeader($client)
{
$link = "" .
$client->prefix . "/" .
urlencode($this->bucket) . "/" .
urlencode($this->key) . ">; riaktag=\"" .
urlencode($this->getTag()) . "\"";
return $link;
}
/**
* Return true if the links are equal.
* @param Link $link - A Link object.
* @return boolean
*/
public function isEqual($link)
{
$is_equal =
($this->bucket == $link->bucket) &&
($this->key == $link->key) &&
($this->getTag() == $link->getTag());
return $is_equal;
}
}PK 9AVTrP2 P2 src/Basho/Riak/MapReduce.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak;
use Basho\Riak\Exception,
Basho\Riak\Link,
Basho\Riak\Link\Phase as LinkPhase,
Basho\Riak\MapReduce\Phase as MapReducePhase,
Basho\Riak\Object,
Basho\Riak\Utils;
/**
* MapReduce
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class MapReduce
{
/**
* Construct a Map/Reduce object.
*
* @param \Basho\Riak\Riak $client - A Client object.
* @return MapReduce
*/
public function __construct($client)
{
$this->client = $client;
$this->phases = array();
$this->inputs = array();
$this->input_mode = null;
$this->key_filters = array();
$this->index = array();
}
/**
* Add inputs to a map/reduce operation
*
* This method takes three different forms,
* depending on the provided inputs. You can
* specify either a Object, a string bucket name,
* or a bucket, key, and additional arg.
*
* @param mixed $arg1 Object or Bucket
* @param mixed $arg2 Key or blank
* @param mixed $arg3 Arg or blank
* @return MapReduce
*/
public function add($arg1, $arg2 = null, $arg3 = null)
{
if (func_num_args() == 1) {
if ($arg1 instanceof Object) {
return $this->add_object($arg1);
} else {
return $this->add_bucket($arg1);
}
}
return $this->add_bucket_key_data($arg1, (string)$arg2, $arg3);
}
/**
* Private
*
* @ignore
*/
private function add_object($obj)
{
return $this->add_bucket_key_data($obj->bucket->name, $obj->key, null);
}
/**
* Private
*
* @ignore
*/
private function add_bucket_key_data($bucket, $key, $data)
{
if ($this->input_mode == "bucket") {
throw new Exception("Already added a bucket, can't add an object.");
}
$this->inputs[] = array($bucket, $key, $data);
return $this;
}
/**
* Private
*
* @ignore
* @return $this
*/
private function add_bucket($bucket)
{
$this->input_mode = "bucket";
$this->inputs = $bucket;
return $this;
}
/**
* Begin a map/reduce operation using a Search
*
* This command will
* return an error unless executed against a Riak Search cluster.
*
* @param string $bucket - The Bucket to search. @param string
* query - The Query to execute. (Lucene syntax.) @return \Basho\Riak\MapReduce
*/
public function search($bucket, $query)
{
$this->inputs = array(
"module" => "riak_search",
"function" => "mapred_search",
"arg" => array($bucket, $query)
);
return $this;
}
/**
* Add a link phase to the map/reduce operation
*
* @param string $bucket - Bucket name (default '_', which means all
* buckets)
* @param string $tag - Tag (default '_', which means all buckets)
* @param boolean $keep - Flag whether to keep results from this
* stage in the map/reduce. (default FALSE, unless this is the last
* step in the phase)
* @return $this
*/
public function link($bucket = '_', $tag = '_', $keep = false)
{
$this->phases[] = new LinkPhase($bucket, $tag, $keep);
return $this;
}
/**
* Add a map phase to the map/reduce operation
*
* @param mixed $function - Either a named Javascript function (ie:
* "Riak.mapValues"), or an anonymous javascript function (ie:
* "function(...) { ... }" or an array ["erlang_module",
* "function"].
* @param array() $options - An optional associative array
* containing "language", "keep" flag, and/or "arg".
* @return $this
*/
public function map($function, $options = array())
{
$language = is_array($function) ? "erlang" : "javascript";
$this->phases[] = new MapReducePhase("map",
$function,
Utils::get_value("language", $options, $language),
Utils::get_value("keep", $options, false),
Utils::get_value("arg", $options, null));
return $this;
}
/**
* Add a reduce phase to the map/reduce operation
*
* @param mixed $function - Either a named Javascript function (ie:
* "Riak.mapValues"), or an anonymous javascript function (ie:
* "function(...) { ... }" or an array ["erlang_module",
* "function"].
* @param array() $options - An optional associative array
* containing "language", "keep" flag, and/or "arg".
* @return $this
*/
public function reduce($function, $options = array())
{
$language = is_array($function) ? "erlang" : "javascript";
$this->phases[] = new MapReducePhase("reduce",
$function,
Utils::get_value("language", $options, $language),
Utils::get_value("keep", $options, false),
Utils::get_value("arg", $options, null));
return $this;
}
/**
* Add a key filter to the map/reduce operation
*
* If there are already
* existing filters, an "and" condition will be used to combine them.
* Alias for key_filter_and
*
* @param array $filter - a key filter (ie:
* ->key_filter(
* array("tokenize", "-", 2),
* array("between", "20110601", "20110630")
* )
* @return $this
*/
public function key_filter(array $filter /*. ,$filter .*/)
{
$args = func_get_args();
array_unshift($args, 'and');
return call_user_func_array(array($this, 'key_filter_operator'), $args);
}
/**
* Add a key filter to the map/reduce operation
*
* If there are already
* existing filters, an "and" condition will be used to combine them.
*
* @param array $filter - a key filter (ie:
* ->key_filter(
* array("tokenize", "-", 2),
* array("between", "20110601", "20110630")
* )
* @return $this
*/
public function key_filter_and(array $filter)
{
$args = func_get_args();
array_unshift($args, 'and');
return call_user_func_array(array($this, 'key_filter_operator'), $args);
}
/**
* Adds a key filter to the map/reduce operation
*
* If there are already
* existing filters, an "or" condition will be used to combine with the
* existing filters.
*
* @param array $filter
* @return $this
*/
public function key_filter_or(array $filter /*. ,$filter .*/)
{
$args = func_get_args();
array_unshift($args, 'or');
return call_user_func_array(array($this, 'key_filter_operator'), $args);
}
/**
* Adds a key filter to the map/reduce operation
*
* If there are already
* existing filters, the provided conditional operator will be used
* to combine with the existing filters.
*
* @param string $operator - Operator (usually "and" or "or")
* @param array $filter
* @return $this
*/
public function key_filter_operator($operator, $filter /*. ,$filter .*/)
{
$filters = func_get_args();
array_shift($filters);
if ($this->input_mode != 'bucket') {
throw new Exception("Key filters can only be used in bucket mode");
}
if (count($this->index)) {
throw new Exception("You cannot use index search and key filters on the same operation");
}
if (count($this->key_filters) > 0) {
$this->key_filters = array(
array(
$operator,
$this->key_filters,
$filters
)
);
} else {
$this->key_filters = $filters;
}
return $this;
}
/**
* Performs an index search as part of a Map/Reduce operation
*
* Note that you can only do index searches on a bucket, so
* this is incompatible with object or key operations, as well
* as key filter operations.
*
* @param string $indexName The name of the index to search.
* @param string $indexType The index type ('bin' or 'int')
* @param string|int $startOrExact Start value to search for, or
* exact value if no end value specified.
* @param string|int optional $end End value to search for during
* a range search
* @return $this
*/
public function indexSearch($indexName, $indexType, $startOrExact, $end = null)
{
// Check prerequisites
if (count($this->key_filters)) {
throw new Exception("You cannot use index search and key filters on the same operation");
}
if ($this->input_mode != 'bucket') {
throw new Exception("Key filters can only be used in bucket mode");
}
if ($end === null) {
$this->index = array(
'index' => "{$indexName}_{$indexType}",
'key' => urlencode($startOrExact)
);
} else {
$this->index = array(
'index' => "{$indexName}_{$indexType}",
'start' => urlencode($startOrExact),
'end' => urlencode($end)
);
}
return $this;
}
/**
* Run the map/reduce operation
*
* Returns an array of results, or an
* array of Link objects if the last phase is a link phase.
*
* @param integer $timeout - Timeout in seconds.
* @return array()
*/
public function run($timeout = null)
{
$num_phases = count($this->phases);
$linkResultsFlag = false;
# If there are no phases, then just echo the inputs back to the user.
if ($num_phases == 0) {
$this->reduce(array("riak_kv_mapreduce", "reduce_identity"));
$num_phases = 1;
$linkResultsFlag = true;
}
# Convert all phases to associative arrays. Also,
# if none of the phases are accumulating, then set the last one to
# accumulate.
$keep_flag = false;
$query = array();
for ($i = 0; $i < $num_phases; $i++) {
$phase = $this->phases[$i];
if ($i == ($num_phases - 1) && !$keep_flag) {
$phase->keep = true;
}
if ($phase->keep) {
$keep_flag = true;
}
$query[] = $phase->to_array();
}
# Add key filters if applicable
if ($this->input_mode == 'bucket' && count($this->key_filters) > 0) {
$this->inputs = array(
'bucket' => $this->inputs,
'key_filters' => $this->key_filters
);
}
# Add index search if applicable
if ($this->input_mode == 'bucket' && count($this->index) > 0) {
$this->inputs = array_merge(array('bucket' => $this->inputs), $this->index);
}
# Construct the job, optionally set the timeout...
$job = array("inputs" => $this->inputs, "query" => $query);
if ($timeout != null) {
$job["timeout"] = $timeout;
}
$content = json_encode($job);
# Do the request...
$url = "http://" . $this->client->host . ":" . $this->client->port . "/" . $this->client->mapred_prefix;
$response = Utils::httpRequest('POST', $url, array('Content-type: application/json'), $content);
$result = json_decode($response[1]);
# If the last phase is NOT a link phase, then return the result.
$linkResultsFlag |= (end($this->phases) instanceof LinkPhase);
# If we don't need to link results, then just return.
if (!$linkResultsFlag) {
return $result;
}
# Otherwise, if the last phase IS a link phase, then convert the
# results to Link objects.
$a = array();
foreach ($result as $r) {
$tag = isset($r[2]) ? $r[2] : null;
$link = new Link($r[0], $r[1], $tag);
$link->client = $this->client;
$a[] = $link;
}
return $a;
}
}
PK 9AV$
src/Basho/Riak/Exception.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak;
/**
* Exception
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class Exception extends \Exception
{
}PK 9AVrV. . src/Basho/Riak/Bucket.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak;
use Basho\Riak\Link;
/**
* Bucket
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class Bucket
{
/**
* @var Riak|null
*/
protected $client = null;
/**
* Construct a Bucket object
*
* @param Riak $client Riak Client object
* @param string $name Bucket name
*/
public function __construct(Riak $client, $name)
{
$this->client = $client;
$this->name = $name;
$this->r = null;
$this->w = null;
$this->dw = null;
}
/**
* Get the bucket name.
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Get the R-value for this bucket
*
* Returns the buckets R-value If it is set, otherwise return the R-value for the client.
*
* @return int
*/
public function getR()
{
if ($this->r != null) {
return $this->r;
}
return $this->client->getR();
}
/**
* Set the R-value for this bucket
*
* get(...) and getBinary(...)
* operations that do not specify an R-value will use this value.
*
* @see \Basho\Riak\Bucket::get()
* @see \Basho\Riak\Bucket::getBinary()
* @param integer $r - The new R-value.
*
* @return $this
*/
public function setR($r)
{
$this->r = $r;
return $this;
}
/**
* Get the W-value for this bucket
*
* If it is set for this bucket, otherwise return the W-value for the client.
*
* @return int
*/
public function getW()
{
if ($this->w != null) {
return $this->w;
}
return $this->client->getW();
}
/**
* Set the W-value for this bucket
*
* See setR(...) for more information.
*
* @param integer $w - The new W-value.
*
* @return $this
*/
public function setW($w)
{
$this->w = $w;
return $this;
}
/**
* Get the DW-value for this bucket
*
* If it is set for this bucket, otherwise return the DW-value for the client.
*
* @return int
*/
public function getDW()
{
if ($this->dw != null) {
return $this->dw;
}
return $this->client->getDW();
}
/**
* Set the DW-value for this bucket.
*
* See setR(...) for more information.
*
* @param integer $dw - The new DW-value
*
* @return $this
*/
public function setDW($dw)
{
$this->dw = $dw;
return $this;
}
/**
* Create a new Riak object that will be stored as JSON.
*
* @param string $key - Name of the key. (default NULL)
* @param object $data - The data to store. (default NULL)
*
* @return Object
*/
public function newObject($key = null, $data = null)
{
$obj = new Object($this->client, $this, $key);
$obj->setData($data);
$obj->setContentType('application/json');
$obj->jsonize = true;
return $obj;
}
/**
* Create a new Riak object that will be stored as plain text/binary.
*
* @param string $key - Name of the key. (default NULL)
* @param object $data - The data to store.
* @param string $content_type - The content type of the object. (default 'application/json')
*
* @return Object
*/
public function newBinary($key = null, $data, $content_type = 'application/json')
{
$obj = new Object($this->client, $this, $key);
$obj->setData($data);
$obj->setContentType($content_type);
$obj->jsonize = false;
return $obj;
}
/**
* Retrieve a JSON-encoded object from Riak.
*
* @param string $key - Name of the key.
* @param int $r - R-Value of the request (defaults to bucket's R)
*
* @return Object
*/
public function get($key, $r = null)
{
$obj = new Object($this->client, $this, $key);
$obj->jsonize = true;
return $obj->reload($r);
}
/**
* Retrieve a binary/string object from Riak.
*
* @param string $key - Name of the key.
* @param int $r - R-Value of the request (defaults to bucket's R)
*
* @return Object
*/
public function getBinary($key, $r = null)
{
$obj = new Object($this->client, $this, $key);
$obj->jsonize = false;
return $obj->reload($r);
}
/**
* Set the N-value for this bucket
*
* The N-value is the number of replicas
* that will be written of each object in the bucket. Set this once
* before you write any data to the bucket, and never change it
* again, otherwise unpredictable things could happen. This should
* only be used if you know what you are doing.
*
* @param integer $nval - The new N-Val.
*
* @return bool
*/
public function setNVal($nval)
{
return $this->setProperty("n_val", $nval);
}
/**
* Retrieve the N-value for this bucket.
*
* @return integer
*/
public function getNVal()
{
return $this->getProperty("n_val");
}
/**
* Allow conflicting data to be stored
*
* If set to true, then writes with conflicting data will be stored
* and returned to the client. This situation can be detected by
* calling hasSiblings() and getSiblings(). This should only be used
* if you know what you are doing.
*
* @param boolean $bool - True to store and return conflicting writes.
*
* @return bool
*/
public function setAllowMultiples($bool)
{
return $this->setProperty("allow_mult", $bool);
}
/**
* Retrieve the 'allow multiples' setting.
*
* @return Boolean
*/
public function getAllowMultiples()
{
return "true" == $this->getProperty("allow_mult");
}
/**
* Set a bucket property
*
* This should only be used if you know what you are doing.
*
* @param string $key - Property to set.
* @param mixed $value - Property value.
*
* @return bool
*/
public function setProperty($key, $value)
{
return $this->setProperties(array($key => $value));
}
/**
* Retrieve a bucket property.
*
* @param string $key - The property to retrieve.
* @return mixed
*/
public function getProperty($key)
{
$props = $this->getProperties();
if (array_key_exists($key, $props)) {
return $props[$key];
} else {
return null;
}
}
/**
* Set multiple bucket properties in one call
*
* This should only be used if you know what you are doing.
*
* @param array $props - An associative array of $key=>$value.
*
* @return bool
* @throws Exception
*/
public function setProperties($props)
{
# Construct the URL, Headers, and Content...
$url = Utils::buildRestPath($this->client, $this);
$headers = array('Content-Type: application/json');
$content = json_encode(array("props" => $props));
# Run the request...
$response = Utils::httpRequest('PUT', $url, $headers, $content);
# Handle the response...
if ($response == null) {
throw new Exception("Error setting bucket properties.");
}
# Check the response value...
$status = $response[0]['http_code'];
if ($status != 204) {
throw new Exception("Error setting bucket properties.");
}
return true;
}
/**
* Retrieve an associative array of all bucket properties.
*
* @return Array
* @throws Exception
*/
public function getProperties()
{
# Run the request...
$params = array('props' => 'true', 'keys' => 'false');
$url = Utils::buildRestPath($this->client, $this, null, null, $params);
$response = Utils::httpRequest('GET', $url);
# Use a Object to interpret the response, we are just interested in the value.
$obj = new Object($this->client, $this, null);
$obj->populate($response, array(200));
if (!$obj->exists()) {
throw new Exception("Error getting bucket properties.");
}
$props = $obj->getData();
$props = $props["props"];
return $props;
}
/**
* Retrieve an array of all keys in this bucket.
*
* Note: this operation is pretty slow.
*
* @return Array
* @throws Exception
*/
public function getKeys()
{
$params = array('props' => 'false', 'keys' => 'true');
$url = Utils::buildRestPath($this->client, $this, null, null, $params);
$response = Utils::httpRequest('GET', $url);
# Use a Object to interpret the response, we are just interested in the value.
$obj = new Object($this->client, $this, null);
$obj->populate($response, array(200));
if (!$obj->exists()) {
throw new Exception("Error getting bucket properties.");
}
$keys = $obj->getData();
return $keys["keys"];
}
/**
* Search a secondary index
*
* @author Eric Stevens
* @param string $indexName - The name of the index to search
* @param string $indexType - The type of index ('int' or 'bin')
* @param string|int $startOrExact
* @param string|int optional $end
* @param bool $dedupe
*
* @return array of Links
* @throws Exception
*/
public function indexSearch($indexName, $indexType, $startOrExact, $end = null, $dedupe = false)
{
$url = Utils::buildIndexPath($this->client, $this, "{$indexName}_{$indexType}", $startOrExact, $end, null);
$response = Utils::httpRequest('GET', $url);
$obj = new Object($this->client, $this, null);
$obj->populate($response, array(200));
if (!$obj->exists()) {
throw new Exception("Error searching index.");
}
$data = $obj->getData();
$keys = $data["keys"];
$seenKeys = array();
foreach ($keys as $id => &$key) {
if ($dedupe) {
if (isset($seenKeys[$key])) {
unset($keys[$id]);
continue;
}
$seenKeys[$key] = true;
}
$key = new Link($this->name, $key);
$key->client = $this->client;
}
return $keys;
}
/**
* Check if a given key exists in a bucket
*
* @author Edgar Veiga
*
* @param string $key - The key to check
*
* @return bool
* @throws Exception
*/
public function hasKey($key)
{
$url = Utils::buildRestPath($this->client, $this, $key);
$response = Utils::httpRequest('HEAD', $url);
if ($response == null) {
throw new Exception("Error checking if key exists.");
}
$status = $response[0]['http_code'];
if ($status === 200) {
return true;
}
return false;
}
}
PK 9AV!^iZs Zs src/Basho/Riak/Object.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak;
use Basho\Riak\Link;
use Basho\Riak\MapReduce;
/**
* \Basho\Riak\Object
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class Object
{
/**
* @var mixed
*/
protected $data;
/**
* @var Link[]
*/
protected $links;
/**
* @var array Meta data store
* @see \Basho\Riak\Object::setMeta()
* @see \Basho\Riak\Object::getMeta()
* @see \Basho\Riak\Object::getAllMeta()
* @see \Basho\Riak\Object::removeMeta()
* @see \Basho\Riak\Object::removeAllMeta()
*/
protected $meta = array();
/**
* @var array Array of indexes
* @see \Basho\Riak\Object::addIndex()
* @see \Basho\Riak\Object::setIndex()
* @see \Basho\Riak\Object::getIndex()
* @see \Basho\Riak\Object::removeIndex()
* @see \Basho\Riak\Object::removeAllIndexes()
*/
protected $indexes = array();
/**
* @var array Array of automatic indexes
* @see \Basho\Riak\Object::addAutoIndex()
* @see \Basho\Riak\Object::hasAutoIndex()
* @see \Basho\Riak\Object::removeAutoIndex()
* @see \Basho\Riak\Object::removeAllAutoIndexes()
*/
protected $autoIndexes = array();
/**
* Construct a new Object.
* @param Riak $client - A Client object.
* @param Bucket $bucket - A Bucket object.
* @param string $key - An optional key. If not specified, then key
* is generated by server when store(...) is called.
*/
public function __construct($client, $bucket, $key = null)
{
$this->client = $client;
$this->bucket = $bucket;
$this->key = $key;
$this->jsonize = true;
$this->headers = array();
$this->links = array();
$this->siblings = null;
$this->exists = false;
}
/**
* Get the bucket of this object.
*
* @return Bucket
*/
public function getBucket()
{
return $this->bucket;
}
/**
* Get the key of this object.
*
* @return string
*/
public function getKey()
{
return $this->key;
}
/**
* Get the data stored in this object.
*
* Will return a associative array, unless the object
* was constructed with newBinary(...) or getBinary(...),
* in which case this will return a string.
*
* @return array|string
*/
public function getData()
{
return $this->data;
}
/**
* Set the data stored in this object.
*
* This data will be JSON encoded unless
* the object was constructed with
* newBinary(...) or getBinary(...).
*
* @param mixed $data - The data to store.
*
* @return Object
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Get the HTTP status from the last operation on this object.
*
* @return integer
*/
public function status()
{
return $this->headers['http_code'];
}
/**
* Return true if the object exists, false otherwise.
*
* Allows you to detect a get(...) or getBinary(...)
* operation where the object is missing.
*
* @return boolean
*/
public function exists()
{
return $this->exists;
}
/**
* Get the content type of this object.
*
* This is either application/json, or the provided content
* type if the object was created via newBinary(...).
*
* @return string
*/
public function getContentType()
{
return $this->headers['content-type'];
}
/**
* Set the content type of this object.
*
* @param string $content_type - The new content type.
* @return $this
*/
public function setContentType($content_type)
{
$this->headers['content-type'] = $content_type;
return $this;
}
/**
* Get last-modified from the object.
*
* @return \DateTime
*/
public function getLastModified()
{
if (array_key_exists('last-modified', $this->headers)) {
return new \DateTime($this->headers['last-modified']);
} else {
return null;
}
}
/**
* Add a link to a Object.
*
* @param mixed $obj - Either a Object or a Link object.
* @param string $tag - Optional link tag. (default is bucket name,
* ignored if $obj is a Link object.)
*
* @return Object
*/
public function addLink($obj, $tag = null)
{
if ($obj instanceof Link) {
$newlink = $obj;
} else {
$newlink = new Link($obj->bucket->name, $obj->key, $tag);
}
$this->removeLink($newlink);
$this->links[] = $newlink;
return $this;
}
/**
* Remove a link to a Object.
*
* @param mixed $obj - Either a Object or a Link object.
* @param string $tag -
* @param mixed $obj - Either a Object or a Link object.
* @param string $tag - Optional link tag. (default is bucket name,
* ignored if $obj is a Link object.)
*
* @return $this
*/
public function removeLink($obj, $tag = null)
{
if ($obj instanceof Link) {
$old_link = $obj;
} else {
$old_link = new Link($obj->bucket->name, $obj->key, $tag);
}
$a = array();
foreach ($this->links as $link) {
if (!$link->isEqual($old_link)) {
$a[] = $link;
}
}
$this->links = $a;
return $this;
}
/**
* Return an array of Link objects.
*
* @return array()
*/
public function getLinks()
{
# Set the clients before returning...
foreach ($this->links as $link) {
$link->client = $this->client;
}
return $this->links;
}
/** @section Indexes */
/**
* Adds a secondary index to the object
*
* This will create the index if it does not exist, or will
* append an additional value if the index already exists and
* does not contain the provided value.
*
* @param string $indexName
* @param string $indexType - Must be one of 'int' or 'bin' - the
* only two index types supported by Riak
* @param string|int $explicitValue If provided, uses this
* value explicitly. If not provided, this will search the object's
* data for a field with the name $indexName, and use that value.
*
* @return $this
*/
public function addIndex($indexName, $indexType = null, $explicitValue = null)
{
if ($explicitValue === null) {
$this->addAutoIndex($indexName, $indexType);
return $this;
}
if ($indexType !== null) {
$index = strtolower("{$indexName}_{$indexType}");
} else {
$index = strtolower($indexName);
}
if (!isset($this->indexes[$index])) {
$this->indexes[$index] = array();
}
if (false === array_search($explicitValue, $this->indexes[$index])) {
$this->indexes[$index][] = $explicitValue;
}
return $this;
}
/**
* Sets a given index to a specific value or set of values
*
* @param string $indexName
* @param string $indexType - must be 'bin' or 'int'
* @param array|string|int $values
*
* @return $this
*/
public function setIndex($indexName, $indexType = null, $values)
{
if ($indexType !== null) {
$index = strtolower("{$indexName}_{$indexType}");
} else {
$index = strtolower($indexName);
}
$this->indexes[$index] = $values;
return $this;
}
/**
* Gets the current values for the identified index
*
* Note, the NULL value has special meaning - when the object is
* ->store()d, this value will be replaced with the current value
* the value of the field matching $indexName from the object's data
*
* @param string $indexName
* @param string $indexType
*
* @return array
*/
public function getIndex($indexName, $indexType = null)
{
if ($indexType !== null) {
$index = strtolower("{$indexName}_{$indexType}");
} else {
$index = strtolower($indexName);
}
if (!isset($this->indexes[$index])) {
return array();
}
return $this->indexes[$index];
}
/**
* Removes a specific value from a given index
*
* @param string $indexName
* @param string $indexType - must be 'bin' or 'int'
* @param string|int $explicitValue
*
* @return $this
*/
public function removeIndex($indexName, $indexType = null, $explicitValue = null)
{
if ($explicitValue === null) {
$this->removeAutoIndex($indexName, $indexType);
return $this;
}
if ($indexType !== null) {
$index = strtolower("{$indexName}_{$indexType}");
} else {
$index = strtolower($indexName);
}
if (!isset($this->indexes[$index])) {
return $this;
}
if (false !== ($position = array_search($explicitValue, $this->indexes[$index]))) {
unset($this->indexes[$index][$position]);
}
return $this;
}
/**
* Bulk index removal
*
* If $indexName and $indexType are provided, all values for the
* identified index are removed.
* If just $indexName is provided, all values for all types of
* the identified index are removed
* If neither is provided, all indexes are removed from the object
*
* Note that this function will NOT affect auto indexes
*
* @param string $indexName
* @param string $indexType
*
* @return $this
*/
public function removeAllIndexes($indexName = null, $indexType = null)
{
if ($indexName === null) {
$this->indexes = array();
} else {
if ($indexType === null) {
$indexName = strtolower($indexName);
unset($this->indexes["{$indexName}_int"]);
unset($this->indexes["{$indexName}_bin"]);
} else {
unset($this->indexes[strtolower("{$indexName}_{$indexType}")]);
}
}
return $this;
}
/** @section Auto Indexes */
/**
* Adds an automatic secondary index to the object
*
* The value of an automatic secondary index is determined at
* time of ->store() by looking for an $fieldName key
* in the object's data.
*
* @param string $fieldName
* @param string $indexType Must be one of 'int' or 'bin'
*
* @return $this
*/
public function addAutoIndex($fieldName, $indexType = null)
{
if ($indexType !== null) {
$index = strtolower("{$fieldName}_{$indexType}");
} else {
$index = strtolower($fieldName);
}
$this->autoIndexes[$index] = $fieldName;
return $this;
}
/**
* Returns whether the object has a given auto index
*
* @param string $fieldName
* @param string $indexType - must be one of 'int' or 'bin'
*
* @return boolean
*/
public function hasAutoIndex($fieldName, $indexType = null)
{
if ($indexType !== null) {
$index = strtolower("{$fieldName}_{$indexType}");
} else {
$index = strtolower($fieldName);
}
return isset($this->autoIndexes[$index]);
}
/**
* Removes a given auto index from the object
*
* @param string $fieldName
* @param string $indexType
*
* @return $this
*/
public function removeAutoIndex($fieldName, $indexType = null)
{
if ($indexType !== null) {
$index = strtolower("{$fieldName}_{$indexType}");
} else {
$index = strtolower($fieldName);
}
unset($this->autoIndexes[$index]);
return $this;
}
/**
* Removes all auto indexes
*
* If $fieldName is not provided, all auto indexes on the
* object are stripped, otherwise just indexes on the given field
* are stripped.
* If $indexType is not provided, all types of index for the
* given field are stripped, otherwise just a given type is stripped.
*
* @param string $fieldName
* @param string $indexType
*
* @return $this
*/
public function removeAllAutoIndexes($fieldName = null, $indexType = null)
{
if ($fieldName === null) {
$this->autoIndexes = array();
} else {
if ($indexType === null) {
$fieldName = strtolower($fieldName);
unset($this->autoIndexes["{$fieldName}_bin"]);
unset($this->autoIndexes["{$fieldName}_int"]);
} else {
unset($this->autoIndexes[strtolower("{$fieldName}_{$indexType}")]);
}
}
return $this;
}
/** @section Meta Data */
/**
* Gets a given metadata value
*
* Returns null if no metadata value with the given name exists
*
* @param string $metaName
*
* @return string|null
*/
public function getMeta($metaName)
{
$metaName = strtolower($metaName);
if (isset($this->meta[$metaName])) {
return $this->meta[$metaName];
}
return null;
}
/**
* Sets a given metadata value
*
* Overwrites an existing value with
* the same name if it exists.
*
* @param string $metaName
* @param string $value
*
* @return $this
*/
public function setMeta($metaName, $value)
{
$this->meta[strtolower($metaName)] = $value;
return $this;
}
/**
* Removes a given metadata value
*
* @param string $metaName
* @return $this
*/
public function removeMeta($metaName)
{
unset ($this->meta[strtolower($metaName)]);
return $this;
}
/**
* Gets all metadata values
*
* @return array=string
*/
public function getAllMeta()
{
return $this->meta;
}
/**
* Strips all metadata values
*
* @return $this;
*/
public function removeAllMeta()
{
$this->meta = array();
return $this;
}
/**
* Store the object in Riak
*
* When this operation completes, the
* object could contain new metadata and possibly new data if Riak
* contains a newer version of the object according to the object's
* vector clock.
*
* @param integer $w - W-value, wait for this many partitions to respond
* before returning to client.
* @param integer $dw - DW-value, wait for this many partitions to
* confirm the write before returning to client.
* @param string $returnbody
*
* @return $this
* @throws Exception
*/
public function store($w = null, $dw = null, $returnbody = 'true')
{
# Use defaults if not specified...
$w = $w ? $w : $this->bucket->getW();
$dw = $dw ? $dw : $this->bucket->getDW();
$status_codes = array(200, 201, 300);
$method = 'POST';
# Construct the URL...
$params = array('returnbody' => $returnbody, 'w' => $w, 'dw' => $dw);
$url = Utils::buildRestPath($this->client, $this->bucket, $this->key, null, $params);
# Construct the headers...
$headers = array(
'Accept: text/plain, */*; q=0.5',
'Content-Type: ' . $this->getContentType(),
'X-Riak-ClientId: ' . $this->client->getClientID()
);
# Add the vclock if it exists...
if ($this->vclock() != null) {
$headers[] = 'X-Riak-Vclock: ' . $this->vclock();
}
# Add the Links...
foreach ($this->links as $link) {
$headers[] = 'Link: ' . $link->toLinkHeader($this->client);
}
# Add the auto indexes...
$collisions = array();
if (!empty($this->autoIndexes) && !is_array($this->data)) {
throw new Exception('Unsupported data type for auto indexing feature. Object must be an array to use auto indexes.');
}
foreach ($this->autoIndexes as $index => $fieldName) {
$value = null;
// look up the value
if (isset($this->data[$fieldName])) {
$value = $this->data[$fieldName];
$headers[] = "x-riak-index-$index: " . urlencode($value);
// look for value collisions with normal indexes
if (isset($this->indexes[$index])) {
if (false !== array_search($value, $this->indexes[$index])) {
$collisions[$index] = $value;
}
}
}
}
count($this->autoIndexes) > 0
? $this->meta['x-rc-autoindex'] = json_encode($this->autoIndexes)
: $this->meta['x-rc-autoindex'] = null;
count($collisions) > 0
? $this->meta['x-rc-autoindexcollision'] = json_encode($collisions)
: $this->meta['x-rc-autoindexcollision'] = null;
# Add the indexes
foreach ($this->indexes as $index => $values) {
$headers[] = "x-riak-index-$index: " . join(', ', array_map('urlencode', $values));
}
# Add the metadata...
foreach ($this->meta as $metaName => $metaValue) {
if ($metaValue !== null) {
$headers[] = "X-Riak-Meta-$metaName: $metaValue";
}
}
if ($this->jsonize) {
$content = json_encode($this->getData());
} else {
$content = $this->getData();
}
// if key is provided, this is a put, support 'No Content' code
if ($this->key) {
$method = 'PUT';
$status_codes[] = 204;
}
# Run the operation.
$response = Utils::httpRequest($method, $url, $headers, $content);
$this->populate($response, $status_codes);
return $this;
}
/**
* Reload the object from Riak
*
* When this operation completes, the
* object could contain new metadata and a new value, if the object
* was updated in Riak since it was last retrieved.
*
* @param integer $r - R-Value, wait for this many partitions to respond
* before returning to client.
*
* @return $this
*/
public function reload($r = null)
{
$r = $r ? $r : $this->bucket->getR();
$params = array('r' => $r);
$url = Utils::buildRestPath($this->client, $this->bucket, $this->key, null, $params);
$response = Utils::httpRequest('GET', $url);
$this->populate($response, array(200, 300, 404));
# If there are siblings, load the data for the first one by default...
if ($this->hasSiblings()) {
$obj = $this->getSibling(0);
$this->setData($obj->getData());
}
return $this;
}
/**
* Delete this object from Riak
*
* @param integer $dw - DW-value. Wait until this many partitions have
* deleted the object before responding.
* @return $this
*/
public function delete($dw = null)
{
# Use defaults if not specified...
$dw = $dw ? $dw : $this->bucket->getDW();
# Construct the URL...
$params = array('dw' => $dw);
$url = Utils::buildRestPath($this->client, $this->bucket, $this->key, null, $params);
# Run the operation...
$response = Utils::httpRequest('DELETE', $url);
$this->populate($response, array(204, 404));
return $this;
}
/**
* Reset this object.
*
* @return $this
*/
private function clear()
{
$this->headers = array();
$this->links = array();
$this->data = null;
$this->exists = false;
$this->siblings = null;
$this->indexes = array();
$this->autoIndexes = array();
$this->meta = array();
return $this;
}
/**
* Get the vclock of this object.
*
* @return string
*/
private function vclock()
{
if (array_key_exists('x-riak-vclock', $this->headers)) {
return $this->headers['x-riak-vclock'];
} else {
return null;
}
}
/**
* Populate object with Utils::httpRequest expected statuses
*
* Given the output of Utils::httpRequest and a list of
* statuses, populate the object. Only for use by the Riak client
* library
*
* @ignore
* @param $response
* @param $expected_statuses
*
* @return $this
* @throws Exception
*/
public function populate($response, $expected_statuses)
{
$this->clear();
# If no response given, then return.
if ($response == null) {
return $this;
}
# Update the object...
$this->headers = $response[0];
$this->data = $response[1];
$status = $this->status();
# Check if the server is down (status==0)
if ($status == 0) {
$m = 'Could not contact Riak Server: http://' . $this->client->host . ':' . $this->client->port . '!';
throw new Exception($m);
}
# Verify that we got one of the expected statuses. Otherwise, throw an exception.
if (!in_array($status, $expected_statuses)) {
$m = 'Expected status ' . implode(
' or ',
$expected_statuses
) . ', received ' . $status . ' with body: ' . $this->data;
throw new Exception($m);
}
# If 404 (Not Found), then clear the object.
if ($status == 404) {
$this->clear();
return $this;
}
# If we are here, then the object exists...
$this->exists = true;
# Parse the link header...
if (array_key_exists("link", $this->headers)) {
$this->populateLinks($this->headers["link"]);
}
# Parse the index and metadata headers
$this->indexes = array();
$this->autoIndexes = array();
$this->meta = array();
foreach ($this->headers as $key => $val) {
if (preg_match('~^x-riak-([^-]+)-(.+)$~', $key, $matches)) {
switch ($matches[1]) {
case 'index':
$index = substr($matches[2], 0, strrpos($matches[2], '_'));
$type = substr($matches[2], strlen($index) + 1);
$this->setIndex($index, $type, array_map('urldecode', explode(', ', $val)));
break;
case 'meta':
$this->meta[$matches[2]] = $val;
break;
}
}
}
# If 300 (Siblings), then load the first sibling, and
# store the rest.
if ($status == 300) {
$siblings = explode("\n", trim($this->data));
array_shift($siblings); # Get rid of 'Siblings:' string.
$this->siblings = $siblings;
$this->exists = true;
return $this;
}
if ($status == 201) {
$path_parts = explode('/', $this->headers['location']);
$this->key = array_pop($path_parts);
}
# Possibly json_decode...
if (($status == 200 || $status == 201) && $this->jsonize) {
$this->data = json_decode($this->data, true);
}
# Look for auto indexes and deindex explicit values if appropriate
if (isset($this->meta['x-rc-autoindex'])) {
# dereference the autoindexes
$this->autoIndexes = json_decode($this->meta['x-rc-autoindex'], true);
$collisions = isset($this->meta['x-rc-autoindexcollision']) ? json_decode(
$this->meta['x-rc-autoindexcollision'],
true
) : array();
foreach ($this->autoIndexes as $index => $fieldName) {
$value = null;
if (isset($this->data[$fieldName])) {
$value = $this->data[$fieldName];
if (isset($collisions[$index]) && $collisions[$index] === $value) {
// Don't strip this value, it's an explicit index.
} else {
if ($value !== null) {
$this->removeIndex($index, null, $value);
}
}
}
}
}
return $this;
}
/**
* Private.
*
* @ignore
* @return $this
*/
private function populateLinks($linkHeaders)
{
$linkHeaders = explode(",", trim($linkHeaders));
foreach ($linkHeaders as $linkHeader) {
$linkHeader = trim($linkHeader);
$matches = array();
$result = preg_match("/\<\/([^\/]+)\/([^\/]+)\/([^\/]+)\>; ?riaktag=\"([^\"]+)\"/", $linkHeader, $matches);
if ($result == 1) {
$this->links[] = new Link(urldecode($matches[2]), urldecode($matches[3]), urldecode($matches[4]));
}
}
return $this;
}
/**
* Return true if this object has siblings.
*
* @return boolean
*/
public function hasSiblings()
{
return ($this->getSiblingCount() > 0);
}
/**
* Get the number of siblings that this object contains.
*
* @return integer
*/
public function getSiblingCount()
{
return count($this->siblings);
}
/**
* Retrieve a sibling by sibling number.
*
* @param integer $i - Sibling number.
* @param integer $r - R-Value. Wait until this many partitions
* have responded before returning to client.
*
* @return Object.
*/
public function getSibling($i, $r = null)
{
# Use defaults if not specified.
$r = $r ? $r : $this->bucket->getR();
# Run the request...
$vtag = $this->siblings[$i];
$params = array('r' => $r, 'vtag' => $vtag);
$url = Utils::buildRestPath($this->client, $this->bucket, $this->key, null, $params);
$response = Utils::httpRequest('GET', $url);
# Respond with a new object...
$obj = new Object($this->client, $this->bucket, $this->key);
$obj->jsonize = $this->jsonize;
$obj->populate($response, array(200));
return $obj;
}
/**
* Retrieve an array of siblings.
*
* @param integer $r - R-Value. Wait until this many partitions have
* responded before returning to client.
*
* @return array of Object
*/
public function getSiblings($r = null)
{
$a = array();
for ($i = 0; $i < $this->getSiblingCount(); $i++) {
$a[] = $this->getSibling($i, $r);
}
return $a;
}
/**
* Start assembling a Map/Reduce operation.
*
* @see MapReduce::add()
* @param $params
*
* @return MapReduce
*/
public function add($params)
{
$mr = new MapReduce($this->client);
$mr->add($this->bucket->name, $this->key);
$args = func_get_args();
return call_user_func_array(array(&$mr, "add"), $args);
}
/**
* Start assembling a Map/Reduce operation.
*
* @see MapReduce::link()
* @param $params
*
* @return MapReduce
*/
public function link($params)
{
$mr = new MapReduce($this->client);
$mr->add($this->bucket->name, $this->key);
$args = func_get_args();
return call_user_func_array(array(&$mr, "link"), $args);
}
/**
* Start assembling a Map/Reduce operation.
*
* @see MapReduce::map()
* @param $params
*
* @return MapReduce
*/
public function map($params)
{
$mr = new MapReduce($this->client);
$mr->add($this->bucket->name, $this->key);
$args = func_get_args();
return call_user_func_array(array(&$mr, "map"), $args);
}
/**
* Start assembling a Map/Reduce operation.
*
* @see MapReduce::reduce()
* @param $params
*
* @return MapReduce
*/
public function reduce($params)
{
$mr = new MapReduce($this->client);
$mr->add($this->bucket->name, $this->key);
$args = func_get_args();
return call_user_func_array(array(&$mr, "reduce"), $args);
}
}
PK 9AVF by y src/Basho/Riak/Riak.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak;
use Basho\Riak\Bucket,
Basho\Riak\MapReduce,
Basho\Riak\Utils;
/**
* Riak
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class Riak
{
/**
* Construct a new Client object.
*
* @param string $host - Hostname or IP address (default '127.0.0.1')
* @param int $port - Port number (default 8098)
* @param string $prefix - Interface prefix (default "riak")
* @param string $mapred_prefix - MapReduce prefix (default "mapred")
*/
public function __construct($host = '127.0.0.1', $port = 8098, $prefix = 'riak', $mapred_prefix = 'mapred')
{
$this->host = $host;
$this->port = $port;
$this->prefix = $prefix;
$this->mapred_prefix = $mapred_prefix;
$this->indexPrefix = 'buckets';
$this->clientid = 'php_' . base_convert(mt_rand(), 10, 36);
$this->r = 2;
$this->w = 2;
$this->dw = 2;
}
/**
* Get the R-value setting for this Client
*
* Default: 2
*
* @return integer
*/
public function getR()
{
return $this->r;
}
/**
* Set the R-value for this Client
*
* This value will be used
* for any calls to get(...) or getBinary(...) where 1) no
* R-value is specified in the method call and 2) no R-value has
* been set in the Bucket.
*
* @param integer $r - The R value.
* @return $this
*/
public function setR($r)
{
$this->r = $r;
return $this;
}
/**
* Get the W-value setting for this Client
*
* Default: 2
*
* @return integer
*/
public function getW()
{
return $this->w;
}
/**
* Set the W-value for this Client
*
* See setR(...) for a description of how these values are used.
*
* @param integer $w - The W value.
* @return $this
*/
public function setW($w)
{
$this->w = $w;
return $this;
}
/**
* Get the DW-value for this ClientOBject
*
* Default: 2
*
* @return integer
*/
public function getDW()
{
return $this->dw;
}
/**
* Set the DW-value for this Client
*
* See setR(...) for a description of how these values are used.
*
* @param integer $dw - The DW value.
* @return $this
*/
public function setDW($dw)
{
$this->dw = $dw;
return $this;
}
/**
* Get the clientID for this Client.
*
* @return string
*/
public function getClientID()
{
return $this->clientid;
}
/**
* Set the clientID for this Client
*
* Should not be called unless you know what you are doing.
*
* @param string $clientID - The new clientID.
* @return $this
*/
public function setClientID($clientid)
{
$this->clientid = $clientid;
return $this;
}
/**
* Get the bucket by the specified name
*
* Since buckets always exist, this will always return a Bucket.
*
* @return Bucket
*/
public function bucket($name)
{
return new Bucket($this, $name);
}
/**
* Get all buckets
*
* @return array() of Bucket objects
*/
public function buckets()
{
$url = Utils::buildRestPath($this);
$response = Utils::httpRequest('GET', $url . '?buckets=true');
$response_obj = json_decode($response[1]);
$buckets = array();
foreach ($response_obj->buckets as $name) {
$buckets[] = $this->bucket($name);
}
return $buckets;
}
/**
* Check if the Riak server for this Client is alive
*
* @return boolean
*/
public function isAlive()
{
$url = 'http://' . $this->host . ':' . $this->port . '/ping';
$response = Utils::httpRequest('GET', $url);
return ($response != null) && ($response[1] == 'OK');
}
# MAP/REDUCE/LINK FUNCTIONS
/**
* Start assembling a Map/Reduce operation
*
* @see MapReduce::add()
* @return MapReduce
*/
public function add($params)
{
$mr = new MapReduce($this);
$args = func_get_args();
return call_user_func_array(array(&$mr, "add"), $args);
}
/**
* Start assembling a Map/Reduce operation
*
* This command will return an error unless
* executed against a Riak Search cluster.
*
* @see MapReduce::search()
* @return MapReduce
*/
public function search($params)
{
$mr = new MapReduce($this);
$args = func_get_args();
return call_user_func_array(array(&$mr, "search"), $args);
}
/**
* Start assembling a Map/Reduce operation.
*
* @see MapReduce::link()
*/
public function link($params)
{
$mr = new MapReduce($this);
$args = func_get_args();
return call_user_func_array(array(&$mr, "link"), $args);
}
/**
* Start assembling a Map/Reduce operation.
*
* @see MapReduce::map()
*/
public function map($params)
{
$mr = new MapReduce($this);
$args = func_get_args();
return call_user_func_array(array(&$mr, "map"), $args);
}
/**
* Start assembling a Map/Reduce operation.
*
* @see MapReduce::reduce()
*/
public function reduce($params)
{
$mr = new MapReduce($this);
$args = func_get_args();
return call_user_func_array(array(&$mr, "reduce"), $args);
}
}
PK 9AV& src/Basho/Riak/Utils.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak;
use Basho\Riak\Bucket,
Basho\Riak\Riak,
Basho\Riak\StringIO;
/**
* Utils
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class Utils
{
/**
* Fetch a value from an array by it's key, or default if not exists
*
* @param mixed $key Key to fetch
* @param array $array Array to fetch from
* @param mixed $defaultValue Default to return if not exists
*
* @return mixed
*/
public static function get_value($key, $array, $defaultValue)
{
if (array_key_exists($key, $array)) {
return $array[$key];
} else {
return $defaultValue;
}
}
/**
* Construct REST URLs
*
* Given a Client, Bucket, Key, LinkSpec, and Params,
* construct and return a URL.
*
* @param \Basho\Riak\Riak
* @param \Basho\Riak\Bucket $bucket
* @param string $key
* @param string $spec
* @param string $params Array of key-value param pairs
* @return string
*/
public static function buildRestPath($client, $bucket = null, $key = null, $spec = null, $params = null)
{
# Build 'http://hostname:port/prefix/bucket'
$path = 'http://';
$path .= $client->host . ':' . $client->port;
$path .= '/' . $client->prefix;
# Add '.../bucket'
if (!is_null($bucket) && $bucket instanceof Bucket) {
$path .= '/' . urlencode($bucket->name);
}
# Add '.../key'
if (!is_null($key)) {
$path .= '/' . urlencode($key);
}
# Add '.../bucket,tag,acc/bucket,tag,acc'
if (!is_null($spec)) {
$s = '';
foreach ($spec as $el) {
if ($s != '') {
$s .= '/';
}
$s .= urlencode($el[0]) . ',' . urlencode($el[1]) . ',' . $el[2] . '/';
}
$path .= '/' . $s;
}
# Add query parameters.
if (!is_null($params)) {
$s = '';
foreach ($params as $key => $value) {
if ($s != '') {
$s .= '&';
}
$s .= urlencode($key) . '=' . urlencode($value);
}
$path .= '?' . $s;
}
return $path;
}
/**
* Construct secondary index URLs
*
* Given a Client, Bucket, Key, LinkSpec, and Params,
* construct and return a URL for searching secondary indexes.
*
* @author Eric Stevens
*
* @param \Basho\Riak\Riak $client
* @param \Basho\Riak\Bucket $bucket
* @param string $index - Index Name & type (eg, "indexName_bin")
* @param string|int $start - Starting value or exact match if no ending value
* @param string|int $end - Ending value for range search
* @return string URL
*/
public static function buildIndexPath(Riak $client, Bucket $bucket, $index, $start, $end = null)
{
# Build 'http://hostname:port/prefix/bucket'
$path = array('http:/', $client->host . ':' . $client->port, $client->indexPrefix);
# Add '.../bucket'
$path[] = urlencode($bucket->name);
# Add '.../index'
$path[] = 'index';
# Add '.../index_type'
$path[] = urlencode($index);
# Add .../(start|exact)
$path[] = urlencode($start);
if (!is_null($end)) {
$path[] = urlencode($end);
}
// faster than repeated string concatenations
$path = join('/', $path);
return $path;
}
/**
* Send HTTP request
*
* Given a Method, URL, Headers, and Body, perform and HTTP request,
* and return an array of arity 2 containing an associative array of
* response headers and the response body.
*
* @return array
*/
public static function httpRequest($method, $url, $request_headers = array(), $obj = '')
{
# Set up curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
if ($method == 'GET') {
curl_setopt($ch, CURLOPT_HTTPGET, 1);
} else {
if ($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $obj);
} else {
if ($method == 'PUT') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $obj);
} else {
if ($method == 'DELETE') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
} else {
if ($method == 'HEAD') {
curl_setopt($ch, CURLOPT_NOBODY, 1);
}
}
}
}
}
# Capture the response headers...
$response_headers_io = new StringIO();
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$response_headers_io, 'write'));
# Capture the response body...
$response_body_io = new StringIO();
curl_setopt($ch, CURLOPT_WRITEFUNCTION, array(&$response_body_io, 'write'));
try {
# Run the request.
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
# Get the headers...
$parsed_headers = Utils::parseHttpHeaders($response_headers_io->contents());
$response_headers = array("http_code" => $http_code);
foreach ($parsed_headers as $key => $value) {
$response_headers[strtolower($key)] = $value;
}
# Get the body...
$response_body = $response_body_io->contents();
# Return a new RiakResponse object.
return array($response_headers, $response_body);
} catch (Exception $e) {
curl_close($ch);
error_log('Error: ' . $e->getMessage());
return null;
}
}
/**
* Parse HTTP headers
*
* Parse an HTTP Header string into an asssociative array of
* response headers.
*
* @param mixed $headers
*
* @return array
*/
static function parseHttpHeaders($headers)
{
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $headers));
foreach ($fields as $field) {
if (preg_match('/([^:]+): (.+)/m', $field, $match)) {
$match[1] = preg_replace_callback(
'/(?<=^|[\x09\x20\x2D])./',
function ($matches) {
return strtoupper($matches[0]);
}, strtolower(trim($match[1]))
);
if (isset($retVal[$match[1]])) {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
}
return $retVal;
}
}
PK 9AVs< < src/Basho/Riak/StringIO.phpnu W+A so we can send you a copy immediately.
*
* @category Basho
* @copyright Copyright (c) 2013 Basho Technologies, Inc. and contributors.
*/
namespace Basho\Riak;
/**
* StringIO
*
* @category Basho
* @author Riak team (https://github.com/basho/riak-php-client/contributors)
*/
class StringIO
{
/**
* Construct a StringIO object.
*/
public function __construct()
{
$this->contents = '';
}
/**
* Add data to contents
*
* @param resource $ch Curl Resource Handler (unused)
* @param string $data Data to add to contents
*
* @return int
*/
public function write($ch, $data)
{
$this->contents .= $data;
return strlen($data);
}
/**
* Retrieve current contents
*
* @return string
*/
public function contents()
{
return $this->contents;
}
}PK 9AV' ' LICENSEnu W+A PK 9AVǴ ' generate-docs.phpnu W+A PK 9AVb{+ + .travis.ymlnu W+A PK 9AV:
P, composer.jsonnu W+A PK 9AVT T
. phpdoc.xmlnu W+A PK 9AVUY Y "2 tests/integration/TestSuite.phpnu W+A PK 9AV8 tests/integration/test.phpnu W+A PK 9AV
-~
E .gitignorenu W+A PK 9AVBR0B 0B README.mdnu W+A PK 9AVD< src/Basho/Riak/Link/Phase.phpnu W+A PK 9AV`% " src/Basho/Riak/MapReduce/Phase.phpnu W+A PK 9AV~f- src/Basho/Riak/Link.phpnu W+A PK 9AVTrP2 P2 K src/Basho/Riak/MapReduce.phpnu W+A PK 9AV$
src/Basho/Riak/Exception.phpnu W+A PK 9AVrV. . =$ src/Basho/Riak/Bucket.phpnu W+A PK 9AV!^iZs Zs MS src/Basho/Riak/Object.phpnu W+A PK 9AVF by y src/Basho/Riak/Riak.phpnu W+A PK 9AV& src/Basho/Riak/Utils.phpnu W+A PK 9AVs< < src/Basho/Riak/StringIO.phpnu W+A PK P