Skip to content

Commit

Permalink
Merge pull request #9 from Rican7/feature/null-safe-context
Browse files Browse the repository at this point in the history
Feature - Null safe context
  • Loading branch information
Rican7 authored Feb 8, 2018
2 parents 584df3c + 14ed7af commit 6ef2ae2
Show file tree
Hide file tree
Showing 12 changed files with 550 additions and 47 deletions.
36 changes: 36 additions & 0 deletions src/Incoming/Hydrator/AbstractDelegateContextualBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,37 @@
abstract class AbstractDelegateContextualBuilder extends AbstractDelegateBuilder implements ContextualBuilder
{

/**
* Properties
*/

/**
* Whether or not to provide a fallback empty context, when a `null` context
* is otherwise provided, to make processes simpler by not having to rely on
* null checks of the actual parameter before usage.
*
* @var bool
*/
private $provide_fallback_context = false;


/**
* Methods
*/

/**
* Constructor
*
* @param bool $provide_fallback_context Whether or not to provide a
* fallback empty context, when a `null` context is otherwise provided, to
* make processes simpler by not having to rely on null checks of the
* actual parameter before usage.
*/
protected function __construct(bool $provide_fallback_context = false)
{
$this->provide_fallback_context = $provide_fallback_context;
}

/**
* {@inheritdoc}
*
Expand All @@ -34,6 +65,11 @@ public function build($incoming, Map $context = null)
{
$callable = $this->getDelegate();

if (null === $context && $this->provide_fallback_context) {
// Provide a non-null context so null checks aren't later required
$context = new Map();
}

return $callable($incoming, $context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,37 @@ abstract class AbstractDelegateContextualBuilderHydrator extends AbstractDelegat
ContextualHydrator
{

/**
* Properties
*/

/**
* Whether or not to provide a fallback empty context, when a `null` context
* is otherwise provided, to make processes simpler by not having to rely on
* null checks of the actual parameter before usage.
*
* @var bool
*/
private $provide_fallback_context = false;


/**
* Methods
*/

/**
* Constructor
*
* @param bool $provide_fallback_context Whether or not to provide a
* fallback empty context, when a `null` context is otherwise provided, to
* make processes simpler by not having to rely on null checks of the
* actual parameter before usage.
*/
protected function __construct(bool $provide_fallback_context = false)
{
$this->provide_fallback_context = $provide_fallback_context;
}

/**
* {@inheritdoc}
*
Expand All @@ -38,6 +69,11 @@ public function build($incoming, Map $context = null)
{
$callable = $this->getDelegateBuilder();

if (null === $context && $this->provide_fallback_context) {
// Provide a non-null context so null checks aren't later required
$context = new Map();
}

return $callable($incoming, $context);
}

Expand All @@ -54,6 +90,11 @@ public function hydrate($incoming, $model, Map $context = null)
{
$callable = $this->getDelegateHydrator();

if (null === $context && $this->provide_fallback_context) {
// Provide a non-null context so null checks aren't later required
$context = new Map();
}

return $callable($incoming, $model, $context);
}
}
36 changes: 36 additions & 0 deletions src/Incoming/Hydrator/AbstractDelegateContextualHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,37 @@
abstract class AbstractDelegateContextualHydrator extends AbstractDelegateHydrator implements ContextualHydrator
{

/**
* Properties
*/

/**
* Whether or not to provide a fallback empty context, when a `null` context
* is otherwise provided, to make processes simpler by not having to rely on
* null checks of the actual parameter before usage.
*
* @var bool
*/
private $provide_fallback_context = false;


/**
* Methods
*/

/**
* Constructor
*
* @param bool $provide_fallback_context Whether or not to provide a
* fallback empty context, when a `null` context is otherwise provided, to
* make processes simpler by not having to rely on null checks of the
* actual parameter before usage.
*/
protected function __construct(bool $provide_fallback_context = false)
{
$this->provide_fallback_context = $provide_fallback_context;
}

/**
* {@inheritdoc}
*
Expand All @@ -35,6 +66,11 @@ public function hydrate($incoming, $model, Map $context = null)
{
$callable = $this->getDelegate();

if (null === $context && $this->provide_fallback_context) {
// Provide a non-null context so null checks aren't later required
$context = new Map();
}

return $callable($incoming, $model, $context);
}
}
110 changes: 110 additions & 0 deletions src/Incoming/Hydrator/Exception/IncompatibleProcessException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php
/**
* Incoming
*
* @author Trevor Suarez (Rican7)
* @copyright (c) Trevor Suarez
* @link https://github.com/Rican7/incoming
* @license MIT
*/

declare(strict_types=1);

namespace Incoming\Hydrator\Exception;

use Incoming\Hydrator\Builder;
use Incoming\Hydrator\Hydrator;
use Throwable;
use UnexpectedValueException;

/**
* An exception to be thrown when a hydrator or builder is incompatible with an
* expected process strategy, such as when a non-context-compatible hydrator is
* provided with a non-null context.
*/
class IncompatibleProcessException extends UnexpectedValueException
{

/**
* Constants
*/

/**
* The default exception message.
*
* @var string
*/
const DEFAULT_MESSAGE = 'Provided or resolved process is not compatible';

/**
* The exception code for when context compatibility is required.
*
* @var int
*/
const CODE_FOR_REQUIRED_CONTEXT_COMPATIBILITY = 1;

/**
* The exception code for when a hydrator is used as the process.
*
* @var int
*/
const CODE_FOR_HYDRATOR = 2;

/**
* The exception code for when a builder is used as the process.
*
* @var int
*/
const CODE_FOR_BUILDER = 4;

/**
* The message extension (appended to the default message) for when context
* compatibility is required.
*
* @var string
*/
const MESSAGE_EXTENSION_FOR_REQUIRED_CONTEXT_COMPATIBILITY = ' due to requiring context compatibility';


/**
* Properties
*/

/**
* The exception message.
*
* @var string
*/
protected $message = self::DEFAULT_MESSAGE;


/**
* Methods
*/

/**
* Create an exception instance for when context compatibility is required.
*
* @param object|null $process The incompatible process.
* @param int $code The exception code.
* @param Throwable|null $previous A previous exception used for chaining.
* @return static The newly created exception.
*/
public static function forRequiredContextCompatibility(
$process = null,
int $code = self::CODE_FOR_REQUIRED_CONTEXT_COMPATIBILITY,
Throwable $previous = null
): self {
if (self::CODE_FOR_REQUIRED_CONTEXT_COMPATIBILITY === $code) {
if ($process instanceof Hydrator) {
$code += self::CODE_FOR_HYDRATOR;
} elseif ($process instanceof Builder) {
$code += self::CODE_FOR_BUILDER;
}
}

$message = self::DEFAULT_MESSAGE . self::MESSAGE_EXTENSION_FOR_REQUIRED_CONTEXT_COMPATIBILITY;

return new static($message, $code, $previous);
}
}
Loading

0 comments on commit 6ef2ae2

Please sign in to comment.