示例#1
0
 /**
  * Check if the constraint is met.
  *
  * @param mixed $value
  * @param array $context
  *
  * @throws LackOfCoffeeException
  * @return mixed
  */
 public function check($value, array $context = [])
 {
     $closure = $this->closure;
     $result = $closure($value, $context);
     if (!is_bool($result)) {
         throw new LackOfCoffeeException(vsprintf('Inner closure of constraint was expected to return a' . ' boolean value. Got %s instead.', [TypeHound::fetch($result)]));
     }
     return $result;
 }
示例#2
0
 /**
  * Concatenate the two provided values.
  *
  * @param string|array|Traversable $one
  * @param string|array|Traversable $other
  *
  * @throws MismatchedArgumentTypesException
  * @throws InvalidArgumentException
  * @return mixed
  */
 public static function concat($one, $other)
 {
     Arguments::define(Boa::either(Boa::lst(), Boa::string()), Boa::either(Boa::lst(), Boa::string()))->check($one, $other);
     $oneType = TypeHound::fetch($one);
     $twoType = TypeHound::fetch($other);
     if ($oneType !== $twoType) {
         throw new MismatchedArgumentTypesException(__FUNCTION__, $one, $other);
     }
     if ($oneType === ScalarTypes::SCALAR_STRING) {
         return $one . $other;
     }
     return ArrayMap::of($one)->append(ArrayMap::of($other))->toArray();
 }
示例#3
0
 /**
  * Escape the provided string.
  *
  * @param SafeHtmlWrapper|SafeHtmlProducerInterface|string $string
  *
  * @throws CoreException
  * @throws InvalidArgumentException
  * @return SafeHtmlWrapper|string
  */
 public static function escape($string)
 {
     Arguments::define(Boa::either(Boa::either(Boa::instance(SafeHtmlWrapper::class), Boa::instance(SafeHtmlProducerInterface::class)), Boa::string()))->check($string);
     if ($string instanceof SafeHtmlWrapper) {
         return $string;
     } elseif ($string instanceof SafeHtmlProducerInterface) {
         $result = $string->getSafeHtml();
         if ($result instanceof SafeHtmlWrapper) {
             return $result;
         } elseif ($result instanceof SafeHtmlProducerInterface) {
             return static::escape($result);
         }
         throw new CoreException(vsprintf('Object of class %s implements SafeHtmlProducerInterface' . ' but it returned an unsafe type: %s', [get_class($string), TypeHound::fetch($result)]));
     }
     return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
 }
示例#4
0
 public function testIsKnown()
 {
     $this->assertEqualsMatrix([[true, TypeHound::isKnown(ScalarTypes::SCALAR_BOOLEAN)], [true, TypeHound::isKnown(ScalarTypes::SCALAR_FLOAT)], [true, TypeHound::isKnown(ScalarTypes::SCALAR_INTEGER)], [true, TypeHound::isKnown(ScalarTypes::SCALAR_STRING)], [true, TypeHound::isKnown(CompoundTypes::COMPOUND_ARRAY)], [true, TypeHound::isKnown(CompoundTypes::COMPOUND_OBJECT)], [true, TypeHound::isKnown(SpecialTypes::SPECIAL_NULL)], [true, TypeHound::isKnown(SpecialTypes::SPECIAL_RESOURCE)]]);
 }
示例#5
0
 /**
  * Get an instance of the model being generated.
  *
  * Note: The instance will be cached after being created for the first
  * time.
  *
  * @param bool $flush Remove old instance
  *
  * @throws LackOfCoffeeException
  * @return Model
  */
 protected function getModelInstance($flush = false)
 {
     if ($this->modelInstance !== null && $flush === false) {
         return $this->modelInstance;
     }
     $model = new $this->model();
     if (!$model instanceof Model) {
         throw new LackOfCoffeeException(vsprintf('ModelGenerator only supports generating instances of' . ' %s. Got %s', [Model::class, TypeHound::fetch($model)]));
     }
     $this->modelInstance = $model;
     return $model;
 }
 /**
  * Construct an instance of a NodeChildRenderingException.
  *
  * @param mixed $content
  * @param int $code
  * @param Exception|null $previous
  */
 public function __construct($content, $code = 0, Exception $previous = null)
 {
     parent::__construct(vsprintf('Unknown child content type: %s. ' . 'Node child item cannot be rendered.', [TypeHound::fetch($content)]), $code, $previous);
     $this->content = $content;
 }
 /**
  * Check if the constraint is met.
  *
  * @param mixed $value
  * @param array $context
  *
  * @throws UnknownTypeException
  * @return mixed
  */
 public function check($value, array $context = [])
 {
     $hound = new TypeHound($value);
     return $this->expectedType === $hound->resolve();
 }
示例#8
0
 /**
  * Check that the type matches.
  *
  * @param TypeHound $other
  *
  * @throws UnknownTypeException
  * @return bool
  */
 public function matches(TypeHound $other)
 {
     return $this->resolve() === $other->resolve();
 }
示例#9
0
 /**
  * Validate and discover all the relationships on a model.
  *
  * @return Relation[]
  */
 protected function discoverRelations()
 {
     if ($this->relations === null) {
         $this->relations = [];
         Std::each(function ($name) {
             // Check that the relationship method is there.
             if (!method_exists($this->model, $name)) {
                 throw new LackOfCoffeeException(vsprintf('The model declares a relationship named "%s" but' . ' there is no method with that name.', [$name]));
             }
             $relationReflector = new ReflectionMethod($this->model, $name);
             if (!$relationReflector->isPublic()) {
                 throw new LackOfCoffeeException(vsprintf('The method for the relationship named "%s" should' . ' be public.', [$name]));
             }
             $argumentCount = $relationReflector->getNumberOfParameters();
             if ($argumentCount > 0) {
                 throw new LackOfCoffeeException(vsprintf('The method for the relationship named "%s" should' . ' take 0 arguments. However, it requires %d.', [$name, $argumentCount]));
             }
             $relation = $this->model->{$name}();
             if (!$relation instanceof Relation) {
                 throw new LackOfCoffeeException(vsprintf('The method for the relationship named "%s" should' . ' return an instance of %s. Got %s.', [$name, Relation::class, TypeHound::fetch($relation)]));
             }
             $this->relations[$name] = $relation;
         }, $this->model->getRelated());
     }
     return $this->relations;
 }
 /**
  * Set the expected class and the received value.
  *
  * @param string|object $expected
  * @param mixed $received
  */
 public function setExpectedAndReceived($expected, $received)
 {
     $this->expected = is_string($expected) ? $expected : get_class($expected);
     $this->received = TypeHound::fetch($received);
     $this->message = vsprintf('An instance of a %s was expected but got %s', [$this->expected, $this->received]);
 }
示例#11
0
 /**
  * Check that a certain input passes the spec.
  *
  * @param mixed $input
  *
  * @return SpecResult
  */
 public function check(array $input)
 {
     $missing = [];
     $invalid = [];
     $check = function ($constraint, $key, $value, $input) use(&$missing, &$invalid) {
         if ($constraint instanceof AbstractConstraint) {
             if (!$constraint->check($value, $input)) {
                 $invalid[$key][] = $constraint;
             }
         } elseif ($constraint instanceof CheckableInterface) {
             $result = $constraint->check($value);
             $missing = Std::concat($missing, array_map(function ($subKey) use($key) {
                 return vsprintf('%s.%s', [$key, $subKey]);
             }, $result->getMissing()));
             foreach ($result->getFailed() as $failedField => $constraints) {
                 $fullPath = vsprintf('%s.%s', [$key, $failedField]);
                 if (array_key_exists($fullPath, $invalid)) {
                     $invalid[$fullPath] = array_merge($invalid[$fullPath], $constraints);
                 } else {
                     $invalid[$fullPath] = $constraints;
                 }
             }
         } else {
             throw new CoreException(vsprintf('Unexpected constraint type: %s.', [TypeHound::fetch($constraint)]));
         }
     };
     $inputMap = ArrayMap::of($input);
     $this->annotations->each(function ($value, $key) use($check, $input, $inputMap, &$missing) {
         // If a field is required but not present, we should report it.
         if (Maybe::fromMaybe(false, $value->lookup(static::ANNOTATION_REQUIRED)) && $inputMap->member($key) === false) {
             $missing[] = $key;
             // There's no point on checking constraints on the field
             // since it is missing.
             return;
         } elseif ($inputMap->member($key) === false) {
             // There's no point on checking constraints on the field
             // since it is missing.
             return;
         }
         $fieldValue = Maybe::fromJust($inputMap->lookup($key));
         $this->getInternalFieldConstraints($key)->each(function ($constraint) use($check, $key, $fieldValue, $input) {
             $check($constraint, $key, $fieldValue, $input);
         });
     });
     if (count($missing) === 0 && count($invalid) === 0) {
         return new SpecResult($missing, $invalid, SpecResult::STATUS_PASS);
     }
     return new SpecResult($missing, $invalid, SpecResult::STATUS_FAIL);
 }
 /**
  * Construct an instance of a MismatchedArgumentTypesException.
  *
  * @param string $functionName
  * @param mixed $arguments
  */
 public function __construct($functionName, ...$arguments)
 {
     parent::__construct(vsprintf('Argument type mismatch: %s for function %s', [ArrayList::of($arguments)->map(function ($item) {
         return TypeHound::fetch($item);
     })->join(', '), $functionName]));
 }
示例#13
0
 public function testCurry()
 {
     $rest = 0;
     $adder = function ($a, $b, $c, $d) {
         return $a + $b + $c + $d;
     };
     $variadicAdder = function (...$args) {
         return Std::foldl(function ($acc, $cur) {
             return $acc + $cur;
         }, 0, $args);
     };
     $partiallyVariadicAdder = function ($a, $b, $c, ...$args) use(&$rest) {
         $rest = Std::foldl(function ($acc, $cur) {
             return $acc + $cur;
         }, 0, $args);
         return $a + $b + $c;
     };
     $one = Std::curry($adder, 2, 5);
     $two = $one(6);
     // Here we test adding one additional parameter that was not expected.
     // This should allow us to support partially variadic functions.
     $three = $two(10, 1000);
     $this->assertEquals(23, $three);
     // Variadic functions will return immediately since we can't determine
     // when they have been fulfilled.
     $four = Std::curry($variadicAdder, 2, 5);
     $this->assertEquals(ScalarTypes::SCALAR_INTEGER, TypeHound::fetch($four));
     $this->assertEquals(7, $four);
     $seven = Std::curry($partiallyVariadicAdder, 8, 5);
     $eight = $seven(9, 102, 20);
     $this->assertEquals(ScalarTypes::SCALAR_INTEGER, TypeHound::fetch($eight));
     $this->assertEquals(22, $eight);
     $this->assertEquals(122, $rest);
 }