Skip to content

Commit

Permalink
Merge pull request #57 from lucatume/container-clone
Browse files Browse the repository at this point in the history
Handle clone
  • Loading branch information
lucatume authored Jun 20, 2023
2 parents 4185e21 + 74bb613 commit ba5c3cc
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 4 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ to [Semantic Versioning](http://semver.org/).

## [unreleased] Unreleased

### Added

- Implement the `Container::__clone` method to clone the container accessory classes correctly upon cloning.

### Changed

- The `Container::__construct` method will bind itself to the `Psr\Container\ContainerInterface` interface as a singleton.
- If the `Container` class is extended, it will bind itself to the extended class in the `__construct` and `__clone` methods.

## [3.3.3] 2023-04-28;

### Fixed
Expand Down
1 change: 1 addition & 0 deletions config/containers/php/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ FROM php:${PHP_VERSION}-cli-alpine

COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
RUN install-php-extensions xdebug && apk add gettext && rm -rf /var/cache/apk/*
RUN rm /usr/bin/install-php-extensions

ARG XDEBUG_REMOTE_HOST='host.docker.internal'
ARG XDEBUG_REMOTE_PORT='9009'
Expand Down
28 changes: 27 additions & 1 deletion src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public function __construct($resolveUnboundAsSingletons = false)
{
$this->resolver = new Builders\Resolver($resolveUnboundAsSingletons);
$this->builders = new Builders\Factory($this, $this->resolver);
$this->singleton(Container::class, $this);
$this->bindThis();
}

/**
Expand Down Expand Up @@ -869,4 +869,30 @@ public function setExceptionMask($maskThrowables)
{
$this->maskThrowables = (int)$maskThrowables;
}

/**
* Binds the container to the base class name, the current class name and the container interface.
*
* @return void
*/
private function bindThis()
{
$this->singleton(ContainerInterface::class, $this);
$this->singleton(Container::class, $this);
if (get_class($this) !== Container::class) {
$this->singleton(get_class($this), $this);
}
}

/**
* Upon cloning, clones the resolver and builders instances.
*
* @return void
*/
public function __clone()
{
$this->resolver = clone $this->resolver;
$this->builders = clone $this->builders;
$this->bindThis();
}
}
101 changes: 101 additions & 0 deletions tests/unit/CloneTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace unit;

use lucatume\DI52\Container;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;

class ContainerExtension extends Container
{
}

class CloneTest extends TestCase
{
/**
* It should support cloning the container
*
* @test
*/
public function should_support_cloning_the_container()
{
$container = new Container();
$object1 = new \stdClass();
$object2 = new \stdClass();
$container->bind('bound', $object1);
$container->singleton('singleton', $object2);

$clone = clone $container;

$this->assertNotSame($clone, $container);
$this->assertTrue($clone->has('bound'));
$this->assertSame($clone->get('bound'), $container->get('bound'));
$this->assertTrue($clone->has('singleton'));
$this->assertSame($clone->get('singleton'), $container->get('singleton'));
$this->assertFalse($clone->has('not-bound'));
}

/**
* It should clone the container resolver
*
* @test
*/
public function should_clone_the_container_resolver()
{
$container = new Container();
$container->singleton('object', function () {
return new \stdClass();
});

$clone = clone $container;

$container->setVar('test', 23);
$clone->setVar('test', 89);

$this->assertEquals(23, $container->getVar('test'));
$this->assertEquals(89, $clone->getVar('test'));

$containerObject = $container->get('object');
$cloneObject = $clone->get('object');

$this->assertSame($container->get('object'), $container->get('object'));
$this->assertSame($clone->get('object'), $clone->get('object'));
$this->assertNotSame($containerObject, $cloneObject);
}

/**
* It should bind clone as singleton container on clone
*
* @test
*/
public function should_bind_clone_as_singleton_container_on_clone()
{
$container = new Container();
$clone = clone $container;

$this->assertNotSame($container, $clone);
$this->assertSame($container, $container->get(Container::class));
$this->assertSame($container, $container->get(ContainerInterface::class));
$this->assertSame($clone, $clone->get(Container::class));
$this->assertSame($clone, $clone->get(ContainerInterface::class));
}

/**
* It should bind the clone as singleton when Container class extended
*
* @test
*/
public function should_bind_the_clone_as_singleton_when_container_class_extended()
{
$container = new ContainerExtension();
$clone = clone $container;

$this->assertNotSame($container, $clone);
$this->assertSame($container, $container->get(Container::class));
$this->assertSame($container, $container->get(ContainerExtension::class));
$this->assertSame($container, $container->get(ContainerInterface::class));
$this->assertSame($clone, $clone->get(Container::class));
$this->assertSame($clone, $clone->get(ContainerExtension::class));
$this->assertSame($clone, $clone->get(ContainerInterface::class));
}
}
3 changes: 1 addition & 2 deletions tests/unit/ContextualBindingContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ public function it_should_resolve_primitive_contextual_bindings_in_a_PHP53_class
/**
* @test
*/
public function it_should_resolve_primitive_contextual_bindings_in_a_php7_class_when_its_bound_interface_is_resolved(
)
public function it_should_resolve_primitive_contextual_bindings_in_a_php7_class_when_its_bound_interface_is_resolved()
{
$container = new Container();

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/PHP7ContextualBindingContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function it_should_resolve_primitive_contextual_bindings_in_a_php7_class_
{
$container = new Container();

$container->bind( Test7Interface::class, Primitive7ConstructorClass::class );
$container->bind(Test7Interface::class, Primitive7ConstructorClass::class);

$container->when(Primitive7ConstructorClass::class)
->needs('$num')
Expand Down

0 comments on commit ba5c3cc

Please sign in to comment.