Skip to content

Commit

Permalink
Redesigned Setup overwrite strategies
Browse files Browse the repository at this point in the history
- Added Build class to collect setup entries and create container
- Removed bulk add methods from Setup (possible with constructor)
- Moved overwrite checks to Setup using Build::has() method
- Added Setup::fallback() strategy (add when missing or ignore)
- Renamed Setup::add() method to Setup::set()
- Separated overwrite violation exception from integrity exception
- Renamed static constructors to Setup::development() and Setup::production()
  • Loading branch information
shudd3r committed Dec 13, 2019
2 parents 520f9f1 + a368abb commit 053c54a
Show file tree
Hide file tree
Showing 23 changed files with 585 additions and 704 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ probably using container too extensively (see [recommended use](#recommended-use
#### Composed entries
##### Record composition using Wrapper
Entry may be built with multiple instance descriptors (same parameters as `InstanceRecord` uses)
given in chained [`Wrapper`](src/Setup/Entry/Wrapper.php) calls:
given in chained [`Wrapper`](src/Setup/Wrapper.php) calls:
```php
$setup->add('A')
->wrappedInstance(SomeClass::class, 'B', 'C')
Expand Down
133 changes: 53 additions & 80 deletions src/Setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,19 @@

namespace Polymorphine\Container;

use Polymorphine\Container\Setup\Build;
use Polymorphine\Container\Setup\Entry;
use Polymorphine\Container\Setup\Exception;
use Psr\Container\ContainerInterface;


abstract class Setup
class Setup
{
protected $records;
protected $containers;
private $build;

/**
* @param Records\Record[] $records
* @param ContainerInterface[] $containers
*/
public function __construct(array $records = [], array $containers = [])
public function __construct(Build $build = null)
{
$this->records = $records;
$this->containers = $containers;
$this->build = $build ?: new Setup\Build();
}

/**
Expand All @@ -36,20 +32,24 @@ public function __construct(array $records = [], array $containers = [])
*
* @return static
*/
public static function basic(array $records = [], array $containers = []): self
public static function production(array $records = [], array $containers = []): self
{
return new Setup\BasicSetup($records, $containers);
return new self(new Setup\Build($records, $containers));
}

/**
* Creates Setup with additional identifier collision checks, and
* Container created with such Setup will also detect circular
* references and add call stack paths to thrown exceptions.
*
* @param Records\Record[] $records
* @param ContainerInterface[] $containers
*
* @return static
*/
public static function validated(array $records = [], array $containers = []): self
public static function development(array $records = [], array $containers = []): self
{
return new Setup\ValidatedSetup($records, $containers);
return new self(new Setup\Build\ValidatedBuild($records, $containers));
}

/**
Expand All @@ -63,35 +63,60 @@ public static function validated(array $records = [], array $containers = []): s
*/
public function container(): ContainerInterface
{
return $this->containers
? new CompositeContainer($this->records(), $this->containers)
: new RecordContainer($this->records());
return $this->build->container();
}

/**
* Returns Entry object able to add new data to container configuration
* for given identifier.
* Returns Entry object adding new container configuration data
* for given identifier. For already defined identifiers Exception
* will be thrown.
*
* @param string $id
*
* @throws Exception\OverwriteRuleException
*
* @return Setup\Entry
*/
public function add(string $id): Entry
public function set(string $id): Entry
{
return new Entry\AddEntry($id, $this);
if ($this->build->has($id)) {
throw Exception\OverwriteRuleException::alreadyDefined($id);
}
return new Entry($id, $this->build);
}

/**
* Returns Entry object able to replace data in container configuration
* for given identifier.
* Returns Entry object replacing container configuration data
* for given identifier. For undefined identifiers Exception will
* be thrown.
*
* @param string $id
*
* @throws Exception\OverwriteRuleException
*
* @return Setup\Entry
*/
public function replace(string $id): Entry
{
return new Entry\ReplaceEntry($id, $this);
if (!$this->build->has($id)) {
throw Exception\OverwriteRuleException::undefined($id);
}
return new Entry($id, $this->build);
}

/**
* Returns Entry object adding new container configuration data
* for given identifier. For already defined identifiers returned
* entry will not change configuration.
*
* @param string $id
*
* @return Setup\Entry
*/
public function fallback(string $id): Entry
{
$build = $this->build->has($id) ? new Build() : $this->build;
return new Entry($id, $build);
}

/**
Expand All @@ -109,64 +134,12 @@ public function replace(string $id): Entry
*
* @param string $id
*
* @throws Setup\Exception\IntegrityConstraintException
* @throws Exception\OverwriteRuleException
*
* @return Setup\Entry\Wrapper
* @return Setup\Wrapper
*/
public function decorate(string $id): Entry\Wrapper
public function decorate(string $id): Setup\Wrapper
{
if (!isset($this->records[$id])) {
throw Setup\Exception\IntegrityConstraintException::undefined($id);
}

return new Entry\Wrapper($id, $this->records[$id], new Entry\ReplaceEntry($id, $this));
return $this->build->decorator($id);
}

/**
* Adds Record instances directly to container configuration.
*
* @param Records\Record[] $records Flat associative array of Record instances
*
* @throws Setup\Exception\IntegrityConstraintException
*/
public function addRecords(array $records): void
{
foreach ($records as $id => $record) {
$this->addRecord($id, $record);
}
}

/**
* @param string $id
* @param Records\Record $record
*
* @throws Setup\Exception\IntegrityConstraintException
*/
abstract public function addRecord(string $id, Records\Record $record): void;

/**
* @param string $id
* @param ContainerInterface $container
*
* @throws Setup\Exception\IntegrityConstraintException
*/
abstract public function addContainer(string $id, ContainerInterface $container): void;

/**
* @param string $id
* @param Records\Record $record
*
* @throws Setup\Exception\IntegrityConstraintException
*/
abstract public function replaceRecord(string $id, Records\Record $record): void;

/**
* @param string $id
* @param ContainerInterface $container
*
* @throws Setup\Exception\IntegrityConstraintException
*/
abstract public function replaceContainer(string $id, ContainerInterface $container): void;

abstract protected function records(): Records;
}
45 changes: 0 additions & 45 deletions src/Setup/BasicSetup.php

This file was deleted.

66 changes: 66 additions & 0 deletions src/Setup/Build.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/*
* This file is part of Polymorphine/Container package.
*
* (c) Shudd3r <q3.shudder@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Polymorphine\Container\Setup;

use Polymorphine\Container\RecordContainer;
use Polymorphine\Container\CompositeContainer;
use Polymorphine\Container\Records;
use Psr\Container\ContainerInterface;


class Build implements Collection
{
protected $records;
protected $containers;

public function __construct(array $records = [], array $containers = [])
{
$this->records = $records;
$this->containers = $containers;
}

public function container(): ContainerInterface
{
return $this->containers
? new CompositeContainer($this->records(), $this->containers)
: new RecordContainer($this->records());
}

public function has(string $id): bool
{
return isset($this->records[$id]) || isset($this->containers[$id]);
}

public function setRecord(string $id, Records\Record $record): void
{
$this->records[$id] = $record;
}

public function setContainer(string $id, ContainerInterface $container): void
{
$this->containers[$id] = $container;
}

public function decorator(string $id): Wrapper
{
if (!isset($this->records[$id])) {
throw Exception\OverwriteRuleException::undefined($id);
}

return new Wrapper($id, $this->records[$id], new Entry($id, $this));
}

protected function records(): Records
{
return new Records($this->records);
}
}

0 comments on commit 053c54a

Please sign in to comment.