Skip to content

Instantly share code, notes, and snippets.

@markphi2013
Created October 24, 2013 09:52
Show Gist options
  • Save markphi2013/7134294 to your computer and use it in GitHub Desktop.
Save markphi2013/7134294 to your computer and use it in GitHub Desktop.
<?php
App::uses('Action', 'Model');
App::uses('FieldValueIncorrect', 'Lib');
App::uses('MissingField', 'Lib');
App::uses('VirtualModel', 'Model');
App::uses('VusionConst', 'Lib');
class Interaction extends VirtualModel
{
var $name = 'interaction';
var $version = '3';
var $payload = array();
var $fields = array(
'interaction-id',
'type-schedule',
'type-interaction',
'activated',
'prioritized');
public function __construct()
{
parent::__construct();
$this->Action = new Action();
}
public $validate = array(
'interaction-id' => array(
'required' => array(
'rule' => 'required',
'message' => 'Interaction Id field is missing.'
),
'notempty' => array(
'rule' => 'notempty',
'message' => 'Interaction Id field cannot be empty.'
)
),
# Type Schedule
'type-schedule' => array(
'required' => array(
'rule' => 'required',
'message' => 'Type Schedule field is missing.'
),
'notempty' => array(
'rule' => 'notempty',
'message' => 'Type Schedule field cannot be empty.'
),
'validValue' => array(
'rule' => array(
'inlist', array(
'fixed-time', 'offset-days', 'offset-time', 'offset-condition')),
'message' => 'Type Schedule has not a valid value.'
),
'valueRequireFields' => array(
'rule' => array(
'valueRequireFields', array(
'fixed-time' => array('date-time'),
'offset-days' => array('days', 'at-time'),
'offset-time' => array('minutes'),
'offset-condition' => array('offset-condition-interaction-id'))),
'message' => 'Type schedule required field are not present.'
)
),
## Type Schedule subtype
'date-time' => array(
'requiredConditional' => array (
'rule' => array('requiredConditionalFieldValue', 'type-schedule', 'fixed-time'),
'message' => 'Fixed time required a date-time.',
),
'validFormat' => array(
'rule' => array('regex', VusionConst::DATE_TIME_REGEX),
'message' => VusionConst::DATE_TIME_FAIL_MESSAGE
)
),
'days' => array(
'requiredConditional' => array (
'rule' => array('requiredConditionalFieldValue', 'type-schedule', 'offset-days'),
'message' => 'Offset-day required a day.',
)
),
'at-time' => array(
'requiredConditional' => array (
'rule' => array('requiredConditionalFieldValue', 'type-schedule', 'offset-days'),
'message' => 'Offset-day required a at-time field.',
)
),
'minutes' => array(
'requiredConditional' => array (
'rule' => array('requiredConditionalFieldValue', 'type-schedule', 'offset-time'),
'message' => 'Minutes required a offset-time.',
)
),
'offset-condition-interaction-id' => array(
'requiredConditional' => array (
'rule' => array('requiredConditionalFieldValue', 'type-schedule', 'offset-condition'),
'message' => 'Schedule Condition required a offset-condition-interaction-id.',
)
),
# Type Interaction
'type-interaction' => array(
'required' => array(
'rule' => 'required',
'message' => 'Type Interaction field is missing.'
),
'notempty' => array(
'rule' => 'notempty',
'message' => 'Type Interaction value cannot be empty.'
),
'validValue' => array(
'rule' => array('inList', array('announcement', 'question-answer', 'question-answer-keyword')),
'message' => 'Type Interaction value is not valid.'
),
'valueRequireFields' => array(
'rule' => array(
'valueRequireFields', array(
'announcement' => array('content'),
'question-answer' => array('content', 'keyword', 'set-use-template', 'type-question', 'type-unmatching-feedback', 'set-max-unmatching-answers', 'set-reminder'),
'question-answer-keyword' => array('content', 'label-for-participant-profiling', 'answer-keywords', 'set-reminder'),
'message' => 'Type interaction required fields are missing.'
)
)
)
),
## Type Interaction Subtype
'content' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldOrValue', 'type-interaction', 'announcement', 'question-answer', 'question-answer-keyword'),
'message' => 'The interaction required a content.',
),
'notempty' => array(
'rule' => 'notempty',
'message' => 'Content field cannot be empty.'
),
'validApostrophe' => array(
'rule' => array('notRegex', VusionConst::APOSTROPHE_REGEX),
'message' => VusionConst::APOSTROPHE_FAIL_MESSAGE
),
'validCustomizeContent' => array(
'rule' => array('validCustomizeContent', VusionConst::CUSTOMIZE_CONTENT_DOMAIN_REGEX),
'message' => 'noMessage'
),
),
'keyword'=> array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-interaction', 'question-answer'),
'message' => 'Question Answer required a keyword.',
),
'validValue' => array(
'rule' => array('regex', VusionConst::KEYWORD_REGEX),
'message' => VusionConst::KEYWORD_FAIL_MESSAGE
)
),
'set-use-template'=> array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-interaction', 'question-answer'),
'message' => 'A set-use-template field is required.',
),
),
'set-max-unmatching-answers' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-interaction', 'question-answer'),
'message' => 'A set-max-unmatching-answer field is required.',
),
),
'set-reminder'=> array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldOrValue', 'type-interaction', 'question-answer', 'question-answer-keyword'),
'message' => 'A set-reminder field is required.',
),
),
'type-unmatching-feedback' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-interaction', 'question-answer'),
'message' => 'A type-unmatching-feedback field is required.',
),
'validValue' => array(
'rule' => array('inList', array('no-unmatching-feedback', 'program-unmatching-feedback', 'interaction-unmatching-feedback')),
'message' => 'Type unmatching feedback is not valid.',
)
),
'type-question'=> array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-interaction', 'question-answer'),
'message' => 'Question Answer required a type-question.',
),
'validValue' => array(
'rule' => array('inList', array('closed-question', 'open-question')),
'message' => 'Please select a valid type of Question.',
)
),
'answer-keywords' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-interaction', 'question-answer-keyword'),
'message' => 'A answer-keywords is required.',
),
'validValues' => array(
'rule' => 'validateAnswerKeywords',
'message' => 'One of the Answer Keyword is not valide.'
)
),
### Type Interaction Subtype - Type Question Subtype
'label-for-participant-profiling'=> array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldOrKeyValue', array(
'type-interaction'=>'question-answer-keyword',
'type-question' => 'closed-question')),
'message' => 'A label-for-participant-profiling is required.',
),
),
'set-answer-accept-no-space'=> array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-question', 'closed-question'),
'message' => 'A set-answer-accept-no-space field is required.',
),
),
'answers'=> array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-question', 'closed-question'),
'message' => 'A answers field is required.',
),
'validValues' => array(
'rule' => 'validateAnswers',
'message' => 'One of the Answers is not valide.'
)
),
'answer-label' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-question', 'open-question'),
'message' => 'A answer-label field is required.',
),
),
'feedbacks' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-question', 'open-question'),
'message' => 'A feedbacks field is required.',
),
),
### Unmatching Answers Subtype
'max-unmatching-answer-number' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'set-max-unmatching-answers', 'max-unmatching-answers'),
'message' => 'A max-unmatching-answer-number field is required.',
),
),
'max-unmatching-answer-actions' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'set-max-unmatching-answers', 'max-unmatching-answers'),
'message' => 'A max-unmatching-answer-actions field is required.',
),
),
### Reminder Subtype
'type-schedule-reminder' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'set-reminder', 'reminder'),
'message' => 'A type-schedule-reminder field is required.',
),
'validValue' => array(
'rule' => array('inList', array('reminder-offset-days', 'reminder-offset-time')),
'message' => 'The value of type-schedule-reminder is not valid.',
)
),
'reminder-number' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'set-reminder', 'reminder'),
'message' => 'A reminder-number field is required.',
),
),
'reminder-actions' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'set-reminder', 'reminder'),
'message' => 'A reminder-actions field is required.',
),
'validValue' => array(
'rule' => 'validateActions',
'message' => null
),
),
### Reminder Schedule Subtype
'reminder-days' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-schedule-reminder', 'reminder-offset-days'),
'message' => 'A reminder-days field is required.',
),
),
'reminder-at-time' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-schedule-reminder', 'reminder-offset-days'),
'message' => 'A reminder-at-time field is required.',
),
),
'reminder-minutes' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-schedule-reminder', 'reminder-offset-time'),
'message' => 'A reminder-minutes field is required.',
),
),
#type-unmatching-feedback
'unmatching-feedback-content' => array(
'requiredConditional' => array(
'rule' => array('requiredConditionalFieldValue', 'type-unmatching-feedback', 'interaction-unmatching-feedback'),
'message' => 'Custom unmatching feedback must have content.',
),
'validApostrophe' => array(
'rule' => array('notRegex', VusionConst::APOSTROPHE_REGEX),
'message' => VusionConst::APOSTROPHE_FAIL_MESSAGE
),
'validCustomizeContent' => array(
'rule' => 'validCustomizeContent',
'message' => 'noMessage'
),
),
# Other Interaction Fields
'activated' => array(
'required' => array(
'rule' => 'required',
'message' => 'Activated field is missing.'
),
'validValue' => array(
'rule' => array('inList', array(0, 1)),
'message' => 'Actived field value is not valid.'
)
),
'prioritized' => array(
'required' => array(
'rule' => 'required',
'message' => 'Prioritized field is missing.'
),
'validValue' => array(
'rule' => array('inList', array(null, 'prioritized')),
'message' => 'Prioritized field value is not valid.'
)
)
);
public $validateReminderAction = array(
'type-action' => array(
'validateActions' => array(
'rule' => 'validateActions',
'message' => null
),
)
);
public $validateAnswer = array(
'choice' => array(
'notempty' => array(
'rule' => 'notempty',
'message' => 'Actived field cannot be empty.'
)
),
'feedbacks' => array(
'validFeedback' => array(
'rule' => 'validateFeedbacks',
'message' => null
)
),
'answer-actions' => array(
'validateActions' => array(
'rule' => 'validateActions',
'message' => null
),
)
);
public $validateAnswerKeyword = array(
'keyword' => array(
'notempty' => array(
'rule' => 'notempty',
'message' => 'keyword field cannot be empty.'
),
'validValue' => array(
'rule' => array('regex', VusionConst::KEYWORD_REGEX),
'message' => VusionConst::KEYWORD_FAIL_MESSAGE
)
),
'feedbacks' => array(
'validFeedback' => array(
'rule' => 'validateFeedbacks',
'message' => null
)
),
'answer-actions' => array(
'validateActions' => array(
'rule' => 'validateActions',
'message' => null
),
)
);
public $validateFeedback = array(
'content' => array(
'notempty' => array(
'rule' => 'notempty',
'message' => 'Content field cannot be empty.'
),
'validApostrophe' => array(
'rule' => array('notRegex', VusionConst::APOSTROPHE_REGEX),
'message' => VusionConst::APOSTROPHE_FAIL_MESSAGE
),
'validCustomizeContent' => array(
'rule' => array('validCustomizeContent', VusionConst::CUSTOMIZE_CONTENT_DOMAIN_ALL_REGEX),
'message' => 'noMessage'
),
)
);
public function validCustomizeContent($field, $allowedDomain, $data)
{
print_r($allowedDomain);
if (isset($data[$field])) {
preg_match_all(VusionConst::CUSTOMIZE_CONTENT_MATCHER_REGEX, $data[$field], $matches, PREG_SET_ORDER);
$allowed = array("domain", "key1", "key2", "keys3", "otherkey");
foreach($matches as $match) {
$match = array_intersect_key($match, array_flip($allowed));
foreach ($match as $key=>$value) {
if (!preg_match(VusionConst::CONTENT_VARIABLE_KEY_REGEX, $value)) {
return __("To be used as customized content, '%s' can only be composed of letter(s), digit(s) and/or space(s).", $value);
}
}
if (!preg_match($allowedDomain, $match['domain'])) {
return __("To be used as customized content, '%s' can only be either: %s.", $match['domain'], implode(',', $allowedDomain));
}
if ($match['domain'] == 'participant') {
if (isset($match['key2'])) {
return VusionConst::CUSTOMIZE_CONTENT_DOMAIN_PARTICIPANT_FAIL;
}
} else if ($match['domain'] == 'contentVariable') {
if (isset($match['otherkey'])) {
return VusionConst::CUSTOMIZE_CONTENT_DOMAIN_CONTENTVARIABLE_FAIL;
}
}
}
}
return true;
}
public function validateAnswers($field, $data)
{
return $this->validList($field, $data, $this->validateAnswer);
}
public function validateAnswerKeywords($field, $data)
{
return $this->validList($field, $data, $this->validateAnswerKeyword);
}
public function validateFeedbacks($field, $data)
{
return $this->validList($field, $data, $this->validateFeedback);
}
public function validateActions($field, $data)
{
if (isset($data[$field])) {
$count = 0;
$validationErrors = array();
foreach($data[$field] as $action) {
$this->Action->set($action);
if (!$this->Action->validates()) {
$validationErrors[$count] = $this->Action->validationErrors;
}
$count++;
}
if ($validationErrors != array()) {
return $validationErrors;
}
}
return true;
}
public function beforeValidate()
{
parent::beforeValidate();
$this->_setDefault('interaction-id', uniqid());
$this->_setDefault('activated', 0);
$this->data['activated'] = intval($this->data['activated']);
$this->_setDefault('prioritized', null);
$this->_setDefault('type-interaction', null);
$this->_setDefault('type-schedule', null);
//Exit the function in case of announcement
if (!in_array($this->data['type-interaction'], array('question-answer', 'question-answer-keyword')))
return true;
if ($this->data['type-interaction'] == 'question-answer') {
$this->_setDefault('type-question', null);
$this->_setDefault('set-use-template', null);
$this->_setDefault('type-unmatching-feedback', 'no-unmatching-feedback');
$this->_setDefault('set-reminder', null);
$this->_setDefault('set-max-unmatching-answers', null);
if ($this->data['set-max-unmatching-answers'] == 'max-unmatching-answers') {
$this->_setDefault('max-unmatching-answer-actions', array());
}
if ($this->data['type-question'] == 'closed-question') {
$this->_setDefault('set-answer-accept-no-space', null);
$this->_setDefault('label-for-participant-profiling', null);
$this->_setDefault('answers', array());
$this->_beforeValidateAnswers();
} elseif ($this->data['type-question'] == 'open-question') {
$this->_setDefault('answer-label', null);
$this->_setDefault('feedbacks', array());
}
}
if ($this->data['type-interaction'] == 'question-answer-keyword') {
$this->_setDefault('set-reminder', null);
$this->_setDefault('answer-keywords', array());
$this->_beforeValidateAnswerKeywords();
}
if ($this->data['set-reminder'] == 'reminder') {
$this->_setDefault('reminder-actions', array());
$this->_beforeValidateActions(&$this->data['reminder-actions']);
}
return true;
}
protected function _beforeValidateActions($actions)
{
foreach($actions as &$action) {
$this->Action->set($action);
$this->Action->beforeValidate();
$action = $this->Action->getCurrent();
}
}
protected function _beforeValidateAnswerKeywords()
{
foreach ($this->data['answer-keywords'] as &$answer) {
if (!isset($answer['feedbacks']))
$answer['feedbacks'] = array();
if (!isset($answer['answer-actions']))
$answer['answer-actions'] = array();
$this->_beforeValidateActions(&$answer['answer-actions']);
}
}
protected function _beforeValidateAnswers()
{
foreach ($this->data['answers'] as &$answer) {
if (!isset($answer['feedbacks']))
$answer['feedbacks'] = array();
if (!isset($answer['answer-actions']))
$answer['answer-actions'] = array();
$this->_beforeValidateActions(&$answer['answer-actions']);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment