D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
home
/
everqlsh
/
www
/
wp-admin
/
user
/
577040
/
Filename :
pimple.tar
back
Copy
pimple/src/Pimple/ServiceIterator.php 0000644 00000004266 15162443064 0013707 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple; /** * Lazy service iterator. * * @author Pascal Luna <skalpa@zetareticuli.org> */ final class ServiceIterator implements \Iterator { private $container; private $ids; public function __construct(Container $container, array $ids) { $this->container = $container; $this->ids = $ids; } /** * @return void */ #[\ReturnTypeWillChange] public function rewind() { \reset($this->ids); } /** * @return mixed */ #[\ReturnTypeWillChange] public function current() { return $this->container[\current($this->ids)]; } /** * @return mixed */ #[\ReturnTypeWillChange] public function key() { return \current($this->ids); } /** * @return void */ #[\ReturnTypeWillChange] public function next() { \next($this->ids); } /** * @return bool */ #[\ReturnTypeWillChange] public function valid() { return null !== \key($this->ids); } } pimple/src/Pimple/Container.php 0000644 00000022324 15162443066 0012514 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple; use Pimple\Exception\ExpectedInvokableException; use Pimple\Exception\FrozenServiceException; use Pimple\Exception\InvalidServiceIdentifierException; use Pimple\Exception\UnknownIdentifierException; /** * Container main class. * * @author Fabien Potencier */ class Container implements \ArrayAccess { private $values = []; private $factories; private $protected; private $frozen = []; private $raw = []; private $keys = []; /** * Instantiates the container. * * Objects and parameters can be passed as argument to the constructor. * * @param array $values The parameters or objects */ public function __construct(array $values = []) { $this->factories = new \SplObjectStorage(); $this->protected = new \SplObjectStorage(); foreach ($values as $key => $value) { $this->offsetSet($key, $value); } } /** * Sets a parameter or an object. * * Objects must be defined as Closures. * * Allowing any PHP callable leads to difficult to debug problems * as function names (strings) are callable (creating a function with * the same name as an existing parameter would break your container). * * @param string $id The unique identifier for the parameter or object * @param mixed $value The value of the parameter or a closure to define an object * * @return void * * @throws FrozenServiceException Prevent override of a frozen service */ #[\ReturnTypeWillChange] public function offsetSet($id, $value) { if (isset($this->frozen[$id])) { throw new FrozenServiceException($id); } $this->values[$id] = $value; $this->keys[$id] = true; } /** * Gets a parameter or an object. * * @param string $id The unique identifier for the parameter or object * * @return mixed The value of the parameter or an object * * @throws UnknownIdentifierException If the identifier is not defined */ #[\ReturnTypeWillChange] public function offsetGet($id) { if (!isset($this->keys[$id])) { throw new UnknownIdentifierException($id); } if ( isset($this->raw[$id]) || !\is_object($this->values[$id]) || isset($this->protected[$this->values[$id]]) || !\method_exists($this->values[$id], '__invoke') ) { return $this->values[$id]; } if (isset($this->factories[$this->values[$id]])) { return $this->values[$id]($this); } $raw = $this->values[$id]; $val = $this->values[$id] = $raw($this); $this->raw[$id] = $raw; $this->frozen[$id] = true; return $val; } /** * Checks if a parameter or an object is set. * * @param string $id The unique identifier for the parameter or object * * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($id) { return isset($this->keys[$id]); } /** * Unsets a parameter or an object. * * @param string $id The unique identifier for the parameter or object * * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($id) { if (isset($this->keys[$id])) { if (\is_object($this->values[$id])) { unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]); } unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]); } } /** * Marks a callable as being a factory service. * * @param callable $callable A service definition to be used as a factory * * @return callable The passed callable * * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object */ public function factory($callable) { if (!\is_object($callable) || !\method_exists($callable, '__invoke')) { throw new ExpectedInvokableException('Service definition is not a Closure or invokable object.'); } $this->factories->attach($callable); return $callable; } /** * Protects a callable from being interpreted as a service. * * This is useful when you want to store a callable as a parameter. * * @param callable $callable A callable to protect from being evaluated * * @return callable The passed callable * * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object */ public function protect($callable) { if (!\is_object($callable) || !\method_exists($callable, '__invoke')) { throw new ExpectedInvokableException('Callable is not a Closure or invokable object.'); } $this->protected->attach($callable); return $callable; } /** * Gets a parameter or the closure defining an object. * * @param string $id The unique identifier for the parameter or object * * @return mixed The value of the parameter or the closure defining an object * * @throws UnknownIdentifierException If the identifier is not defined */ public function raw($id) { if (!isset($this->keys[$id])) { throw new UnknownIdentifierException($id); } if (isset($this->raw[$id])) { return $this->raw[$id]; } return $this->values[$id]; } /** * Extends an object definition. * * Useful when you want to extend an existing object definition, * without necessarily loading that object. * * @param string $id The unique identifier for the object * @param callable $callable A service definition to extend the original * * @return callable The wrapped callable * * @throws UnknownIdentifierException If the identifier is not defined * @throws FrozenServiceException If the service is frozen * @throws InvalidServiceIdentifierException If the identifier belongs to a parameter * @throws ExpectedInvokableException If the extension callable is not a closure or an invokable object */ public function extend($id, $callable) { if (!isset($this->keys[$id])) { throw new UnknownIdentifierException($id); } if (isset($this->frozen[$id])) { throw new FrozenServiceException($id); } if (!\is_object($this->values[$id]) || !\method_exists($this->values[$id], '__invoke')) { throw new InvalidServiceIdentifierException($id); } if (isset($this->protected[$this->values[$id]])) { @\trigger_error(\sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), E_USER_DEPRECATED); } if (!\is_object($callable) || !\method_exists($callable, '__invoke')) { throw new ExpectedInvokableException('Extension service definition is not a Closure or invokable object.'); } $factory = $this->values[$id]; $extended = function ($c) use ($callable, $factory) { return $callable($factory($c), $c); }; if (isset($this->factories[$factory])) { $this->factories->detach($factory); $this->factories->attach($extended); } return $this[$id] = $extended; } /** * Returns all defined value names. * * @return array An array of value names */ public function keys() { return \array_keys($this->values); } /** * Registers a service provider. * * @param array $values An array of values that customizes the provider * * @return static */ public function register(ServiceProviderInterface $provider, array $values = []) { $provider->register($this); foreach ($values as $key => $value) { $this[$key] = $value; } return $this; } } pimple/src/Pimple/Tests/ServiceIteratorTest.php 0000644 00000003567 15162443067 0015657 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests; use PHPUnit\Framework\TestCase; use Pimple\Container; use Pimple\ServiceIterator; use Pimple\Tests\Fixtures\Service; class ServiceIteratorTest extends TestCase { public function testIsIterable() { $pimple = new Container(); $pimple['service1'] = function () { return new Service(); }; $pimple['service2'] = function () { return new Service(); }; $pimple['service3'] = function () { return new Service(); }; $iterator = new ServiceIterator($pimple, ['service1', 'service2']); $this->assertSame(['service1' => $pimple['service1'], 'service2' => $pimple['service2']], iterator_to_array($iterator)); } } pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php 0000644 00000005311 15162443071 0020630 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests; use PHPUnit\Framework\TestCase; use Pimple\Container; /** * @author Dominik Zogg <dominik.zogg@gmail.com> */ class PimpleServiceProviderInterfaceTest extends TestCase { public function testProvider() { $pimple = new Container(); $pimpleServiceProvider = new Fixtures\PimpleServiceProvider(); $pimpleServiceProvider->register($pimple); $this->assertEquals('value', $pimple['param']); $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); $serviceOne = $pimple['factory']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); $serviceTwo = $pimple['factory']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); $this->assertNotSame($serviceOne, $serviceTwo); } public function testProviderWithRegisterMethod() { $pimple = new Container(); $pimple->register(new Fixtures\PimpleServiceProvider(), [ 'anotherParameter' => 'anotherValue', ]); $this->assertEquals('value', $pimple['param']); $this->assertEquals('anotherValue', $pimple['anotherParameter']); $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); $serviceOne = $pimple['factory']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); $serviceTwo = $pimple['factory']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); $this->assertNotSame($serviceOne, $serviceTwo); } } pimple/src/Pimple/Tests/PimpleTest.php 0000644 00000043720 15162443072 0013762 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests; use PHPUnit\Framework\TestCase; use Pimple\Container; /** * @author Igor Wiedler <igor@wiedler.ch> */ class PimpleTest extends TestCase { public function testWithString() { $pimple = new Container(); $pimple['param'] = 'value'; $this->assertEquals('value', $pimple['param']); } public function testWithClosure() { $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); } public function testServicesShouldBeDifferent() { $pimple = new Container(); $pimple['service'] = $pimple->factory(function () { return new Fixtures\Service(); }); $serviceOne = $pimple['service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); $serviceTwo = $pimple['service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); $this->assertNotSame($serviceOne, $serviceTwo); } public function testShouldPassContainerAsParameter() { $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $pimple['container'] = function ($container) { return $container; }; $this->assertNotSame($pimple, $pimple['service']); $this->assertSame($pimple, $pimple['container']); } public function testIsset() { $pimple = new Container(); $pimple['param'] = 'value'; $pimple['service'] = function () { return new Fixtures\Service(); }; $pimple['null'] = null; $this->assertTrue(isset($pimple['param'])); $this->assertTrue(isset($pimple['service'])); $this->assertTrue(isset($pimple['null'])); $this->assertFalse(isset($pimple['non_existent'])); } public function testConstructorInjection() { $params = ['param' => 'value']; $pimple = new Container($params); $this->assertSame($params['param'], $pimple['param']); } public function testOffsetGetValidatesKeyIsPresent() { $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); $this->expectExceptionMessage('Identifier "foo" is not defined.'); $pimple = new Container(); echo $pimple['foo']; } /** * @group legacy */ public function testLegacyOffsetGetValidatesKeyIsPresent() { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Identifier "foo" is not defined.'); $pimple = new Container(); echo $pimple['foo']; } public function testOffsetGetHonorsNullValues() { $pimple = new Container(); $pimple['foo'] = null; $this->assertNull($pimple['foo']); } public function testUnset() { $pimple = new Container(); $pimple['param'] = 'value'; $pimple['service'] = function () { return new Fixtures\Service(); }; unset($pimple['param'], $pimple['service']); $this->assertFalse(isset($pimple['param'])); $this->assertFalse(isset($pimple['service'])); } /** * @dataProvider serviceDefinitionProvider */ public function testShare($service) { $pimple = new Container(); $pimple['shared_service'] = $service; $serviceOne = $pimple['shared_service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); $serviceTwo = $pimple['shared_service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); $this->assertSame($serviceOne, $serviceTwo); } /** * @dataProvider serviceDefinitionProvider */ public function testProtect($service) { $pimple = new Container(); $pimple['protected'] = $pimple->protect($service); $this->assertSame($service, $pimple['protected']); } public function testGlobalFunctionNameAsParameterValue() { $pimple = new Container(); $pimple['global_function'] = 'strlen'; $this->assertSame('strlen', $pimple['global_function']); } public function testRaw() { $pimple = new Container(); $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; }); $this->assertSame($definition, $pimple->raw('service')); } public function testRawHonorsNullValues() { $pimple = new Container(); $pimple['foo'] = null; $this->assertNull($pimple->raw('foo')); } public function testFluentRegister() { $pimple = new Container(); $this->assertSame($pimple, $pimple->register($this->getMockBuilder('Pimple\ServiceProviderInterface')->getMock())); } public function testRawValidatesKeyIsPresent() { $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); $this->expectExceptionMessage('Identifier "foo" is not defined.'); $pimple = new Container(); $pimple->raw('foo'); } /** * @group legacy */ public function testLegacyRawValidatesKeyIsPresent() { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Identifier "foo" is not defined.'); $pimple = new Container(); $pimple->raw('foo'); } /** * @dataProvider serviceDefinitionProvider */ public function testExtend($service) { $pimple = new Container(); $pimple['shared_service'] = function () { return new Fixtures\Service(); }; $pimple['factory_service'] = $pimple->factory(function () { return new Fixtures\Service(); }); $pimple->extend('shared_service', $service); $serviceOne = $pimple['shared_service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); $serviceTwo = $pimple['shared_service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); $this->assertSame($serviceOne, $serviceTwo); $this->assertSame($serviceOne->value, $serviceTwo->value); $pimple->extend('factory_service', $service); $serviceOne = $pimple['factory_service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); $serviceTwo = $pimple['factory_service']; $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); $this->assertNotSame($serviceOne, $serviceTwo); $this->assertNotSame($serviceOne->value, $serviceTwo->value); } public function testExtendDoesNotLeakWithFactories() { if (\extension_loaded('pimple')) { $this->markTestSkipped('Pimple extension does not support this test'); } $pimple = new Container(); $pimple['foo'] = $pimple->factory(function () { return; }); $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; }); unset($pimple['foo']); $p = new \ReflectionProperty($pimple, 'values'); $p->setAccessible(true); $this->assertEmpty($p->getValue($pimple)); $p = new \ReflectionProperty($pimple, 'factories'); $p->setAccessible(true); $this->assertCount(0, $p->getValue($pimple)); } public function testExtendValidatesKeyIsPresent() { $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); $this->expectExceptionMessage('Identifier "foo" is not defined.'); $pimple = new Container(); $pimple->extend('foo', function () { }); } /** * @group legacy */ public function testLegacyExtendValidatesKeyIsPresent() { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Identifier "foo" is not defined.'); $pimple = new Container(); $pimple->extend('foo', function () { }); } public function testKeys() { $pimple = new Container(); $pimple['foo'] = 123; $pimple['bar'] = 123; $this->assertEquals(['foo', 'bar'], $pimple->keys()); } /** @test */ public function settingAnInvokableObjectShouldTreatItAsFactory() { $pimple = new Container(); $pimple['invokable'] = new Fixtures\Invokable(); $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']); } /** @test */ public function settingNonInvokableObjectShouldTreatItAsParameter() { $pimple = new Container(); $pimple['non_invokable'] = new Fixtures\NonInvokable(); $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']); } /** * @dataProvider badServiceDefinitionProvider */ public function testFactoryFailsForInvalidServiceDefinitions($service) { $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); $this->expectExceptionMessage('Service definition is not a Closure or invokable object.'); $pimple = new Container(); $pimple->factory($service); } /** * @group legacy * @dataProvider badServiceDefinitionProvider */ public function testLegacyFactoryFailsForInvalidServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Service definition is not a Closure or invokable object.'); $pimple = new Container(); $pimple->factory($service); } /** * @dataProvider badServiceDefinitionProvider */ public function testProtectFailsForInvalidServiceDefinitions($service) { $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); $this->expectExceptionMessage('Callable is not a Closure or invokable object.'); $pimple = new Container(); $pimple->protect($service); } /** * @group legacy * @dataProvider badServiceDefinitionProvider */ public function testLegacyProtectFailsForInvalidServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Callable is not a Closure or invokable object.'); $pimple = new Container(); $pimple->protect($service); } /** * @dataProvider badServiceDefinitionProvider */ public function testExtendFailsForKeysNotContainingServiceDefinitions($service) { $this->expectException(\Pimple\Exception\InvalidServiceIdentifierException::class); $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.'); $pimple = new Container(); $pimple['foo'] = $service; $pimple->extend('foo', function () { }); } /** * @group legacy * @dataProvider badServiceDefinitionProvider */ public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.'); $pimple = new Container(); $pimple['foo'] = $service; $pimple->extend('foo', function () { }); } /** * @group legacy * @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected? */ public function testExtendingProtectedClosureDeprecation() { $pimple = new Container(); $pimple['foo'] = $pimple->protect(function () { return 'bar'; }); $pimple->extend('foo', function ($value) { return $value.'-baz'; }); $this->assertSame('bar-baz', $pimple['foo']); } /** * @dataProvider badServiceDefinitionProvider */ public function testExtendFailsForInvalidServiceDefinitions($service) { $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); $this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.'); $pimple = new Container(); $pimple['foo'] = function () { }; $pimple->extend('foo', $service); } /** * @group legacy * @dataProvider badServiceDefinitionProvider */ public function testLegacyExtendFailsForInvalidServiceDefinitions($service) { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.'); $pimple = new Container(); $pimple['foo'] = function () { }; $pimple->extend('foo', $service); } public function testExtendFailsIfFrozenServiceIsNonInvokable() { $this->expectException(\Pimple\Exception\FrozenServiceException::class); $this->expectExceptionMessage('Cannot override frozen service "foo".'); $pimple = new Container(); $pimple['foo'] = function () { return new Fixtures\NonInvokable(); }; $foo = $pimple['foo']; $pimple->extend('foo', function () { }); } public function testExtendFailsIfFrozenServiceIsInvokable() { $this->expectException(\Pimple\Exception\FrozenServiceException::class); $this->expectExceptionMessage('Cannot override frozen service "foo".'); $pimple = new Container(); $pimple['foo'] = function () { return new Fixtures\Invokable(); }; $foo = $pimple['foo']; $pimple->extend('foo', function () { }); } /** * Provider for invalid service definitions. */ public function badServiceDefinitionProvider() { return [ [123], [new Fixtures\NonInvokable()], ]; } /** * Provider for service definitions. */ public function serviceDefinitionProvider() { return [ [function ($value) { $service = new Fixtures\Service(); $service->value = $value; return $service; }], [new Fixtures\Invokable()], ]; } public function testDefiningNewServiceAfterFreeze() { $pimple = new Container(); $pimple['foo'] = function () { return 'foo'; }; $foo = $pimple['foo']; $pimple['bar'] = function () { return 'bar'; }; $this->assertSame('bar', $pimple['bar']); } public function testOverridingServiceAfterFreeze() { $this->expectException(\Pimple\Exception\FrozenServiceException::class); $this->expectExceptionMessage('Cannot override frozen service "foo".'); $pimple = new Container(); $pimple['foo'] = function () { return 'foo'; }; $foo = $pimple['foo']; $pimple['foo'] = function () { return 'bar'; }; } /** * @group legacy */ public function testLegacyOverridingServiceAfterFreeze() { $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Cannot override frozen service "foo".'); $pimple = new Container(); $pimple['foo'] = function () { return 'foo'; }; $foo = $pimple['foo']; $pimple['foo'] = function () { return 'bar'; }; } public function testRemovingServiceAfterFreeze() { $pimple = new Container(); $pimple['foo'] = function () { return 'foo'; }; $foo = $pimple['foo']; unset($pimple['foo']); $pimple['foo'] = function () { return 'bar'; }; $this->assertSame('bar', $pimple['foo']); } public function testExtendingService() { $pimple = new Container(); $pimple['foo'] = function () { return 'foo'; }; $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { return "$foo.bar"; }); $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { return "$foo.baz"; }); $this->assertSame('foo.bar.baz', $pimple['foo']); } public function testExtendingServiceAfterOtherServiceFreeze() { $pimple = new Container(); $pimple['foo'] = function () { return 'foo'; }; $pimple['bar'] = function () { return 'bar'; }; $foo = $pimple['foo']; $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) { return "$bar.baz"; }); $this->assertSame('bar.baz', $pimple['bar']); } } pimple/src/Pimple/Tests/Fixtures/Service.php 0000644 00000002406 15162443074 0015103 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests\Fixtures; /** * @author Igor Wiedler <igor@wiedler.ch> */ class Service { public $value; } pimple/src/Pimple/Tests/Fixtures/Invokable.php 0000644 00000002530 15162443075 0015414 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests\Fixtures; class Invokable { public function __invoke($value = null) { $service = new Service(); $service->value = $value; return $service; } } pimple/src/Pimple/Tests/Fixtures/NonInvokable.php 0000644 00000002364 15162443076 0016075 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests\Fixtures; class NonInvokable { public function __call($a, $b) { } } pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php 0000644 00000003413 15162443100 0017752 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests\Fixtures; use Pimple\Container; use Pimple\ServiceProviderInterface; class PimpleServiceProvider implements ServiceProviderInterface { /** * Registers services on the given container. * * This method should only be used to configure services and parameters. * It should not get services. */ public function register(Container $pimple) { $pimple['param'] = 'value'; $pimple['service'] = function () { return new Service(); }; $pimple['factory'] = $pimple->factory(function () { return new Service(); }); } } pimple/src/Pimple/Tests/Psr11/ContainerTest.php 0000644 00000004715 15162443101 0015356 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009-2017 Fabien Potencier * * 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 Pimple\Tests\Psr11; use PHPUnit\Framework\TestCase; use Pimple\Container; use Pimple\Psr11\Container as PsrContainer; use Pimple\Tests\Fixtures\Service; class ContainerTest extends TestCase { public function testGetReturnsExistingService() { $pimple = new Container(); $pimple['service'] = function () { return new Service(); }; $psr = new PsrContainer($pimple); $this->assertSame($pimple['service'], $psr->get('service')); } public function testGetThrowsExceptionIfServiceIsNotFound() { $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); $this->expectExceptionMessage('Identifier "service" is not defined.'); $pimple = new Container(); $psr = new PsrContainer($pimple); $psr->get('service'); } public function testHasReturnsTrueIfServiceExists() { $pimple = new Container(); $pimple['service'] = function () { return new Service(); }; $psr = new PsrContainer($pimple); $this->assertTrue($psr->has('service')); } public function testHasReturnsFalseIfServiceDoesNotExist() { $pimple = new Container(); $psr = new PsrContainer($pimple); $this->assertFalse($psr->has('service')); } } pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php 0000644 00000010524 15162443102 0016354 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Tests\Psr11; use PHPUnit\Framework\TestCase; use Pimple\Container; use Pimple\Psr11\ServiceLocator; use Pimple\Tests\Fixtures; /** * ServiceLocator test case. * * @author Pascal Luna <skalpa@zetareticuli.org> */ class ServiceLocatorTest extends TestCase { public function testCanAccessServices() { $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $locator = new ServiceLocator($pimple, ['service']); $this->assertSame($pimple['service'], $locator->get('service')); } public function testCanAccessAliasedServices() { $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $locator = new ServiceLocator($pimple, ['alias' => 'service']); $this->assertSame($pimple['service'], $locator->get('alias')); } public function testCannotAccessAliasedServiceUsingRealIdentifier() { $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); $this->expectExceptionMessage('Identifier "service" is not defined.'); $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $locator = new ServiceLocator($pimple, ['alias' => 'service']); $service = $locator->get('service'); } public function testGetValidatesServiceCanBeLocated() { $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); $this->expectExceptionMessage('Identifier "foo" is not defined.'); $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $locator = new ServiceLocator($pimple, ['alias' => 'service']); $service = $locator->get('foo'); } public function testGetValidatesTargetServiceExists() { $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); $this->expectExceptionMessage('Identifier "invalid" is not defined.'); $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $locator = new ServiceLocator($pimple, ['alias' => 'invalid']); $service = $locator->get('alias'); } public function testHasValidatesServiceCanBeLocated() { $pimple = new Container(); $pimple['service1'] = function () { return new Fixtures\Service(); }; $pimple['service2'] = function () { return new Fixtures\Service(); }; $locator = new ServiceLocator($pimple, ['service1']); $this->assertTrue($locator->has('service1')); $this->assertFalse($locator->has('service2')); } public function testHasChecksIfTargetServiceExists() { $pimple = new Container(); $pimple['service'] = function () { return new Fixtures\Service(); }; $locator = new ServiceLocator($pimple, ['foo' => 'service', 'bar' => 'invalid']); $this->assertTrue($locator->has('foo')); $this->assertFalse($locator->has('bar')); } } pimple/src/Pimple/ServiceProviderInterface.php 0000644 00000003027 15162443103 0015515 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple; /** * Pimple service provider interface. * * @author Fabien Potencier * @author Dominik Zogg */ interface ServiceProviderInterface { /** * Registers services on the given container. * * This method should only be used to configure services and parameters. * It should not get services. */ public function register(Container $pimple); } pimple/src/Pimple/Exception/FrozenServiceException.php 0000644 00000003171 15162443103 0017162 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Exception; use Psr\Container\ContainerExceptionInterface; /** * An attempt to modify a frozen service was made. * * @author Pascal Luna <skalpa@zetareticuli.org> */ class FrozenServiceException extends \RuntimeException implements ContainerExceptionInterface { /** * @param string $id Identifier of the frozen service */ public function __construct($id) { parent::__construct(\sprintf('Cannot override frozen service "%s".', $id)); } } pimple/src/Pimple/Exception/UnknownIdentifierException.php 0000644 00000003201 15162443104 0020033 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Exception; use Psr\Container\NotFoundExceptionInterface; /** * The identifier of a valid service or parameter was expected. * * @author Pascal Luna <skalpa@zetareticuli.org> */ class UnknownIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface { /** * @param string $id The unknown identifier */ public function __construct($id) { parent::__construct(\sprintf('Identifier "%s" is not defined.', $id)); } } pimple/src/Pimple/Exception/ExpectedInvokableException.php 0000644 00000002662 15162443104 0017777 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Exception; use Psr\Container\ContainerExceptionInterface; /** * A closure or invokable object was expected. * * @author Pascal Luna <skalpa@zetareticuli.org> */ class ExpectedInvokableException extends \InvalidArgumentException implements ContainerExceptionInterface { } pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php 0000644 00000003262 15162443105 0021313 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Exception; use Psr\Container\NotFoundExceptionInterface; /** * An attempt to perform an operation that requires a service identifier was made. * * @author Pascal Luna <skalpa@zetareticuli.org> */ class InvalidServiceIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface { /** * @param string $id The invalid identifier */ public function __construct($id) { parent::__construct(\sprintf('Identifier "%s" does not contain an object definition.', $id)); } } pimple/src/Pimple/Psr11/Container.php 0000644 00000003274 15162443106 0013420 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009-2017 Fabien Potencier * * 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 Pimple\Psr11; use Pimple\Container as PimpleContainer; use Psr\Container\ContainerInterface; /** * PSR-11 compliant wrapper. * * @author Pascal Luna <skalpa@zetareticuli.org> */ final class Container implements ContainerInterface { private $pimple; public function __construct(PimpleContainer $pimple) { $this->pimple = $pimple; } public function get(string $id) { return $this->pimple[$id]; } public function has(string $id): bool { return isset($this->pimple[$id]); } } pimple/src/Pimple/Psr11/ServiceLocator.php 0000644 00000004560 15162443106 0014421 0 ustar 00 <?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * 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 Pimple\Psr11; use Pimple\Container as PimpleContainer; use Pimple\Exception\UnknownIdentifierException; use Psr\Container\ContainerInterface; /** * Pimple PSR-11 service locator. * * @author Pascal Luna <skalpa@zetareticuli.org> */ class ServiceLocator implements ContainerInterface { private $container; private $aliases = []; /** * @param PimpleContainer $container The Container instance used to locate services * @param array $ids Array of service ids that can be located. String keys can be used to define aliases */ public function __construct(PimpleContainer $container, array $ids) { $this->container = $container; foreach ($ids as $key => $id) { $this->aliases[\is_int($key) ? $id : $key] = $id; } } /** * {@inheritdoc} */ public function get(string $id) { if (!isset($this->aliases[$id])) { throw new UnknownIdentifierException($id); } return $this->container[$this->aliases[$id]]; } /** * {@inheritdoc} */ public function has(string $id): bool { return isset($this->aliases[$id]) && isset($this->container[$this->aliases[$id]]); } } pimple/README.rst 0000644 00000023213 15162443107 0007525 0 ustar 00 Pimple ====== .. caution:: Pimple is now closed for changes. No new features will be added and no cosmetic changes will be accepted either. The only accepted changes are compatibility with newer PHP versions and security issue fixes. .. caution:: This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good way to learn more about how to create a simple Dependency Injection Container (recent versions of Pimple are more focused on performance). Pimple is a small Dependency Injection Container for PHP. Installation ------------ Before using Pimple in your project, add it to your ``composer.json`` file: .. code-block:: bash $ ./composer.phar require pimple/pimple "^3.0" Usage ----- Creating a container is a matter of creating a ``Container`` instance: .. code-block:: php use Pimple\Container; $container = new Container(); As many other dependency injection containers, Pimple manages two different kind of data: **services** and **parameters**. Defining Services ~~~~~~~~~~~~~~~~~ A service is an object that does something as part of a larger system. Examples of services: a database connection, a templating engine, or a mailer. Almost any **global** object can be a service. Services are defined by **anonymous functions** that return an instance of an object: .. code-block:: php // define some services $container['session_storage'] = function ($c) { return new SessionStorage('SESSION_ID'); }; $container['session'] = function ($c) { return new Session($c['session_storage']); }; Notice that the anonymous function has access to the current container instance, allowing references to other services or parameters. As objects are only created when you get them, the order of the definitions does not matter. Using the defined services is also very easy: .. code-block:: php // get the session object $session = $container['session']; // the above call is roughly equivalent to the following code: // $storage = new SessionStorage('SESSION_ID'); // $session = new Session($storage); Defining Factory Services ~~~~~~~~~~~~~~~~~~~~~~~~~ By default, each time you get a service, Pimple returns the **same instance** of it. If you want a different instance to be returned for all calls, wrap your anonymous function with the ``factory()`` method .. code-block:: php $container['session'] = $container->factory(function ($c) { return new Session($c['session_storage']); }); Now, each call to ``$container['session']`` returns a new instance of the session. Defining Parameters ~~~~~~~~~~~~~~~~~~~ Defining a parameter allows to ease the configuration of your container from the outside and to store global values: .. code-block:: php // define some parameters $container['cookie_name'] = 'SESSION_ID'; $container['session_storage_class'] = 'SessionStorage'; If you change the ``session_storage`` service definition like below: .. code-block:: php $container['session_storage'] = function ($c) { return new $c['session_storage_class']($c['cookie_name']); }; You can now easily change the cookie name by overriding the ``cookie_name`` parameter instead of redefining the service definition. Protecting Parameters ~~~~~~~~~~~~~~~~~~~~~ Because Pimple sees anonymous functions as service definitions, you need to wrap anonymous functions with the ``protect()`` method to store them as parameters: .. code-block:: php $container['random_func'] = $container->protect(function () { return rand(); }); Modifying Services after Definition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In some cases you may want to modify a service definition after it has been defined. You can use the ``extend()`` method to define additional code to be run on your service just after it is created: .. code-block:: php $container['session_storage'] = function ($c) { return new $c['session_storage_class']($c['cookie_name']); }; $container->extend('session_storage', function ($storage, $c) { $storage->...(); return $storage; }); The first argument is the name of the service to extend, the second a function that gets access to the object instance and the container. Extending a Container ~~~~~~~~~~~~~~~~~~~~~ If you use the same libraries over and over, you might want to reuse some services from one project to the next one; package your services into a **provider** by implementing ``Pimple\ServiceProviderInterface``: .. code-block:: php use Pimple\Container; class FooProvider implements Pimple\ServiceProviderInterface { public function register(Container $pimple) { // register some services and parameters // on $pimple } } Then, register the provider on a Container: .. code-block:: php $pimple->register(new FooProvider()); Fetching the Service Creation Function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When you access an object, Pimple automatically calls the anonymous function that you defined, which creates the service object for you. If you want to get raw access to this function, you can use the ``raw()`` method: .. code-block:: php $container['session'] = function ($c) { return new Session($c['session_storage']); }; $sessionFunction = $container->raw('session'); PSR-11 compatibility -------------------- For historical reasons, the ``Container`` class does not implement the PSR-11 ``ContainerInterface``. However, Pimple provides a helper class that will let you decouple your code from the Pimple container class. The PSR-11 container class ~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``Pimple\Psr11\Container`` class lets you access the content of an underlying Pimple container using ``Psr\Container\ContainerInterface`` methods: .. code-block:: php use Pimple\Container; use Pimple\Psr11\Container as PsrContainer; $container = new Container(); $container['service'] = function ($c) { return new Service(); }; $psr11 = new PsrContainer($container); $controller = function (PsrContainer $container) { $service = $container->get('service'); }; $controller($psr11); Using the PSR-11 ServiceLocator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sometimes, a service needs access to several other services without being sure that all of them will actually be used. In those cases, you may want the instantiation of the services to be lazy. The traditional solution is to inject the entire service container to get only the services really needed. However, this is not recommended because it gives services a too broad access to the rest of the application and it hides their actual dependencies. The ``ServiceLocator`` is intended to solve this problem by giving access to a set of predefined services while instantiating them only when actually needed. It also allows you to make your services available under a different name than the one used to register them. For instance, you may want to use an object that expects an instance of ``EventDispatcherInterface`` to be available under the name ``event_dispatcher`` while your event dispatcher has been registered under the name ``dispatcher``: .. code-block:: php use Monolog\Logger; use Pimple\Psr11\ServiceLocator; use Psr\Container\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcher; class MyService { /** * "logger" must be an instance of Psr\Log\LoggerInterface * "event_dispatcher" must be an instance of Symfony\Component\EventDispatcher\EventDispatcherInterface */ private $services; public function __construct(ContainerInterface $services) { $this->services = $services; } } $container['logger'] = function ($c) { return new Monolog\Logger(); }; $container['dispatcher'] = function () { return new EventDispatcher(); }; $container['service'] = function ($c) { $locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher')); return new MyService($locator); }; Referencing a Collection of Services Lazily ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Passing a collection of services instances in an array may prove inefficient if the class that consumes the collection only needs to iterate over it at a later stage, when one of its method is called. It can also lead to problems if there is a circular dependency between one of the services stored in the collection and the class that consumes it. The ``ServiceIterator`` class helps you solve these issues. It receives a list of service names during instantiation and will retrieve the services when iterated over: .. code-block:: php use Pimple\Container; use Pimple\ServiceIterator; class AuthorizationService { private $voters; public function __construct($voters) { $this->voters = $voters; } public function canAccess($resource) { foreach ($this->voters as $voter) { if (true === $voter->canAccess($resource)) { return true; } } return false; } } $container = new Container(); $container['voter1'] = function ($c) { return new SomeVoter(); } $container['voter2'] = function ($c) { return new SomeOtherVoter($c['auth']); } $container['auth'] = function ($c) { return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2')); } .. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1 pimple/LICENSE 0000644 00000002051 15162443107 0007040 0 ustar 00 Copyright (c) 2009-2020 Fabien Potencier 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.