ldc-crm-client/src/Models/Question.php
2021-12-06 00:16:13 +01:00

296 lines
8.4 KiB
PHP

<?php
namespace LDC\LDCCRM\Models;
use LDC\LDCCRM\Enums\QuestionType;
use LDC\LDCCRM\Utils;
use TypeError;
/**
* This class represents a question
* It has some static methods to retrieve questions and answers
*
* @property string $id The question id
* @property string $question The actual question as a string
* @property \LDC\LDCCRM\Enums\QuestionType $type
* The question type to display,
* it also hints wether it can accept one or multiple responses,
* so only checkbox allows multiple responses
* @property \LDC\LDCCRM\Models\Answer[] $answers An array with answers
*
* @category Api Models
* @package LDCCrmClient
* @subpackage models
*/
class Question extends CrmClientModel
{
/**
* The question id
*
* Required
* Field Type bigInt
*
* @var int
*/
private $id;
/**
* The actual question as a string
*
* Required
* Max length 255
* Field Type varchar
*
* @var string
*/
private $question = null;
/**
* The question type
*
* Validate: in QuestionType::toValues()
*
* Required
* Field Type tinyInteger
*
* @var \LDC\LDCCRM\Enums\QuestionType
*/
private $type = null;
/**
* The question answers
*
* \LDC\LDCCRM\Models\Answer
*
* @var array
*/
private $answers = [];
/**
* The crm customer fields
*
* @var array
*/
protected $modelFields = [
'id', 'question', 'type', 'answers'
];
/**
* Validation rules
*
* @var array
*/
protected static $validation = [
'id' => 'required|int',
'question' => 'required|string|max:255',
'type' => ['required'],
'answers' => 'required|array'
];
public function __construct(array $properties = [])
{
parent::__construct();
$this->fill($properties);
return $this;
}
public function __get(string $field)
{
$props = \array_diff(
$this->modelFields,
$this->invisibleFields
);
if (in_array($field, $props)) {
if ($field === 'type' and !\is_object($this->{$field})) {
return QuestionType::make($this->{$field});
}
}
return parent::__get($field);
}
/**
* Set prop
*
* @param string $field
* @param mixed $value
* @throws TypeError if the field has an incorrect value
* @return mixed|null The input value or null is this prop does not exists
*/
public function __set(string $field, $value)
{
$out = parent::__set($field, $value);
if (in_array($field, $this->modelFields)) {
$this->updatedValues[$field] = (\is_object($value) and
get_class($value) === QuestionType::class) ? $value->value : $value;
$this->setRawProperty($this, $field, $this->updatedValues[$field]);
}
return $out;
}
/**
* Fill data into this model
* using validation rules
*
* @param array $properties
* @return void
* @throws TypeError if a field has an incorrect value
*/
public function fill(array $properties)
{
if (isset($properties['type'])) {
try {
$properties['type'] = (\is_object($properties['type']) and
get_class($properties['type']) === QuestionType::class) ?
$properties['type']->value : (ctype_digit($properties['type']) ?
(int)$properties['type'] : $properties['type']);
} catch (TypeError $e) {
// cast anyway
$properties['type'] = (int)$properties['type'];
}
}
parent::fill($properties);
}
/**
* Validate all model properties
*
* @return array the validated values
*/
protected function validateAllValues(array $ignore = []): array
{
$out = [];
if (!\in_array('type', $ignore)) {
try {
$this->validateValue('type', QuestionType::make(self::getRawProperty($this, 'type')));
} catch (TypeError $e) {
// this to throw validation error if failure way
$this->validateValue('type', self::getRawProperty($this, 'type'));
}
$out['type'] = self::getRawProperty($this, 'type');
}
return array_merge($out, parent::validateAllValues(array_merge(['type'], $ignore)));
}
// PUBLIC METHODS
/**
* Get all questions only
*
* @return array
*
* with \LDC\LDCCRM\Models\Question[]
* @throws \LDC\LDCCRM\Exceptions\CrmException
* if an error occurs on server side or on getting response
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException
* If any error or \LDC\LDCCRM\Enums\ApiError occurs
*/
public static function all(): array
{
static::setUpApiInterface(); // set apiInterface
$request = Utils::getResquest('apiV2.questions.index');
$response = static::$apiInterface->call($request);
$out = [];
foreach ($response->data as $question) {
$answers = \array_map(function ($answer) {
return new Answer($answer);
}, $question['answers']);
$question['answers'] = $answers;
$out[] = new self($question);
}
return $out;
}
/**
* Get all the questions with customer answers
*
* @param \LDC\LDCCRM\Models\Customer $customer
* @return array
*
* [
* 0 => [
* 'question' => \LDC\LDCCRM\Models\Question,
* 'customerAnswers' => \LDC\LDCCRM\Models\Answer[]
* ]
* ]
*
* with \LDC\LDCCRM\Models\Question[]
* and the customer \LDC\LDCCRM\Models\Answer[]
* @throws \LDC\LDCCRM\Exceptions\CrmException
* if an error occurs on server side or on getting response
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException
* If any error or \LDC\LDCCRM\Enums\ApiError occurs
*/
public static function allWithCustomerAnswers(Customer $customer): array
{
static::setUpApiInterface(); // set apiInterface
$request = Utils::getResquest('apiV2.questions.indexWithResponse', [
'customer' => $customer->hashcode
]);
$response = static::$apiInterface->call($request);
$out = [];
foreach ($response->data as $question) {
$answers = \array_map(function ($answer) {
return new Answer($answer);
}, $question['answers']);
$customerAnswers = \array_map(function ($answer) {
return new Answer($answer);
}, $question['customerAnswers']);
unset($question['customerAnswers']);
$question['answers'] = $answers;
$out[] = [
'question' => new self($question),
'customerAnswers' => $customerAnswers,
];
}
return $out;
}
/**
* Get unanswered question for a specific customer
*
* @param \LDC\LDCCRM\Models\Customer $customer
* @return \LDC\LDCCRM\Models\Question[]
* @throws \LDC\LDCCRM\Exceptions\CrmException
* if an error occurs on server side or on getting response
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException
* If any error or \LDC\LDCCRM\Enums\ApiError occurs
*/
public static function unansweredBy(Customer $customer): array
{
self::assertValidHascode($customer->hashcode);
static::setUpApiInterface(); // set apiInterface
$request = Utils::getResquest(
'apiV2.questions.unAnsweredBy',
['customer' => $customer->hashcode]
);
$response = static::$apiInterface->call($request);
$out = [];
foreach ($response->data as $question) {
$answers = \array_map(function ($answer) {
return new Answer($answer);
}, $question['answers']);
$question['answers'] = $answers;
$out[] = new self($question);
}
return $out;
}
/**
* Serialize this object to an array
*
* @return array
*/
public function jsonSerialize()
{
return [
'id' => $this->id,
'question' => $this->question,
'type' => $this->type,
'answers' => $this->answers
];
}
}