ldc-crm-client/src/Models/Question.php

294 lines
8.5 KiB
PHP
Raw Normal View History

2021-08-11 17:26:30 +02:00
<?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
{
/**
* Is true if this model was not filled from crm
*
* @var boolean
*/
private $isNew = true;
/**
* 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
*
* @var \LDC\LDCCRM\Models\Answer[]
*/
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();
if (count(self::$validation['type']) < 2) {
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
self::$validation['type'][] = function ($attribute, $value, $fail) {
if (!is_object($value) or !\in_array($value, QuestionType::toArray())) {
$type = \gettype($value);
$fail("Question type ($type)$value is not in QuestionType enum list");
}
};
}
$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 any valid is not validated
*/
public function fill(array $properties)
{
if (isset($properties['type'])) {
try {
$properties['type'] = (\is_int($properties['type']) or \ctype_digit($properties['type'])) ?
QuestionType::make((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[]
2021-08-12 14:49:27 +02:00
* @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
2021-08-11 17:26:30 +02:00
*/
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[]
2021-08-12 14:49:27 +02:00
* @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
2021-08-11 17:26:30 +02:00
*/
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[]
2021-08-12 14:49:27 +02:00
* @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
2021-08-11 17:26:30 +02:00
*/
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;
}
}