Permalink
Browse files

Merge branch 'release-0.2.0'

  • Loading branch information...
2 parents 8177e89 + 07d28d7 commit f4339440abe2e7c999ddddb58b804aed7a77bcae @trq trq committed Mar 4, 2012
View
BIN build/proem.phar
Binary file not shown.
View
63 lib/Proem/Api/Dispatch/Payload.php
@@ -35,7 +35,7 @@
/**
* Proem\Api\Dispatch\Payload
*/
-class Payload
+class Payload extends KeyValStore
{
/**
* A flag to keep note as to wether or not this Payload is populated
@@ -45,67 +45,6 @@ class Payload
private $populated = false;
/**
- * Store the actual data.
- *
- * @var array
- */
- private $data = array();
-
- public function __construct()
- {
- $this->data = new KeyValStore;
- }
-
- /**
- * Store a parameter.
- *
- * @param string $name
- * @param string|array $value
- * @return Command
- */
- public function setParam($name, $value)
- {
- $this->data->set($name, $value);
- return $this;
- }
-
- /**
- * Store multiple params.
- *
- * @param array $params
- */
- public function setParams(array $params)
- {
- foreach ($params as $index => $value) {
- $this->setParam($index, $value);
- }
-
- return $this;
- }
-
- /**
- * Retrieve a parameter or an optional default.
- *
- * @param string $name
- * @param mixed $default
- * @return mixed
- */
- public function getParam($name, $default = null)
- {
- return $this->data->get($name, $default);
- }
-
- /**
- * Retrieve all parameters as KeyValStore.
- *
- * @return array
- */
- public function getParams()
- {
- return $this->data;
- }
-
- /**
* Is the Payload Populated?
*/
public function isPopulated()
View
2 lib/Proem/Api/Proem.php
@@ -49,7 +49,7 @@ class Proem
/**
* Store the framework version
*/
- const VERSION = '0.1.5';
+ const VERSION = '0.2.0';
/**
* Store events
View
4 lib/Proem/Api/Routing/Route/Standard.php
@@ -151,9 +151,9 @@ function($matches) use ($custom_filters, $default_tokens, $default_filters)
// parse it into an array and send it to setParams() instead
// of the singular setParam.
if ($key == 'params' && strpos($value, '/') !== false) {
- $this->getPayload()->setParams($this->createAssocArray(explode('/', trim($value, '/'))));
+ $this->getPayload()->set($this->createAssocArray(explode('/', trim($value, '/'))));
} else {
- $this->getPayload()->setParam($key, $value);
+ $this->getPayload()->set($key, $value);
}
}
View
4 lib/Proem/Api/Service/Asset/Generic.php
@@ -164,12 +164,12 @@ public function set($provides, \Closure $closure)
* Retrieve an instantiated Asset.
*
* Here the closure is passed this asset container and optionally the
- * Proem\Api\Asset\Manager.
+ * Proem\Api\Service\Manager.
*
* This provides the closure with the ability to use any required parameters
* and also be able to call upon any other assets stored in the asset manager.
*
- * @param Proem\Api\Asset\Manager $assetManager
+ * @param Proem\Api\Service\Manager $assetManager
*/
public function get(Manager $assetManager = null)
{
View
11 lib/Proem/Api/Service/Manager.php
@@ -64,7 +64,7 @@ class Manager
* Store an Asset container by named index.
*
* @param string $index The index the asset will be referenced by.
- * @param Proem\Api\Asset $asset
+ * @param Proem\Api\Service\Asset\Generic $asset
*/
public function set($index, Asset $asset)
{
@@ -110,7 +110,14 @@ public function has($index)
*/
public function provides($index, $provides = null)
{
- if ($provides === null) {
+ if (is_array($index)) {
+ foreach ($index as $key) {
+ if (!in_array($key, $this->provides)) {
+ return false;
+ }
+ }
+ return true;
+ } elseif ($provides === null) {
return in_array($index, $this->provides);
} else {
if ($this->has($index)) {
View
4 lib/Proem/Api/Signal/Manager.php
@@ -122,14 +122,14 @@ public function trigger(Array $options)
foreach ($this->queues[$ops->name] as $event) {
$eventObj = $ops->event;
if ($eventObj instanceof \Proem\Signal\Event\Generic) {
- if (isset($ops->params)) {
+ if ($ops->has('params')) {
$eventObj->setParams($ops->params);
}
}
$eventObj->setTarget($ops->target);
$eventObj->setMethod($ops->method);
if ($return = $event($eventObj)) {
- if (isset($ops->callback)) {
+ if ($ops->has('callback')) {
(new Callback($ops->callback, $return))->call();
}
}
View
85 lib/Proem/Api/Util/Opt/Option.php
@@ -30,7 +30,9 @@
*/
namespace Proem\Api\Util\Opt;
-use Proem\Util\Process\Callback;
+use Proem\Util\Process\Callback,
+ Proem\Service\Asset\Generic as GenericAsset,
+ Proem\Service\Manager as ServiceManager;
/**
* Proem\Api\Util\Opt\Option
@@ -40,8 +42,10 @@ class Option
private $value;
private $is_required = false;
private $is_type;
+ private $is_asset;
private $is_object;
private $is_classof;
+ private $throws = null;
private $unless = [];
private $type_validators = [];
@@ -112,6 +116,10 @@ public function required() {
return $this;
}
+ public function isRequired() {
+ return $this->is_required;
+ }
+
/**
* Disable this Option from being required if some other argument(s) has been provided
*
@@ -156,6 +164,26 @@ public function object($object)
}
/**
+ * Force this Option's value to be an Asset or an ServiceMananger
+ * providing a specific object.
+ *
+ * @param $provides The Asset this Option provides
+ */
+ public function asset($provides)
+ {
+ $this->is_asset = $provides;
+ return $this;
+ }
+
+ /**
+ * The exception to throw if invalid
+ */
+ public function throws(callable $exception) {
+ $this->throws = $exception;
+ return $this;
+ }
+
+ /**
* Force this Option's value to be a string representation of a
* particular class or subclass
*
@@ -186,34 +214,77 @@ public function validate($options = []) {
if ($this->is_required) {
if ($this->value === __FILE__) {
- throw new \InvalidArgumentException(' is a required option');
+ if ($this->throws === null) {
+ throw new \InvalidArgumentException(' is a required option');
+ } else {
+ throw (new Callback($this->throws))->call();
+ }
}
}
if ($this->is_type && $this->value !== __FILE__) {
if (isset($this->type_validators[$this->is_type])) {
- //$func = $this->type_validators[$this->is_type];
if (!(new Callback($this->type_validators[$this->is_type], [$this->value]))->call()) {
- throw new \InvalidArgumentException(' did not pass the "' . $this->is_type . '" validator');
+ if ($this->throws === null) {
+ throw new \InvalidArgumentException(' did not pass the "' . $this->is_type . '" validator');
+ } else {
+ throw (new Callback($this->throws))->call();
+ }
}
} else {
throw new \RuntimeException('No validator found for type ' . $this->is_type);
}
}
+ if ($this->is_asset && $this->value !== __FILE__) {
+ if ($this->value instanceof GenericAsset) {
+ if ($this->value->provides() !== $this->is_asset) {
+ if ($this->throws === null) {
+ throw new \InvalidArgumentException(' did not pass the "' . $this->is_asset . '" Asset validator');
+ } else {
+ throw (new Callback($this->throws))->call();
+ }
+ }
+ } elseif ($this->value instanceof ServiceManager) {
+ if (!$this->value->provides($this->is_asset)) {
+ if ($this->throws === null) {
+ throw new \InvalidArgumentException(' did not pass the "' . (is_array($this->is_asset) ? '[' . implode(', ', $this->is_asset) . ']' : $this->is_asset) . '" Asset validator');
+ } else {
+ throw (new Callback($this->throws))->call();
+ }
+ }
+ } else {
+ if ($this->throws === null) {
+ throw new \InvalidArgumentException(' is not a valid "Asset" or "Service\Manager"');
+ } else {
+ throw (new Callback($this->throws))->call();
+ }
+ }
+ }
+
if ($this->is_object && $this->value !== __FILE__) {
if (!$this->value instanceof $this->is_object) {
- throw new \InvalidArgumentException(' is required to be an instance of ' . $this->is_object . ', ' . get_class($this->value) . ' provided');
+ if ($this->throws === null) {
+ throw new \InvalidArgumentException(' is required to be an instance of ' . $this->is_object . ', ' . (is_object($this->value) ? get_class($this->value) : $this->value) . ' provided');
+ } else {
+ throw (new Callback($this->throws))->call();
+ }
}
}
if ($this->is_classof && $this->value !== __FILE__) {
if (!$this->value == $this->is_classof && !is_subclass_of($this->is_classof, $this->value)) {
- throw new \InvalidArgumentException(' is required to be a string representation of the class of type ' . $this->is_classof);
+ if ($this->throws === null) {
+ throw new \InvalidArgumentException(' is required to be a string representation of the class of type ' . $this->is_classof);
+ } else {
+ throw (new Callback($this->throws))->call();
+ }
}
}
- if ($this->value == __FILE__) { $this->value = null; }
+ if ($this->value == __FILE__) {
+ return false;
+ }
return true;
}
View
11 lib/Proem/Api/Util/Opt/Options.php
@@ -44,6 +44,8 @@
*/
public function setOptions($defaults, $options)
{
+ $payload = new Payload;
+
foreach ($options as $key => $value) {
if (isset($defaults[$key]) && ($defaults[$key] instanceof Option)) {
$defaults[$key]->setValue($value);
@@ -55,15 +57,18 @@ public function setOptions($defaults, $options)
foreach ($defaults as $key => $value) {
if ($value instanceof Option) {
try {
- $value->validate($options);
- $defaults[$key] = $value->getValue();
+ if ($value->isRequired() || $value->getValue() !== null) {
+ if ($value->validate($options)) {
+ $payload->set($key, $value->getValue());
+ }
+ }
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException($key . $e->getMessage());
} catch (\RuntimeException $e) {
throw new \RuntimeException($e->getMessage());
}
}
}
- return (object) $defaults;
+ return $payload;
}
}
View
41 lib/Proem/Api/Util/Opt/Payload.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * The MIT License
+ *
+ * Copyright (c) 2010 - 2012 Tony R Quilkey <trq@proemframework.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+/**
+ * @namespace Proem\Api\Util\Opt
+ */
+namespace Proem\Api\Util\Opt;
+
+use Proem\Util\Storage\KeyValStore;
+
+/**
+ * Proem\Api\Util\Opt\Payload
+ */
+class Payload extends KeyValStore
+{
+
+}
View
49 lib/Proem/Api/Util/Storage/KeyValStore.php
@@ -35,7 +35,7 @@
*
* A generic key => value storage mechanism.
*/
-class KeyValStore
+class KeyValStore implements \Iterator
{
/**
* Store the data
@@ -88,14 +88,18 @@ public function __get($index)
}
/**
- * Set a value by index
+ * Set multiple values or a single value by index.
*
- * @param string $index
+ * @param string|array $index
* @param mixed $value
*/
- public function set($index, $value)
+ public function set($index, $value = null)
{
- $this->data[$index] = $value;
+ if (is_array($index)) {
+ $this->data = array_merge($index, $this->data);
+ } else {
+ $this->data[$index] = $value;
+ }
return $this;
}
@@ -131,4 +135,39 @@ public function has($index)
{
return array_key_exists($index, $this->data);
}
+
+ /**
+ * Reset internal pointer
+ */
+ public function rewind() {
+ return reset($this->data);
+ }
+
+ /**
+ * Return the current element
+ */
+ public function current() {
+ return current($this->data);
+ }
+
+ /**
+ * Fetch current key
+ */
+ public function key() {
+ return key($this->data);
+ }
+
+ /**
+ * Advance the internal pointer and return its data
+ */
+ public function next() {
+ return next($this->data);
+ }
+
+ /**
+ * Does the current internal pointer position point to an existing element?
+ */
+ public function valid() {
+ return $this->current();
+ }
}
View
10 tests/lib/Proem/Tests/Routing/RouterTest.php
@@ -50,9 +50,9 @@ public function testTargetedMapedRoute()
$this->assertInstanceOf('\Proem\Dispatch\Payload', $payload);
$this->assertTrue($payload->isPopulated());
- $this->assertEquals('auth', $payload->getParam('controller'));
- $this->assertEquals('login', $payload->getParam('action'));
- $this->assertNull($payload->getParam('doesntexist'));
+ $this->assertEquals('auth', $payload->controller);
+ $this->assertEquals('login', $payload->action);
+ $this->assertNull($payload->doesntexist);
}
public function dataProvider()
@@ -93,7 +93,7 @@ public function testSeriesOfMappedRoutes($uri, $controller, $action)
$this->assertInstanceOf('\Proem\Dispatch\Payload', $payload);
$this->assertTrue($payload->isPopulated());
- $this->assertEquals($controller, $payload->getParam('controller'));
- $this->assertEquals($action, $payload->getParam('action', 'index'));
+ $this->assertEquals($controller, $payload->controller);
+ $this->assertEquals($action, $payload->get('action', 'index'));
}
}
View
36 tests/lib/Proem/Tests/Routing/StandardRouteTest.php
@@ -44,9 +44,9 @@ public function testController()
$route->process('/foo/bar/a/b');
$this->assertTrue($route->getPayload()->isPopulated());
- $this->assertEquals('foo', $route->getPayload()->getParam('controller'));
- $this->assertEquals('bar', $route->getPayload()->getParam('action'));
- $this->assertEquals('b', $route->getPayload()->getParam('a'));
+ $this->assertEquals('foo', $route->getPayload()->controller);
+ $this->assertEquals('bar', $route->getPayload()->action);
+ $this->assertEquals('b', $route->getPayload()->a);
}
public function testModule()
@@ -57,10 +57,30 @@ public function testModule()
$route->process('/bob/foo/bar/a/b');
$this->assertTrue($route->getPayload()->isPopulated());
- $this->assertEquals('bob', $route->getPayload()->getParam('module'));
- $this->assertEquals('foo', $route->getPayload()->getParam('controller'));
- $this->assertEquals('bar', $route->getPayload()->getParam('action'));
- $this->assertEquals('b', $route->getPayload()->getParam('a'));
+ $this->assertEquals('bob', $route->getPayload()->module);
+ $this->assertEquals('foo', $route->getPayload()->controller);
+ $this->assertEquals('bar', $route->getPayload()->action);
+ $this->assertEquals('b', $route->getPayload()->a);
+ }
+
+ public function testAnotherRoute()
+ {
+ $route = new Standard([
+ 'rule' => '/foo/bar/:id',
+ 'targets' => [
+ 'module' => 'default',
+ 'controller' => 'foo',
+ 'action' => 'bar'
+ ],
+ 'filters' => ['id' => ':int']
+ ]);
+ $route->process('/foo/bar/12');
+
+ $this->assertTrue($route->getPayload()->isPopulated());
+ $this->assertEquals('default', $route->getPayload()->module);
+ $this->assertEquals('foo', $route->getPayload()->controller);
+ $this->assertEquals('bar', $route->getPayload()->action);
+ $this->assertEquals(12, $route->getPayload()->id);
}
public function testAlphaFilter()
@@ -72,7 +92,7 @@ public function testAlphaFilter()
$route->process('/foo');
$this->assertTrue($route->getPayload()->isPopulated());
- $this->assertEquals('foo', $route->getPayload()->getParam('data'));
+ $this->assertEquals('foo', $route->getPayload()->data);
$route = new Standard([
'rule' => '/:data',
View
18 tests/lib/Proem/Tests/ServiceTest.php
@@ -207,4 +207,22 @@ public function testManagerHas()
$this->assertTrue($am->has('bar'));
}
+
+ public function testManagerHasMultiple()
+ {
+ $bar = new Asset;
+ $bar->set('Proem\Service\Asset\Bar', function() {
+ return new Bar;
+ });
+
+ $foo = new Asset;
+ $foo->set('Proem\Service\Asset\Foo', function() {
+ return new Foo();
+ });
+
+ $am = new Manager;
+ $am->set('Foo', $foo)->set('Bar', $bar);
+
+ $this->assertTrue($am->provides(['Proem\Service\Asset\Foo', 'Proem\Service\Asset\Bar']));
+ }
}
View
75 tests/lib/Proem/Tests/Util/OptTest.php
@@ -28,7 +28,9 @@
use Proem\Tests\Util\Options\Fixtures\OptionsFixture,
Proem\Tests\Util\Options\Fixtures\OptionsFixture2,
- Proem\Proem;
+ Proem\Proem,
+ Proem\Service\Asset\Generic as GenericAsset,
+ Proem\Service\Manager as ServiceManager;
class OptTest extends \PHPUnit_Framework_TestCase
{
@@ -71,6 +73,17 @@ public function testMissingBoo()
}
/**
+ * @expectedException DomainException
+ */
+ public function testCustomExcpetion()
+ {
+ $fixture = new OptionsFixture2([
+ 'foo' => '',
+ 'except' => 'something'
+ ]);
+ }
+
+ /**
* @expectedException InvalidArgumentException
*/
public function testMissingBob()
@@ -103,6 +116,66 @@ public function testInvalidBob()
]);
}
+ public function testValidAsset()
+ {
+ $fixture = new OptionsFixture([
+ 'boo' => [],
+ 'bar' => 'this is bar',
+ 'bob' => new Proem,
+ 'asset' => (new GenericAsset())
+ ->set('StdClass', function() {
+ return new \StdClass;
+ })
+ ]);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidAsset()
+ {
+ $fixture = new OptionsFixture([
+ 'boo' => [],
+ 'asset' => new \StdClass
+ ]);
+ }
+
+ public function testValidServiceManager()
+ {
+ $asset = new GenericAsset;
+ $asset->set('StdClass', function() {
+ return new \StdClass;
+ });
+
+ $proem = new GenericAsset;
+ $proem->set('Proem', function() {
+ return new Proem;
+ });
+
+ $man = new ServiceManager;
+ $man->set('StdClass', $asset)
+ ->set('Proem', $proem);
+
+ $fixture = new OptionsFixture([
+ 'boo' => [],
+ 'bar' => 'this is bar',
+ 'bob' => new Proem,
+ 'asset' => $man,
+ 'am' => $man
+ ]);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidServiceManager()
+ {
+ $fixture = new OptionsFixture([
+ 'boo' => [],
+ 'asset' => new \StdClass
+ ]);
+ }
+
public function testUnless()
{
$fixture = new OptionsFixture2([
View
10 tests/lib/Proem/Tests/Util/Options/Fixtures/OptionsFixture.php
@@ -36,10 +36,12 @@ class OptionsFixture
public function __construct(array $options = [])
{
$this->options = $this->setOptions([
- 'foo' => (new Option('foo')),
- 'bar' => (new Option())->required(),
- 'boo' => (new Option())->required()->type('array'),
- 'bob' => (new Option())->required()->object('Proem\Proem')
+ 'foo' => (new Option('foo')),
+ 'asset' => (new Option())->asset('StdClass'),
+ 'am' => (new Option())->asset(['StdClass', 'Proem']),
+ 'bar' => (new Option())->required(),
+ 'boo' => (new Option())->required()->type('array'),
+ 'bob' => (new Option())->required()->object('Proem\Proem'),
], $options);
}
View
3 tests/lib/Proem/Tests/Util/Options/Fixtures/OptionsFixture2.php
@@ -39,6 +39,9 @@ public function __construct(array $options = [])
'foo' => (new Option())->required()->unless('bar'),
'obj' => (new Option())->classof('Proem\Proem'),
'emptytest' => (new Option())->object('Proem\Proem'),
+ 'except' => (new Option())->object('Proem\Proem')->throws(function() {
+ return new \DomainException('This is a custom exception');
+ }),
'custom-arg' => (new Option())->addTypeValidator('custom', function($value) { return preg_match('/[a-z]/', $value); })->type('custom')
], $options);
}

0 comments on commit f433944

Please sign in to comment.