Skip to content

Commit

Permalink
split ObjectSet into multiple classes depending on use
Browse files Browse the repository at this point in the history
  • Loading branch information
peldax committed Nov 7, 2020
1 parent 0f37f2a commit af11415
Show file tree
Hide file tree
Showing 11 changed files with 395 additions and 269 deletions.
40 changes: 21 additions & 19 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpunit colors="true">
<testsuites>
<testsuite name="unit">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="build/html" lowUpperBound="50" highLowerBound="90"/>
<log type="coverage-text" target="php://stdout" showOnlySummary="true"/>
<log type="coverage-clover" target="build/coverage.xml"/>
<log type="coverage-php" target="build/coverage.serialized"/>
<log type="junit" target="build/logfile.xml"/>
</logging>
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
<report>
<clover outputFile="build/coverage.xml"/>
<html outputDirectory="build/html" lowUpperBound="50" highLowerBound="90"/>
<php outputFile="build/coverage.serialized"/>
<text outputFile="php://stdout" showOnlySummary="true"/>
</report>
</coverage>
<testsuites>
<testsuite name="unit">
<directory>tests</directory>
</testsuite>
</testsuites>
<logging>
<junit outputFile="build/logfile.xml"/>
</logging>
</phpunit>
89 changes: 89 additions & 0 deletions src/Utils/BaseSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types = 1);

namespace Infinityloop\Utils;

abstract class BaseSet implements \Iterator, \ArrayAccess, \Countable
{
use \Nette\SmartObject;

protected const INNER_CLASS = self::class;

protected array $array = [];

public function merge(self $objectSet, bool $allowReplace = false) : self
{
if (!$objectSet instanceof static) {
throw new \Exception('I can only merge Sets of same type');
}

return $this->mergeImpl($objectSet, $allowReplace);
}

public function toArray() : array
{
return $this->array;
}

public function current() : object
{
return \current($this->array);
}

public function next() : void
{
\next($this->array);
}

public function valid() : bool
{
return \key($this->array) !== null;
}

public function rewind() : void
{
\reset($this->array);
}

public function count() : int
{
return \count($this->array);
}

public function offsetExists($offset) : bool
{
return \array_key_exists($offset, $this->array);
}

public function offsetGet($offset) : object
{
if (!$this->offsetExists($offset)) {
throw new \Exception('Item doesnt exist.');
}

return $this->array[$offset];
}

public function offsetSet($offset, $object) : void
{
if (!\is_a($object, static::INNER_CLASS)) {
throw new \Exception('Invalid input.');
}

$this->offsetSetImpl($offset, $object);
}

public function offsetUnset($offset) : void
{
if (!$this->offsetExists($offset)) {
throw new \Exception('Item already doesnt exist.');
}

unset($this->array[$offset]);
}

abstract protected function mergeImpl(self $objectSet, bool $allowReplace) : self;

abstract protected function offsetSetImpl($offset, object $object) : void;
}
44 changes: 44 additions & 0 deletions src/Utils/ImplicitObjectMap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types = 1);

namespace Infinityloop\Utils;

abstract class ImplicitObjectMap extends ObjectMap
{
public function __construct(array $data = [])
{
parent::__construct();

foreach ($data as $key => $object) {
$this->offsetSet(\is_string($key)
? $key
: null , $object);
}
}

abstract protected function getKey(object $object) : string;

protected function offsetSetImpl($offset, object $object) : void
{
$key = $this->getKey($object);

if ($offset === $key) {
parent::offsetSetImpl($key, $object);

return;
}

if ($offset === null) {
if ($this->offsetExists($key)) {
throw new \Exception('Duplicated item');
}

parent::offsetSetImpl($key, $object);

return;
}

throw new \Exception('Offset does not match implicit offset');
}
}
44 changes: 44 additions & 0 deletions src/Utils/ObjectMap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types = 1);

namespace Infinityloop\Utils;

