2 namespace Workspace\Contract;
10 abstract class AbstractBase
19 protected $inputs = array();
27 protected $requirement;
31 protected $conditionalCases = array();
35 protected $caseConditions = array();
39 protected $optionData = array();
43 protected $contractData = array();
47 protected $validation = array();
51 protected $data = array();
55 * Initialize contract with base use case.
56 * @param \Workspace\UseCase\Requirement $requirement
57 * @param array $packagedContract
58 * @param array $contractData
59 * @return \Workspace\Contract\UseOnce
61 public function __construct(
62 \Workspace\UseCase\Options $options = null,
63 \Workspace\UseCase\Requirement $requirement = null,
64 array $packagedContract = array(),
65 array $contractData = array(),
66 array $optionData = array()
69 if (!is_null($options) && !is_null($requirement))
71 $this->options = $options->package();
72 $this->requirement = $requirement->getRequirements();
73 $this->inputs = $requirement->getInputs();
75 else if (!empty($packagedContract))
77 $this->hydrate($packagedContract);
79 if (!empty($contractData))
81 $this->setContractData($contractData);
83 if (!empty($optionData))
85 $options = new \Workspace\UseCase\Options($this->options, $optionData);
86 $this->optionData = $options->getOptions();
91 * Set base requirement.
92 * @param \Workspace\UseCase\Requirement $requirement
93 * @return \Workspace\Contract\AbstractBase
95 public function setRequirement(\Workspace\UseCase\Requirement $requirement)
97 $this->requirement = $requirement->getRequirements();
98 $this->inputs = $requirement->getInputs();
103 * Add a conditional use case.
104 * @param string $name
105 * @param \Workspace\UseCase\ConditionBase $condition
106 * @param \Workspace\UseCase\Requirement $requirement
107 * @return \Workspace\Contract\UseOnce
109 public function addConditionalCase($name, \Workspace\UseCase\AbstractBase $condition, \Workspace\UseCase\Requirement $requirement)
111 $this->conditionalCases[$name] = array(
112 'Condition' => $condition->getPrerequisites(),
113 'Requirement' => $requirement->getRequirements()
115 $stack = $requirement->getInputs();
116 foreach ($stack as $group => $fieldSet)
118 isset($this->inputs[$group])
119 || $this->inputs[$group] = array();
120 $this->inputs[$group] = array_merge($this->inputs[$group], $fieldSet);
126 * Set contract dataset.
128 * @return \Workspace\Contract\AbstractBase
130 public function setData(array $data)
137 * Package this contract into an array.
140 public function package()
143 'LifeTime' => $this->lifeTime,
144 'Options' => $this->options,
145 'Requirement' => $this->requirement,
146 'Conditional' => $this->conditionalCases,
147 'Inputs' => $this->inputs,
148 'Data' => $this->data
153 * Hydrate contract from package.
154 * @param array $packagedContract
155 * @return \Workspace\Contract\UseOnce
157 public function hydrate(array $packagedContract)
159 $this->lifeTime = $packagedContract['LifeTime'];
160 $this->options = $packagedContract['Options'];
161 $this->requirement = $packagedContract['Requirement'];
162 $this->conditionalCases = $packagedContract['Conditional'];
163 $this->inputs = $packagedContract['Inputs'];
164 $this->data = $packagedContract['Data'];
169 * Set data inputs for contract.
170 * @param array $input
171 * @return \Workspace\Contract\AbstractBase
173 public function setContractData(array $input)
175 $this->contractData = array();
177 && $this->contractData['id'] = $input['id'];
178 foreach ($this->inputs as $group => $fieldSet)
180 $this->contractData[$group] = array();
181 foreach ($fieldSet as $field => $spec)
183 isset($input[$group][$field])
184 && $this->contractData[$group][$field] = $input[$group][$field];
191 * Retrieve filtered contract data.
194 public function getSignedContract($requestId, $hash)
196 $options = new \Workspace\Utility\ServiceInput('ParamSet', $this->optionData);
197 $data = new \Workspace\Utility\ServiceInput('ParamSet', $this->contractData);
198 $conditions = new \Workspace\Utility\ServiceInput('ParamSet', array(), $this->caseConditions);
199 $contract = new \Workspace\Utility\ServiceInput('Contract', array(
200 'requestId' => $requestId,
202 'options' => $options->pack(),
203 'data' => $data->pack(),
204 'conditions' => $conditions->pack()
206 return $contract->pack();
210 * Cleanup array values.
211 * @param array $input
214 protected function cleanupStack(array $input)
216 foreach ($input as $field => $value)
218 if (is_array($value))
220 $input[$field] = $this->cleanupStack($value);
223 $input[$field] = strip_tags($value);
231 protected function cleanupInputs()
233 $this->inputs = $this->cleanupStack($this->inputs);
237 * Evaluate the contract. IMPORTANT: setContractData() must be called before this method.
238 * @param \Workspace\Workflow $workflow
241 public function isValid(\Workspace\Workflow $workflow)
245 $messages['Base'] = $this->checkRequiredInputs($workflow, $this->requirement, $this->contractData);
246 !empty($messages['Base'])
248 foreach ($this->conditionalCases as $caseId => $case)
250 if ($this->checkCondition($case['Condition'], $this->contractData))
252 $this->caseConditions[$caseId] = $caseId;
253 $msgs = $this->checkRequiredInputs($workflow, $case['Requirement'], $this->contractData);
257 isset($messages['Conditional'])
258 || $messages['Conditional'] = array();
259 $messages['Conditional'][] = array('Condition' => $case['Condition'], 'Messages' => $msgs);
263 $this->validation = $messages;
264 $validator = new \Utility\Service\Validator();
265 if (!$validator->validateGroupedInputSet($this->inputs, $this->contractData))
268 $this->validation['ValidationErrors'] = $validator->getMessages();
274 * Retrieve validation error messages.
277 public function getMessages()
279 return $this->validation;
283 * Evaluate a condition collection.
284 * @param array $conditions
285 * @param array $input
288 protected function checkCondition(array $conditions, array $input)
291 return $this->checkStack($conditions['Operator'], $conditions['Conditions'], $input);
292 /* foreach ($conditions as $condition)
294 $cons = $condition['Conditions'];
295 $check = $this->checkStack($condition['Operator'], $condition['Conditions'], $input);
296 $valid = $valid && $check;
302 * Evaluate condition stack.
303 * @param string $base
304 * @param array $conditions
305 * @param array $input
308 protected function checkStack($base, array $conditions, array $input)
310 $valid = ('and' == $base)
313 foreach ($conditions as $condition)
315 if (!isset($condition['Conditions']))
317 list($group, $field) = explode('.', $condition['Input']);
318 if (!isset($input[$group][$field]))
329 switch($condition['Operator'])
332 $check = ($input[$group][$field] == $condition['Value']);
335 $check = ($input[$group][$field] != $condition['Value']);
338 $check = ($input[$group][$field] < $condition['Value']);
341 $check = ($input[$group][$field] > $condition['Value']);
344 $check = in_array($input[$group][$field], $condition['Value']);
347 $check = !in_array($input[$group][$field], $condition['Value']);
353 $check = $this->checkStack($condition['Operator'], $condition['Conditions'], $input);
355 $valid = ('and' == $base)
358 if ('and' == $base && !$valid)
362 if ('or' == $base && $valid)
371 * Check that Required Fields are provided and that Unique Constraints adhered to.
372 * @param \Workspace\Workflow $workflow
374 * @param array $input
377 protected function checkRequiredInputs(\Workspace\Workflow $workflow, array $case, array $inputs)
380 foreach ($case as $group => $requirements)
382 $input = isset($inputs[$group])
385 foreach ($requirements as $requiredInput)
387 if (!isset($input[$requiredInput])
388 || (empty($input[$requiredInput]) && !$this->inputs[$group][$requiredInput]['Options']['AllowEmpty'])
389 || (0 === $input[$requiredInput] && !$this->inputs[$group][$requiredInput]['Options']['AllowZero'])
390 || (is_null($input[$requiredInput]) && !$this->inputs[$group][$requiredInput]['Options']['AllowNull']))
392 isset($messages[$group])
393 || $messages[$group] = array();
394 $messages[$group][] = 'Required input `' . $requiredInput . '` not provided.';
396 if ($this->inputs[$group][$requiredInput]['Options']['Unique'])
398 $contract = new \Workspace\Utility\ServiceInput('Contract', array(
400 'Field' => $requiredInput,
401 'Value' => $input[$requiredInput]
403 $serviceResponse = $workflow->fieldIsUnique($contract->pack());
404 if ('Error' == $serviceResponse['Status'])
406 $messages[$group][] = $serviceResponse['Message'];