Обучение. Рефакторинг

This commit is contained in:
2023-01-18 12:43:45 +01:00
parent 037d43857d
commit bae941e155
5 changed files with 265 additions and 161 deletions
@@ -3,24 +3,127 @@
namespace DarksLight2\Training;
use Core\Db;
use DarksLight2\Training\Steps\ChatFirstStep;
use DarksLight2\Training\Steps\MyUserFirstQuest;
use DarksLight2\Training\Steps\MyUserFirstStep;
use DarksLight2\Training\Steps\MyUserFourthQuest;
use DarksLight2\Training\Steps\MyUserFourthStep;
use DarksLight2\Training\Steps\MyUserSecondQuest;
use DarksLight2\Training\Steps\MyUserSecondStep;
use DarksLight2\Training\Steps\MyUserThirdQuest;
use DarksLight2\Training\Steps\MyUserThirdStep;
use DarksLight2\Traits\Singleton;
use PassGen;
use PDO;
use stdClass;
use User;
class TrainingManager
{
use Singleton;
private $database_records = false;
private array $steps_data;
private int $user_id;
private array $steps;
public string $current_step = '';
private array $registered_steps;
private array $completed_steps;
private array $active_steps;
public function __construct(int $user_id)
private $database;
public function __construct(int $user_id, $refresh_token = true)
{
try {
$this->register([
new ChatFirstStep(),
new MyUserFirstStep(),
new MyUserFirstQuest(),
new MyUserSecondStep(),
new MyUserSecondQuest(),
new MyUserThirdStep(),
new MyUserThirdQuest(),
new MyUserFourthStep(),
new MyUserFourthQuest(),
]);
} catch (TrainingException $e) {
}
$this->user_id = $user_id;
$this->generateToken();
if($refresh_token) {
$this->generateToken();
}
$this->database = Db::getRow('SELECT * FROM user_training WHERE user_id = ?', [$user_id]);
$this->createDatabaseRecord();
$this->database['data'] = json_decode($this->database['data'], true);
$this->selectActiveSteps();
}
public function getCurrentStepName(): string
{
if(empty($this->current_step)) {
$this->current_step = array_key_first($this->active_steps) ?? '';
}
return $this->current_step;
}
public function getRegistered(): array
{
return $this->registered_steps;
}
public function getDatabaseData()
{
return $this->database;
}
public function addPoint($short_name, $closure = null)
{
if($short_name === $this->getCurrentStepName()) {
$this->database['data'][$short_name]['progress']['current']++;
if(isset($closure)) {
$closure($this);
}
}
}
public function nextStep()
{
if($this->database['data'][$this->getCurrentStepName()]['progress']['need'] <= $this->database['data'][$this->getCurrentStepName()]['progress']['current']) {
$this->database['data'][$this->getCurrentStepName()]['progress']['current'] = 0;
$this->database['data'][$this->getCurrentStepName()]['completed'] = true;
unset($this->active_steps[$this->getCurrentStepName()]);
$this->current_step = array_key_first($this->active_steps) ?? '';
$this->database['current'] = $this->getCurrentStepName();
}
}
public function previousStep()
{
$this->current_step = end($this->completed_steps) ?? '';
$this->database['current'] = $this->current_step;
$this->database['data'][$this->getCurrentStepName()]['completed'] = false;
}
public function selectActiveSteps()
{
foreach ($this->database['data'] as $step_name => $data) {
if($data['completed'] === false) {
$this->active_steps[$step_name] = $data;
continue;
}
$this->completed_steps[] = $step_name;
}
}
public function store()
{
Db::sql('UPDATE user_training SET data = ?, current = ? WHERE user_id = ?', [json_encode($this->database['data']), $this->database['current'], $this->user_id]);
}
/**
@@ -37,77 +140,14 @@ class TrainingManager
foreach ($steps as $step) {
if($step instanceof StepFactory) {
$this->steps[$step->getShortName()] = new class (
$step->getMessage(),
$step->getTitle(),
$step->getRewards(),
$this->stepData($step->getShortName())->complete,
$step->getShortName(),
$this->stepData($step->getShortName())->progress
) {
public string $message;
public string $title;
public string $short_name;
public array $rewards;
public bool $isComplete;
public stdClass $progress;
public function __construct(
string $message,
string $title,
array $rewards,
bool $isComplete,
string $short_name,
stdClass $progress
) {
$this->rewards = $rewards;
$this->title = $title;
$this->isComplete = $isComplete;
$this->message = $message;
$this->short_name = $short_name;
$this->progress = $progress;
}
public function render()
{
if(!$this->isComplete) {
$path = $_SERVER['DOCUMENT_ROOT'] . '/modules_data/steps/' . $this->short_name . '.php';
if (file_exists($path)) {
require $path;
return;
}
throw TrainingException::noRenderingFile();
}
}
};
$this->registered_steps[$step->getShortName()] = $step;
}
}
}
private function stepData(string $short_name): object
{
$data = $this->getDatabaseRecords()->data;
if(!isset($data->$short_name)) {
$this->updateDatabaseRecord($short_name);
$data = $this->getDatabaseRecords()->data;
}
return $data->$short_name;
}
private function generateToken($length = 16)
{
$letters = 'abcdefgmikiHGJKLjkGASysj7603456';
$token = '';
for ($i = 0; $i <= $length; $i++) {
$token .= $letters[rand(0, strlen($letters))];
}
$token = PassGen::new($length);
Db::run('UPDATE user_training SET api_token = ? WHERE user_id = ?', [
$token,
@@ -115,87 +155,42 @@ class TrainingManager
]);
}
public function getDatabaseRecords(): stdClass
{
if(!$this->database_records) {
$data = Db::run('SELECT * FROM user_training WHERE user_id = ?', [$this->user_id])
->fetch(PDO::FETCH_OBJ);
$this->database_records = new stdClass();
$this->database_records->user_id = $data->user_id;
$this->database_records->api_token = $data->api_token;
$this->database_records->data = json_decode($data->data);
}
return $this->database_records;
}
public function updateDatabaseRecord(string $short_name)
{
if($this->getDatabaseRecords()) {
$this->database_records->data->$short_name = $this->firstRecordData()->$short_name;
Db::run('UPDATE user_training SET data = ? WHERE user_id = ?', [
json_encode($this->database_records->data),
$this->user_id
]);
}
}
public function createDatabaseRecord()
{
if(!$this->getDatabaseRecords()) {
Db::run('INSERT INTO user_training (user_id, data) VALUES (?, ?)', [
$this->user_id,
json_encode($this->firstRecordData())
]);
}
}
if(!$this->database) {
private function firstRecordData(): stdClass
{
$data = new stdClass();
$short_names = [
'first_step',
'second_step'
];
$data = [];
foreach ($short_names as $name) {
$data->$name->complete = false;
$data->$name->progress->current = 0;
$data->$name->progress->need = 1;
}
return $data;
}
public function __get(string $name)
{
return $this->steps[$name];
}
public function addPoint(string $short_name)
{
$this->database_records->data->$short_name->progress->current++;
}
public function nextStep()
{
foreach ($this->database_records->data as $step) {
if($step->complete === false && $step->progress->current >= $step->progress->need) {
$step->complete = true;
foreach ($this->registered_steps as $step) {
$data[$step->getShortName()] = $step->databaseRecord();
}
Db::sql('INSERT INTO user_training (user_id, data, current) VALUES (?, ?, ?)', [
$this->user_id,
json_encode($data, true),
array_key_first($data)
]);
$this->database = Db::getRow('SELECT * FROM user_training WHERE user_id = ?', [$this->user_id]);
}
}
public function store()
/**
* @throws \DarksLight2\Training\TrainingException
*/
public function render()
{
$this->nextStep();
if(in_array(User::start()->room['file'], $this->registered_steps[$this->getCurrentStepName()]->onLocations()) || in_array('all', $this->registered_steps[$this->getCurrentStepName()]->onLocations())) {
$path = $_SERVER['DOCUMENT_ROOT'] . '/modules_data/steps/step.php';
Db::run('UPDATE user_training SET data = ? WHERE user_id = ?', [
json_encode($this->database_records->data),
$this->user_id
]);
if (file_exists($path)) {
$short_name = $this->getCurrentStepName();
$answer = $this->registered_steps[$this->getCurrentStepName()]->getAnswer();
require $path;
return;
}
throw TrainingException::noRenderingFile();
}
}
}