1: <?php
2:
3: 4: 5: 6: 7: 8:
9:
10: namespace Chromabits\Nucleus\Meditation;
11:
12: use Chromabits\Nucleus\Control\Maybe;
13: use Chromabits\Nucleus\Data\ArrayList;
14: use Chromabits\Nucleus\Data\ArrayMap;
15: use Chromabits\Nucleus\Foundation\BaseObject;
16: use Chromabits\Nucleus\Meditation\Constraints\AbstractConstraint;
17: use Chromabits\Nucleus\Meditation\Exceptions\InvalidArgumentException;
18: use Chromabits\Nucleus\Meditation\Exceptions\MismatchedArgumentTypesException;
19:
20: 21: 22: 23: 24: 25: 26:
27: class SpecFactory extends BaseObject
28: {
29: 30: 31:
32: const FIELD_SELF = '*';
33:
34: 35: 36:
37: protected $constraints;
38:
39: 40: 41:
42: protected $defaults;
43:
44: 45: 46:
47: protected $required;
48:
49: 50: 51:
52: public function __construct()
53: {
54: parent::__construct();
55:
56: $this->constraints = new ArrayMap();
57: $this->defaults = new ArrayMap();
58: $this->required = new ArrayList();
59: }
60:
61: 62: 63:
64: public static function define()
65: {
66: return new static();
67: }
68:
69: 70: 71: 72: 73: 74: 75: 76: 77:
78: public function letOnContext($constraint)
79: {
80: $this->defaultValue(static::FIELD_SELF, null);
81:
82: return $this->let(static::FIELD_SELF, $constraint);
83: }
84:
85: 86: 87: 88: 89: 90: 91: 92: 93:
94: public function defaultValue($field, $value)
95: {
96: Arguments::define(Boa::string(), Boa::any())->check($field, $value);
97:
98: $this->defaults = $this->defaults->insert($field, $value);
99:
100: return $this;
101: }
102:
103: 104: 105: 106: 107: 108: 109: 110: 111:
112: public function let($field, $constraint)
113: {
114: Arguments::define(
115: Boa::string(),
116: Boa::either(
117: Boa::instance(AbstractConstraint::class),
118: Boa::arrOf(Boa::instance(AbstractConstraint::class))
119: )
120: )->check($field, $constraint);
121:
122: if (!$this->constraints->member($field)) {
123: $this->constraints = $this->constraints->insert(
124: $field,
125: ArrayList::zero()
126: );
127: }
128:
129: if (!is_array($constraint)) {
130: $constraint = [$constraint];
131: }
132:
133: $this->constraints = $this->constraints->insert(
134: $field,
135: Maybe::fromMaybe(
136: ArrayList::zero(),
137: $this->constraints->lookup($field)
138: )->append(ArrayList::of($constraint))
139: );
140:
141: return $this;
142: }
143:
144: 145: 146: 147: 148: 149: 150: 151:
152: public function required($fields)
153: {
154: Arguments::define(
155: Boa::either(Boa::string(), Boa::arrOf(Boa::string()))
156: )->check($fields);
157:
158: if (!is_array($fields)) {
159: $fields = [$fields];
160: }
161:
162: $this->required = $this->required->append(ArrayList::of($fields));
163:
164: return $this;
165: }
166:
167: 168: 169: 170: 171:
172: public function make()
173: {
174: return new Spec(
175: $this->constraints->toArray(),
176: $this->defaults->toArray(),
177: $this->required->toArray()
178: );
179: }
180: }
181: