Git viewing holonet/common / d0112e97243643d96b80acfee811b0117e460cd2


Filter

d0112e97243643d96b80acfee811b0117e460cd2

Matthias Lantsch(11 months ago)

Rework collection classes. Remove unused methods / classes

Browse Files
  • Changed file psalm.xml
    diff --git a/d97637caf43966a4293e98526aa8804762fe43a2 b/0bfa773fc80a214396f5c4441d3fc97ea1215cda
    index d97637c..0bfa773 100644
    --- a/d97637caf43966a4293e98526aa8804762fe43a2
    +++ b/0bfa773fc80a214396f5c4441d3fc97ea1215cda
    @@ -5,6 +5,7 @@
     	reportMixedIssues="false"
       findUnusedPsalmSuppress="true"
       findUnusedBaselineEntry="true"
    +  findUnusedCode="false"
     	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     	xmlns="https://getpsalm.org/schema/config"
     	xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
  • Removed file ComparableInterface.php
  • Changed file ChangeAwareCollection.php
    diff --git a/ceda524845255f96824216ccf0e678a49e59f53d b/69958a66e10c26fd6ae1912e172cf3762a78fb6b
    index ceda524..69958a6 100644
    --- a/ceda524845255f96824216ccf0e678a49e59f53d
    +++ b/69958a66e10c26fd6ae1912e172cf3762a78fb6b
    @@ -9,24 +9,26 @@
    
     namespace holonet\common\collection;
    
    -use Countable;
     use ArrayAccess;
     use ArrayIterator;
    +use Countable;
    +use Iterator;
     use IteratorAggregate;
    -use holonet\common\ComparableInterface;
    +use OutOfBoundsException;
    
     /**
      * The ChangeAwareCollection is used as a wrapper around an array
      * it keeps track internally on how it's data changed.
    + * @psalm-suppress MissingTemplateParam
      */
    -class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countable, IteratorAggregate {
    +class ChangeAwareCollection implements Countable, ArrayAccess, IteratorAggregate {
     	/**
     	 * Array with $all keys of newly added entries.
     	 */
     	protected array $added = array();
    
     	/**
    -	 * @var array<int|string, mixed> $all An array containing all entries
    +	 * @var array<string, mixed> $all An array containing all entries
     	 */
     	protected array $all = array();
    
    @@ -49,35 +51,28 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     	 * @param mixed $entry Either the key or the value that changes
     	 * @return mixed reference to the value or null if it doesn't exist
     	 */
    -	public function &change($entry): mixed {
    +	public function &change(mixed $entry): mixed {
     		$key = $this->findKeyForKeyOrEntry($entry);
     		if ($key !== null) {
     			$this->changed[] = $key;
    
     			return $this->all[$key];
     		}
    +
    +		throw new OutOfBoundsException("Entry not found");
     	}
    
     	/**
     	 * @param mixed $val The data entry to be saved
    -	 * @param string|null $key The key to save the entry under
    +	 * @param string $key The key to save the entry under
     	 * @param bool $new Flag marking this entry as not new (not to be saved into $this->added)
     	 */
    -	public function add($val, ?string $key = null, bool $new = true): void {
    +	public function add(mixed $val, string $key, bool $new = true): void {
     		if (is_object($val) && is_subclass_of($val, ChangeAwareInterface::class)) {
     			$val->belongsTo($this);
    -			//not every change aware object can know about a unique key
    -			if (method_exists($val, 'uniqKey') && $key === null) {
    -				$key = $val->uniqKey();
    -			}
     		}
    
    -		if ($key === null) {
    -			$this->all[] = $val;
    -			$key = array_search($val, $this->all, true);
    -		} else {
    -			$this->all[$key] = $val;
    -		}
    +		$this->all[$key] = $val;
    
     		//if the override flag wasn't given, mark the entry as newly added
     		if ($new) {
    @@ -90,8 +85,8 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     	 * @param bool $new Flag marking these entries as not new (not to be saved into $this->added)
     	 */
     	public function addAll(array $values, bool $new = true): void {
    -		foreach ($values as $val) {
    -			$this->add($val, null, $new);
    +		foreach ($values as $key => $val) {
    +			$this->add($val, $key, $new);
     		}
     	}
    
    @@ -109,19 +104,6 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     		return !empty($this->added) || !empty($this->removed) || !empty($this->changed);
     	}
    
    -	/**
    -	 * compare this attribute set to another attribute set.
    -	 * @param ComparableInterface $other The other object to compare this one to
    -	 * @return bool if this object should be considered the same attribute set as the other one
    -	 */
    -	public function compareTo(ComparableInterface $other): bool {
    -		if (!$other instanceof self) {
    -			return false;
    -		}
    -
    -		return $this->compareToCollection($other);
    -	}
    -
     	/**
     	 * Only counts the "current" entries
     	 * {@inheritDoc}
    @@ -143,6 +125,8 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     		if (isset($this->all[$key]) && !in_array($key, $this->removed)) {
     			return $this->all[$key];
     		}
    +
    +		return null;
     	}
    
     	/**
    @@ -188,60 +172,8 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     		return $this->all;
     	}
    
    -	/**
    -	 * {@inheritDoc}
    -	 */
    -	public function getIterator(): ArrayIterator {
    -		return new ArrayIterator($this->getAll());
    -	}
    -
    -	public function has($value): bool {
    -		//if the given value is comparable, we can use that to find it
    -		if (is_object($value) && $value instanceof ComparableInterface) {
    -			foreach ($this->getAll('current') as $entry) {
    -				if (is_object($entry) && $entry instanceof ComparableInterface && $entry->compareTo($value)) {
    -					return true;
    -				}
    -			}
    -		} else {
    -			return in_array($value, $this->getAll('current'), true);
    -		}
    -
    -		return false;
    -	}
    -
    -	/**
    -	 * Does not return true for "removed" entries.
    -	 * {@inheritDoc}
    -	 */
    -	public function offsetExists($offset): bool {
    -		return isset($this->all[$offset]) && !in_array($offset, $this->removed);
    -	}
    -
    -	/**
    -	 * Does only return values that aren't "removed".
    -	 * {@inheritDoc}
    -	 * @see self::get()
    -	 */
    -	public function offsetGet($offset) {
    -		return $this->get($offset);
    -	}
    -
    -	/**
    -	 * {@inheritDoc}
    -	 * @see self::set()
    -	 */
    -	public function offsetSet($offset, $value): void {
    -		$this->set($offset, $value);
    -	}
    -
    -	/**
    -	 * Does only add the entry to "removed".
    -	 * {@inheritDoc}
    -	 * @see self::remove()
    -	 */
    -	public function offsetUnset($offset): void {
    -		$this->remove($offset);
    +	public function has(mixed $value): bool {
    +		return $this->findKeyForKeyOrEntry($value) !== null;
     	}
    
     	/**
    @@ -249,7 +181,7 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     	 * @param mixed $entry Either the key or the value that changes
     	 * @return bool true or false on success or not
     	 */
    -	public function remove($entry): bool {
    +	public function remove(mixed $entry): bool {
     		$key = $this->findKeyForKeyOrEntry($entry);
     		if ($key !== null) {
     			$this->removed[] = $key;
    @@ -273,15 +205,15 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     	/**
     	 * setter function to set a value by its key
     	 * either calls the add function or set the value.
    -	 * @param string|null $key The key for the value
    +	 * @param string $key The key for the value
     	 * @param mixed $value The value that is to be set
     	 */
    -	public function set(?string $key, $value): void {
    -		if ($key === null || !array_key_exists($key, $this->all)) {
    +	public function set(string $key, mixed $value): void {
    +		if (!array_key_exists($key, $this->all)) {
     			$this->add($value, $key);
     		} else {
     			if ($this->all[$key] !== $value) {
    -				$this->change($key);
    +				$this->changed[] = $key;
     			}
    
     			if (is_object($value) && is_subclass_of($value, ChangeAwareInterface::class)) {
    @@ -292,16 +224,6 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     		}
     	}
    
    -	/**
    -	 * compare this attribute set to another attribute set.
    -	 * @param ChangeAwareCollection $other The other object to compare this one to
    -	 * @return bool if this object should be considered the same attribute set as the other one
    -	 */
    -	private function compareToCollection(self $other): bool {
    -		return $this->all === $other->all && $this->changed === $other->changed
    -			&& $this->added === $other->added && $this->removed === $other->removed;
    -	}
    -
     	/**
     	 * helper function to figure out what an argument is
     	 * first assumes the argument is a key
    @@ -310,19 +232,46 @@ class ChangeAwareCollection implements ArrayAccess, ComparableInterface, Countab
     	 * @param mixed $entry Either the key or the value
     	 * @return mixed|null the key of the value/the key if it's a key
     	 */
    -	private function findKeyForKeyOrEntry($entry): mixed {
    +	private function findKeyForKeyOrEntry(mixed $entry): ?string {
     		//check if $entry is an array key (allow null, so no isset)
    -		if ((is_string($entry) || is_int($entry)) && array_key_exists($entry, $this->all)) {
    +		if (is_string($entry) && array_key_exists($entry, $this->all)) {
     			return $entry;
     		}
    -		if (is_object($entry) && $entry instanceof ComparableInterface) {
    -			foreach ($this->all as $key => $value) {
    -				if ($value instanceof ComparableInterface && $entry->compareTo($value)) {
    -					return $key;
    -				}
    -			}
    -		} elseif (($key = array_search($entry, $this->all)) !== false) {
    +
    +		if (($key = array_search($entry, $this->all, true)) !== false) {
     			return $key;
     		}
    +
    +		return null;
    +	}
    +
    +	public function offsetExists(mixed $offset): bool {
    +		// specifically use isset() in order to return false on null values
    +		return isset($this->all[$offset]) && !in_array($offset, $this->removed);
    +	}
    +
    +	/**
    +	 * @see self::get()
    +	 */
    +	public function offsetGet(mixed $offset): mixed {
    +		return $this->get($offset);
    +	}
    +
    +	/**
    +	 * @see self::set()
    +	 */
    +	public function offsetSet(mixed $offset, mixed $value): void {
    +		$this->set($offset, $value);
    +	}
    +
    +	/**
    +	 * @see self::remove()
    +	 */
    +	public function offsetUnset(mixed $offset): void {
    +		$this->remove($offset);
    +	}
    +
    +	public function getIterator(): Iterator {
    +		return new ArrayIterator($this->getAll());
     	}
     }
  • Changed file ChangeAwareTrait.php
    diff --git a/d10b0620b948e97a9d30827c4f190cfe1611d0f6 b/d6a2eac05bc14dd84411460028e13cf6e055c3e9
    index d10b062..d6a2eac 100644
    --- a/d10b0620b948e97a9d30827c4f190cfe1611d0f6
    +++ b/d6a2eac05bc14dd84411460028e13cf6e055c3e9
    @@ -13,7 +13,7 @@ trait ChangeAwareTrait {
     	/**
     	 * holds a reference to the ChangeAwareCollection that is keeping track of this object.
     	 */
    -	private ChangeAwareCollection $partOfCollection;
    +	private ?ChangeAwareCollection $partOfCollection = null;
    
     	/**
     	 * @param ChangeAwareCollection $coll A reference to the collection this object is part of
  • Changed file Collection.php
    diff --git a/a032ecc3cd200babc8e821b4c22b6afbc67a0651 b/1143f81053f5f8ef420d7160d252fae32606b2b4
    index a032ecc..1143f81 100644
    --- a/a032ecc3cd200babc8e821b4c22b6afbc67a0651
    +++ b/1143f81053f5f8ef420d7160d252fae32606b2b4
    @@ -10,15 +10,18 @@
     namespace holonet\common\collection;
    
     use Countable;
    -use ArrayAccess;
     use ArrayIterator;
     use IteratorAggregate;
    
     /**
      * The Collection is used as a wrapper around a data array
      * it allows for the data to be accessed like an array or object.
    + * @template TKey of array-key
    + * @template T
    + *
    + * @implements IteratorAggregate<array-key, T>
      */
    -class Collection implements ArrayAccess, Countable, IteratorAggregate {
    +class Collection implements Countable, IteratorAggregate {
     	protected array $data = array();
    
     	public function __construct(array $initial = array()) {
    @@ -50,7 +53,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate {
     	 * return a reference so we can change e.g. sub arrays from this call
     	 *  => cannot use our own get() method.
     	 */
    -	public function &__get(string $key) {
    +	public function __get(string $key): mixed {
     		if (is_object($this->data[$key]) || $this->data[$key] === null) {
     			//only actual variables should be returned by reference
     			return $this->data[$key];
    @@ -81,7 +84,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate {
     	/**
     	 * @param string[] $which Array with keys that are requested
     	 */
    -	public function getAll(?array $which = null): array {
    +	public function all(?array $which = null): array {
     		if ($which !== null) {
     			return array_intersect_key($this->data, array_flip($which));
     		}
    @@ -108,39 +111,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate {
     		}
     	}
    
    -	/**
    -	 * {@inheritDoc}
    -	 * @see self::__isset()
    -	 */
    -	public function offsetExists($offset): bool {
    -		//use the isset method in order to return false for null value (the behaviour of isset())
    -		return $this->__isset($offset);
    -	}
    -
    -	/**
    -	 * {@inheritDoc}
    -	 * @see self::get()
    -	 */
    -	public function offsetGet($offset) {
    -		return $this->get($offset);
    -	}
    -
    -	/**
    -	 * {@inheritDoc}
    -	 * @see self::set()
    -	 */
    -	public function offsetSet($offset, $value): void {
    -		$this->set($offset, $value);
    -	}
    -
    -	/**
    -	 * {@inheritDoc}
    -	 * @see self::remove()
    -	 */
    -	public function offsetUnset($offset): void {
    -		$this->remove($offset);
    -	}
    -
     	public function remove(string $key): void {
     		unset($this->data[$key]);
     	}
  • Changed file Registry.php
    diff --git a/a45ef12f46df6871a502077a9d865e0ea42b5461 b/8bbbfc56bd777fa230760f9db2564a6153bd1b77
    index a45ef12..8bbbfc5 100644
    --- a/a45ef12f46df6871a502077a9d865e0ea42b5461
    +++ b/8bbbfc56bd777fa230760f9db2564a6153bd1b77
    @@ -18,7 +18,7 @@ use function holonet\common\dot_key_set;
      *  e.g. toplevel.lowerlevel => $data['toplevel']['lowerlevel']
      *  e.g. "%app.name%-test" => $data['app']['name'] . "-test".
      */
    -class Registry implements ArrayAccess {
    +class Registry {
     	/**
     	 * @var array<string, mixed> $data Multilevel array with key=value pairs
     	 */
    @@ -35,75 +35,35 @@ class Registry implements ArrayAccess {
     		$this->data = array();
     	}
    
    -	/**
    -	 * @see self::offsetGet()
    -	 */
     	public function get(string $key, mixed $default = null): mixed {
    -		return $this->offsetGet($key) ?? $default;
    -	}
    +		$value = dot_key_get($this->data, $key, separator: $this->separator);
    
    -	/**
    -	 * @see self::offsetExists()
    -	 */
    -	public function has(string $key): bool {
    -		return $this->offsetExists($key);
    +		return $this->replacePlaceholder($value) ?? $default;
     	}
    
    -	/**
    -	 * {@inheritDoc}
    -	 */
    -	public function offsetExists($offset): bool {
    -		$parts = explode($this->separator, $offset);
    +	public function has(string $key): bool {
    +		$parts = explode($this->separator, $key);
     		$position = $this->data;
    -		foreach ($parts as $sublevel) {
    -			if (!isset($position[$sublevel])) {
    +		foreach ($parts as $subLevel) {
    +			if (!isset($position[$subLevel])) {
     				return false;
     			}
    -			$position = $position[$sublevel];
    +			$position = $position[$subLevel];
     		}
    
     		return true;
     	}
    
    -	/**
    -	 * {@inheritDoc}
    -	 */
    -	public function offsetGet($offset): mixed {
    -		$value = dot_key_get($this->data, $offset, separator: $this->separator);
    -
    -		return $this->replacePlaceholder($value);
    -	}
    -
    -	/**
    -	 * {@inheritDoc}
    -	 */
    -	public function offsetSet($offset, $value): void {
    -		dot_key_set($this->data, $offset, $value, $this->separator);
    -	}
    -
    -	/**
    -	 * {@inheritDoc}
    -	 */
    -	public function offsetUnset($offset): void {
    -		dot_key_set($this->data, $offset, null, $this->separator);
    -	}
    -
    -	/**
    -	 * @see self::offsetSet()
    -	 */
     	public function set(string $key, $value): void {
    -		$this->offsetSet($key, $value);
    +		dot_key_set($this->data, $key, $value, $this->separator);
     	}
    
     	public function setAll(array $data): void {
     		$this->data = array_replace_recursive($this->data, $data);
     	}
    
    -	/**
    -	 * @see self::offsetUnset()
    -	 */
     	public function unset(string $key): void {
    -		$this->offsetUnset($key);
    +		dot_key_set($this->data, $key, null, $this->separator);
     	}
    
     	/**
  • Changed file ConfigRegistry.php
    diff --git a/9cd09b5663fc7ee8ef75de35be5def0279e7b7a2 b/d3abc9f92256688586cc8184c20bd645b558828d
    index 9cd09b5..d3abc9f 100644
    --- a/9cd09b5663fc7ee8ef75de35be5def0279e7b7a2
    +++ b/d3abc9f92256688586cc8184c20bd645b558828d
    @@ -22,7 +22,7 @@ class ConfigRegistry extends Registry {
     	/**
     	 * @template T
     	 * Get an instance of a config dto class supplied by the user.
    -	 * @param class-string<T>|T $cfgDto
    +	 * @psalm-param class-string<T>|T $cfgDto
     	 * @return T
     	 */
     	public function asDto(string $configKey, string|object $cfgDto): object {
    @@ -51,7 +51,7 @@ class ConfigRegistry extends Registry {
     	/**
     	 * @template T
     	 * Get a verified instance of a config dto class supplied by the user.
    -	 * @param class-string<T>|T $cfgDto
    +	 * @psalm-param class-string<T>|T $cfgDto
     	 * @return T
     	 */
     	public function verifiedDto(string $configKey, string|object $cfgDto): object {
  • Changed file functions.php
    diff --git a/a3a91deda75f58c115b6a114421878067ab6ab24 b/ca95b8884d1ed2a4e07e87642ed09b81350fabb1
    index a3a91de..ca95b88 100644
    --- a/a3a91deda75f58c115b6a114421878067ab6ab24
    +++ b/ca95b8884d1ed2a4e07e87642ed09b81350fabb1
    @@ -232,10 +232,10 @@ if (!function_exists(__NAMESPACE__.'\\dir_path')) {
    
     if (!function_exists(__NAMESPACE__.'\\str_lreplace')) {
     	/**
    -	 * Replace the last occurence of a string inside the subject.
    +	 * Replace the last occurrence of a string inside the subject.
     	 * Courtesy of https://stackoverflow.com/a/3835653.
     	 */
    -	function str_lreplace($search, $replace, $subject) {
    +	function str_lreplace(string $search, string $replace, string $subject): string {
     		$pos = mb_strrpos($subject, $search);
    
     		if ($pos !== false) {
  • Changed file Proof.php
    diff --git a/8f27807563f695c567daef9563b091fc5557d4fa b/cf2d9dbb16aa2d33b6cfc46e01d50fa6af8dc728
    index 8f27807..cf2d9db 100644
    --- a/8f27807563f695c567daef9563b091fc5557d4fa
    +++ b/cf2d9dbb16aa2d33b6cfc46e01d50fa6af8dc728
    @@ -34,7 +34,7 @@ class Proof {
    
     	public function flat(): array {
     		$all = array();
    -		array_walk_recursive($this->errors, function ($error) use (&$all): void { $all[] = $error; });
    +		array_walk_recursive($this->errors, function (string $error) use (&$all): void { $all[] = $error; });
    
     		return $all;
     	}
  • Changed file Rule.php
    diff --git a/2a5535d60af59ae09cbb23de6b3f048bd83839bb b/6c341bec8ad5a2425ba2b7e586fbe18d1b376df2
    index 2a5535d..6c341be 100644
    --- a/2a5535d60af59ae09cbb23de6b3f048bd83839bb
    +++ b/6c341bec8ad5a2425ba2b7e586fbe18d1b376df2
    @@ -12,8 +12,10 @@ namespace holonet\common\verifier\rules;
     use function holonet\common\stringify;
    
     abstract class Rule {
    -	public function __construct(public ?string $message = null) {
    -		$this->message ??= static::defaultMessage();
    +	public string $message;
    +
    +	public function __construct(string $message = null) {
    +		$this->message = $message ?? static::defaultMessage();
     	}
    
     	public static function defaultMessage(): string {
  • Changed file RegistryTest.php
    diff --git a/9f92571b617b7c98d18637656df09c9e29452e81 b/54fbfbb38efa0260c20bd1ff2c56f61e81f1e46e
    index 9f92571..54fbfbb 100644
    --- a/9f92571b617b7c98d18637656df09c9e29452e81
    +++ b/54fbfbb38efa0260c20bd1ff2c56f61e81f1e46e
    @@ -18,26 +18,6 @@ use PHPUnit\Framework\Attributes\CoversFunction;
     #[CoversFunction('holonet\common\dot_key_get')]
     #[CoversFunction('holonet\common\dot_key_set')]
     class RegistryTest extends TestCase {
    -	public function testArrayAccessCalls(): void {
    -		$registry = new Registry();
    -
    -		$data = array(
    -			'array' => array(
    -				'lowerval' => 'lower',
    -				'arrayarray' => array(
    -					'lowestval' => 'lowest'
    -				)
    -			)
    -		);
    -		$registry->setAll($data);
    -
    -		$this->assertSame('lowest', $registry['array.arrayarray.lowestval']);
    -		$this->assertTrue(isset($registry['array.lowerval']));
    -		$this->assertFalse(isset($registry['array.invalid']));
    -		unset($registry['array.lowerval.arrayarray']);
    -		$this->assertNull($registry['array.lowerval.arrayarray']);
    -	}
    -
     	public function testGetMultilevel(): void {
     		$registry = new Registry();
    
    @@ -51,6 +31,7 @@ class RegistryTest extends TestCase {
     		);
     		$registry->setAll($data);
    
    +		$this->assertFalse($registry->has('array.notexisting'));
     		$this->assertSame('lower', $registry->get('array.lowerval'));
     		$this->assertNull($registry->get('array.notexisting'));
     		$this->assertSame('lowest', $registry->get('array.arrayarray.lowestval'));