Skip to content
This repository has been archived by the owner on May 15, 2020. It is now read-only.

Commit

Permalink
[FEATURE] Direct execution, add ImplodeTransform and RecursiveReversible
Browse files Browse the repository at this point in the history
  • Loading branch information
vertexvaar committed Feb 7, 2020
1 parent 8a6f3e9 commit 05fa292
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 76 deletions.
17 changes: 17 additions & 0 deletions src/AbstractReversible.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace CoStack\Reversible;

abstract class AbstractReversible implements Reversible
{
public function execute($value)
{
return $this->getExecutionClosure()($value);
}

public function reverse($value)
{
return $this->getReversionClosure()($value);
}

}
38 changes: 12 additions & 26 deletions src/Encoding/Base64Encoding.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,33 @@
namespace CoStack\Reversible\Encoding;

use Closure;
use CoStack\Reversible\AbstractReversible;
use CoStack\Reversible\Exception\InvalidArgumentTypeException;
use CoStack\Reversible\Reversible;
use CoStack\Reversible\TypeLossy;
use function base64_decode;
use function base64_encode;
use function explode;
use function gettype;
use function is_array;
use function is_scalar;
use function json_decode;
use function json_encode;

class Base64Encoding implements Reversible
/**
* Lossy
*/
class Base64Encoding extends AbstractReversible implements TypeLossy
{
private const TYPE_ARRAY = 'array';
private const TYPE_SCALAR = 'scalar';
private const DELIMITER = '|';

public function getExecutionClosure(): Closure
{
return static function($value): string {
if (!(is_array($value) || is_scalar($value))) {
throw InvalidArgumentTypeException::create('value', 'array|scalar', gettype($value));
}
$type = self::TYPE_SCALAR;
if (is_array($value)) {
$value = json_encode($value);
$type = self::TYPE_ARRAY;
return function($value): string {
if (!is_scalar($value)) {
throw InvalidArgumentTypeException::create('value', 'scalar', gettype($value));
}
return $type . self::DELIMITER . base64_encode($value);
return base64_encode((string)$value);
};
}

public function getReversionClosure(): Closure
{
return static function(string $value) {
[$type, $value] = explode(self::DELIMITER, $value, 2);
$value = base64_decode($value);
if ($type === self::TYPE_ARRAY) {
$value = json_decode($value, true);
}
return $value;
return function(string $value): string {
return base64_decode($value, true);
};
}

Expand Down
24 changes: 20 additions & 4 deletions src/Encoding/JsonEncoding.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,46 @@
namespace CoStack\Reversible\Encoding;

use Closure;
use CoStack\Reversible\AbstractReversible;
use CoStack\Reversible\Exception;
use CoStack\Reversible\Exception\InvalidArgumentTypeException;
use CoStack\Reversible\Reversible;
use function gettype;
use function is_array;
use function is_scalar;
use function json_decode;
use function json_encode;
use function json_last_error;
use function json_last_error_msg;
use const JSON_ERROR_NONE;

class JsonEncoding implements Reversible
class JsonEncoding extends AbstractReversible
{
public function getExecutionClosure(): Closure
{
return static function($value): string {
if (!(is_array($value) || is_scalar($value))) {
throw InvalidArgumentTypeException::create('value', 'array|scalar', gettype($value));
}
return json_encode($value);
$value = json_encode($value);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new Exception(
'json_encode error: ' . json_last_error_msg()
);
}
return $value;
};
}

public function getReversionClosure(): Closure
{
return static function(string $value) {
return json_decode($value, true);
$value = json_decode($value, true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new Exception(
'json_decode error: ' . json_last_error_msg()
);
}
return $value;
};
}
}
4 changes: 2 additions & 2 deletions src/Encoding/RawUrlEncode.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
namespace CoStack\Reversible\Encoding;

use Closure;
use CoStack\Reversible\Reversible;
use CoStack\Reversible\AbstractReversible;
use function rawurldecode;
use function rawurlencode;

class RawUrlEncode implements Reversible
class RawUrlEncode extends AbstractReversible
{
public function getExecutionClosure(): Closure
{
Expand Down
4 changes: 2 additions & 2 deletions src/Encoding/SerializationEncoding.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
namespace CoStack\Reversible\Encoding;

use Closure;
use CoStack\Reversible\AbstractReversible;
use CoStack\Reversible\Exception\InvalidArgumentTypeException;
use CoStack\Reversible\Reversible;
use function gettype;
use function is_array;
use function is_object;
use function is_scalar;
use function serialize;
use function unserialize;

class SerializationEncoding implements Reversible
class SerializationEncoding extends AbstractReversible
{
public function getExecutionClosure(): Closure
{
Expand Down
4 changes: 2 additions & 2 deletions src/Encoding/UrlEncode.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
namespace CoStack\Reversible\Encoding;

use Closure;
use CoStack\Reversible\Reversible;
use CoStack\Reversible\AbstractReversible;
use function urldecode;
use function urlencode;

class UrlEncode implements Reversible
class UrlEncode extends AbstractReversible
{
public function getExecutionClosure(): Closure
{
Expand Down
17 changes: 17 additions & 0 deletions src/Exception/ArrayIsNotSequentialException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace CoStack\Reversible\Exception;

use CoStack\Reversible\Exception;
use function sprintf;

class ArrayIsNotSequentialException extends Exception
{
public const CODE = 1581089760;
public const MESSAGE = 'The array passed to "%s" is not sequential (it has associative keys).';

public static function create(string $method): ArrayIsNotSequentialException
{
return new self(sprintf(self::MESSAGE, $method), self::CODE);
}
}
2 changes: 1 addition & 1 deletion src/Exception/InvalidArgumentTypeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ class InvalidArgumentTypeException extends Exception

public static function create(string $name, string $expected, string $actual): InvalidArgumentTypeException
{
return new self(self::CODE, sprintf(self::MESSAGE, $name, $expected, $actual));
return new self(sprintf(self::MESSAGE, $name, $expected, $actual), self::CODE);
}
}
47 changes: 47 additions & 0 deletions src/Mapping/ArrayKeyMapping.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace CoStack\Reversible\Mapping;

use Closure;
use CoStack\Reversible\AbstractReversible;
use function array_flip;
use function ksort;

class ArrayKeyMapping extends AbstractReversible
{
private $mapping;

/**
* ArrayKeyMapping constructor.
* @param array $mapping Key = Numeric, Value = assoc index
*/
public function __construct(array $mapping)
{
$this->mapping = $mapping;
}

public function getExecutionClosure(): Closure
{
return function(array $value): array {
$mapping = array_flip($this->mapping);
$newValue = [];
foreach ($value as $key => $var) {
$newValue[$mapping[$key]] = $var;
}
ksort($newValue);
return $newValue;
};
}

public function getReversionClosure(): Closure
{
return function(array $value): array {
$newValue = [];
foreach ($this->mapping as $numIndex => $assocIndex) {
$newValue[$assocIndex] = $value[$numIndex];
}
return $newValue;
};
}

}
43 changes: 43 additions & 0 deletions src/RecursiveReversible.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace CoStack\Reversible;

use Closure;
use function array_map;
use function is_array;

class RecursiveReversible extends AbstractReversible
{
/** @var Reversible */
private $reversible;

public function __construct(Reversible $reversible)
{
$this->reversible = $reversible;
}

public function getExecutionClosure(): Closure
{
$reversible = $this->reversible;
$recursion = null;
return $recursion = static function($value) use (&$recursion, $reversible) {
if (is_array($value)) {
return array_map($recursion, $value);
}
return $reversible->getExecutionClosure()($value);
};
}

public function getReversionClosure(): Closure
{
$reversible = $this->reversible;
$recursion = null;
return $recursion = static function($value) use (&$recursion, $reversible) {
if (is_array($value)) {
return array_map($recursion, $value);
}
return $reversible->getReversionClosure()($value);
};
}

}
4 changes: 4 additions & 0 deletions src/Reversible.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@

interface Reversible
{
public function execute($value);

public function getExecutionClosure(): Closure;

public function reverse($value);

public function getReversionClosure(): Closure;
}
38 changes: 38 additions & 0 deletions src/ReversiblePipe.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace CoStack\Reversible;

use Closure;
use function array_reverse;

class ReversiblePipe extends AbstractReversible
{
/** @var Reversible[] */
protected $functions = [];

public function enqueue(Reversible $function): self
{
$this->functions[] = $function;
return $this;
}

public function getExecutionClosure(): Closure
{
return function($value) {
foreach ($this->functions as $function) {
$value = $function->execute($value);
}
return $value;
};
}

public function getReversionClosure(): Closure
{
return function($value) {
foreach (array_reverse($this->functions) as $function) {
$value = $function->reverse($value);
}
return $value;
};
}
}
39 changes: 0 additions & 39 deletions src/ReversibleQueue.php

This file was deleted.

Loading

0 comments on commit 05fa292

Please sign in to comment.