/** * Fill properties in this object using an input array. * * - Only fields that are mentioned in the fillable array can be set. * - Other keys will just be ignored completely. * - If a setter is present, it will be automatically called. * * @param array $input * * @return $this * @throws LackOfCoffeeException */ public function fill(array $input) { $this->assertIsFillable(); ArrayMap::of($input)->only($this->getFillable())->each(function ($value, $key) { $setter = vsprintf('set%s', [Str::studly($key)]); if (method_exists($this, $setter)) { $this->{$setter}($value); return; } $camel = Str::camel($key); $this->{$camel} = $value; }); return $this; }
/** * Get an environment variable or return the default if it is not defined. * * This avoid any post-processing, such as automatic casting. * * @param string $key * @param null|mixed|callable $default * * @return mixed|string */ public static function getRaw($key, $default = null) { $env = ArrayMap::of($_ENV); $server = ArrayMap::of($_SERVER); if ($env->member($key)) { return Maybe::fromJust($env->lookup($key)); } elseif ($server->member($key)) { return Maybe::fromJust($server->lookup($key)); } $value = getenv($key); if ($value === false) { return Std::thunk($default); } return $value; }
/** * Render the object into a string. * * @return mixed */ public function render() { $addColon = function ($label) { return Maybe::just(vsprintf('%s:', [$label])); }; return (new Form($this->attributes, $this->spec->getAnnotations()->map(function ($_, $key) use($addColon) { return new Row(['class' => 'form-group'], [new Node('label', ['class' => 'col-sm-2 form-control-label'], Maybe::fromMaybe('', $this->spec->getFieldLabel($key)->bind($addColon))), new Div(['class' => 'col-sm-8'], $this->renderFullField($key))]); })->append(ArrayMap::of([new Row(['class' => 'form-group'], [new Div(['class' => 'col-sm-offset-2 col-sm-10'], [new Div(['class' => 'btn-group'], [new Button(['type' => 'reset', 'class' => 'btn btn-secondary'], 'Reset'), new Button(['type' => 'submit', 'class' => 'btn btn-primary'], 'Submit')])])])]))))->render(); }
/** * Render the attributes part of the opening tag. * * @return string */ protected function renderAttributes() { return ArrayMap::of($this->attributes)->map(function ($value, $name) { return $this->renderAttribute($name, $value); })->join(' '); }
/** * @return ListInterface */ public static function toValuesList() { return ArrayMap::of(static::getValues())->values(); }
/** * Set properties of an object by only calling setters of array keys that * are set in the input array. Useful for parsing API responses into * entities. * * @param object $object * @param array $input * @param string[]|null $allowed */ public static function callSetters($object, array $input, array $allowed = null) { $filtered = ArrayMap::of($input); if ($allowed !== null) { $filtered = $filtered->only($allowed); } $filtered->each(function ($value, $key) use(&$object) { $setterName = 'set' . Str::studly($key); $object->{$setterName}($value); }); }
/** * 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); }
/** * Execute the transform. * * @param array $input * * @return array */ public function run(array $input) { return ArrayMap::of($input)->only($this->allowed)->toArray(); }