abstract class ObjectMap extends \Infinityloop\Utils\BaseSet
{
public function __construct(array $data = [])
{
foreach ($data as $key => $object) {
$this->offsetSet($key, $object);
}
}

public function key() : string
{
return \key($this->array);
}

protected function mergeImpl(BaseSet $objectSet, bool $allowReplace = false) : self
{
foreach ($objectSet as $offset => $object) {
if (!$allowReplace && $this->offsetExists($offset)) {
throw new \Exception('Item already exists, use $allowReplace if you wish to replace');
}

$this->offsetSet($offset, $object);
}

return $this;
}

protected function offsetSetImpl($offset, object $object) : void
{
if (\is_string($offset)) {
$this->array[$offset] = $object;

return;
}

throw new \Exception('Invalid offset for given object.');
}
}
101 changes: 8 additions & 93 deletions src/Utils/ObjectSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,22 @@

namespace Infinityloop\Utils;

abstract class ObjectSet implements \Iterator, \ArrayAccess, \Countable
abstract class ObjectSet extends \Infinityloop\Utils\BaseSet
{
use \Nette\SmartObject;

protected const INNER_CLASS = self::class;

protected array $array = [];

public function __construct(array $data)
public function __construct(array $data = [])
{
foreach ($data as $object) {
$this->offsetSet(null, $object);
}
}

public function toArray() : array
public function key() : int
{
return $this->array;
return \key($this->array);
}

public function merge(self $objectSet, bool $allowReplace = false) : self
protected function mergeImpl(BaseSet $objectSet, bool $allowReplace = false) : self
{
if (!$objectSet instanceof static) {
throw new \Exception('I can only merge ObjectSets of same type');
}

foreach ($objectSet as $offset => $object) {
$this->offsetSet($allowReplace
? $offset
Expand All @@ -39,95 +29,20 @@ public function merge(self $objectSet, bool $allowReplace = false) : self
return $this;
}

public function current() : object
{
return \current($this->array);
}

public function next() : void
{
\next($this->array);
}

/** @return int|string */
public function key()
protected function offsetSetImpl($offset, object $object) : void
{
return \key($this->array);
}

public function valid() : bool
{
return \key($this->array) !== null;
}

public function rewind() : void
{
\reset($this->array);
}

public function count() : int
{
return \count($this->array);
}

public function offsetExists($offset) : bool
{
return \array_key_exists($offset, $this->array);
}

public function offsetGet($offset) : object
{
if (!$this->offsetExists($offset)) {
throw new \Exception('Item doesnt exist.');
}

return $this->array[$offset];
}

public function offsetSet($offset, $object) : void
{
if (!\is_a($object, static::INNER_CLASS)) {
throw new \Exception('Invalid input.');
}

$key = $this->getKey($object);

if ($offset === null) {
if ($key === null) {
$this->array[] = $object;

return;
}

if ($this->offsetExists($key)) {
throw new \Exception('Duplicated item. Set using explicit key if you wish to replace.');
}

$this->array[$key] = $object;
$this->array[] = $object;

return;
}

if (($key === null && \is_int($offset)) || (\is_string($key) && \is_string($offset) && $key === $offset)) {
if (\is_int($offset)) {
$this->array[$offset] = $object;

return;
}

throw new \Exception('Invalid offset for given object.');
}

public function offsetUnset($offset) : void
{
if (!$this->offsetExists($offset)) {
throw new \Exception('Item already doesnt exist.');
}

unset($this->array[$offset]);
}

protected function getKey(object $object) : ?string
{
return null;
}
}
16 changes: 5 additions & 11 deletions tests/Utils/EmptyClassSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,11 @@

namespace Infinityloop\Tests\Utils;

class EmptyClassSet extends \Infinityloop\Utils\ObjectSet
/**
* @method \Infinityloop\Tests\Utils\EmptyClass current() : object
* @method \Infinityloop\Tests\Utils\EmptyClass offsetGet($offset) : object
*/
final class EmptyClassSet extends \Infinityloop\Utils\ObjectSet
{
protected const INNER_CLASS = EmptyClass::class;

public function current() : EmptyClass
{
return parent::current();
}

public function offsetGet($offset) : EmptyClass
{
return parent::offsetGet($offset);
}
}
Loading

0 comments on commit af11415

Please sign in to comment.