File: D:/HostingSpaces/SBogers10/ehbo.today/app/KommaApp/Competences/Kms/CompetenceService.php
<?php
/**
* Created by PhpStorm.
* Competence: julesgraus
* Date: 31/01/2018
* Time: 13:13
*/
namespace App\KommaApp\Competences\Kms;
use App\KommaApp\Courses\Models\Course;
use App\KommaApp\Kms\Core\AbstractTranslatableModel;
use App\KommaApp\Kms\Core\Attributes\Attribute;
use App\KommaApp\Kms\Core\Attributes\Models\SelectOption;
use App\KommaApp\Kms\Core\Attributes\Models\SelectOptionInterface;
use App\KommaApp\Kms\Core\Sections\AbstractSectionTabItem;
use App\KommaApp\Kms\Core\Sections\SectionService;
use App\KommaApp\Competences\Models\Competence;
use App\KommaApp\Kms\Core\Sections\SectionTabItem;
use App\KommaApp\Users\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection as DatabaseCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
class CompetenceService extends SectionService
{
protected $sortable = false;
function __construct()
{
$this->forModelName = Competence::class;
parent::__construct();
}
public function getOptionsForSelect($languageId = null, int $excludeId = null): \Illuminate\Support\Collection
{
$models = collect();
$competences = $this->models();
$competences->each(function ($competence) use (&$models) {
$models->push((new SelectOption())->setValue($competence->id)->setContent($competence->id)->setHtmlContent($competence->title));
});
return $models;
}
/**
* Links the user to a competence, indicating the user is competent in it.
* Also updates the acquired date to to moment you call this method and
* sets the date the competence expires for the user
* @param User $user
* @param int|Competence $competence The id of a competence or a specific competence
*/
public function userAcquiredCompetence(User $user, $competence)
{
$competence = $this->validateAndGetCompetence($competence);
//Get the competence from the user if the competence already was acquired
$userCompetence = $user->competences()->where('competence_id', '=', $competence->id)->first();
//Save the competence for the user.
if($userCompetence) {
//User had acquired it beforehand. Update it.
$userCompetence->fill([
'previous_acquired_at' => $userCompetence->acquired_at,
'previous_expires_at' => $userCompetence->expires_at,
'acquired_at' => Carbon::now()->toDateTimeString(),
'expires_at' => $this->calculateNextExpirationDateForCompetence($competence),
]);
$userCompetence->save();
} else {
$user->competences()->save($competence, [
//User had never acquired it. Create it.
'acquired_at' => Carbon::now()->toDateTimeString(),
'expires_at' => $this->calculateNextExpirationDateForCompetence($competence),
]);
}
}
/**
* Reverts an acquired competence to the previous acquired and expired at dates.
* Or removes the competence if the user never acquired it before.
*
* @param User $user
* @param $competence
*/
public function revertAcquiredCompetence(User $user, $competence)
{
$competence = $this->validateAndGetCompetence($competence);
//Get the competence from the user if the competence already was acquired
/** @var Competence $userCompetence */
$userCompetence = $user->competences()->where('competence_id', '=', $competence->id)->withPivot(['acquired_at', 'expires_at', 'previous_acquired_at', 'previous_expires_at'])->first();
//Check if the user acquired the competence. If not just return
if(!$userCompetence) return;
//If the competence has a previous acquired_at date and an expires_at date revert the competence to those dates...
if($userCompetence->pivot->previous_acquired_at && $userCompetence->pivot->previous_expires_at) {
$userCompetence->pivot->acquired_at = $userCompetence->pivot->previous_acquired_at;
$userCompetence->pivot->expires_at = $userCompetence->pivot->previous_expires_at;
$userCompetence->pivot->previous_acquired_at = null;
$userCompetence->pivot->previous_expires_at = null;
$userCompetence->save();
}
//...If not remove the competence from the user
else
{
$user->competences()->detach($userCompetence->id);
}
}
/**
* Checks if the value of competence is a Competence instance or int.
* If it is the instance, it wil return that instance. If it is an int,
* it will get the competence by id and return that OR throw an exception
* telling that the competence was not found
*
* @param $competence
* @return Competence
*/
private function validateAndGetCompetence($competence):Competence
{
//Parameter type validation
if(!is_a($competence, Competence::class) && !is_int($competence)) throw new \RuntimeException('The competence must be a "'.Competence::class.'" instance or an id of a "'.Competence::class.'"');
if(is_int($competence)) {
$competence = $competence->find($competence);
if(!$competence) throw new \InvalidArgumentException('Competence was not found');
}
/** @var Competence $competence */
return $competence;
}
/**
* Looks up the given competence in the users competences and if it finds the competence in the user's competences,
* it wil give you the next expiration date for that competence.
*
* @param Competence $competence
* @return Carbon
*/
public function calculateNextExpirationDateForCompetence(Competence $competence): Carbon
{
/** @var Carbon $currentExpirationDate */
if(!$competence->pivot) throw new \RuntimeException('The competence was not retrieved via a user while it must');
$currentExpirationDate = Carbon::parse($competence->pivot->expires_at);
$newExpirationDate = null;
$now = Carbon::now();
switch ($competence->renew_interval) {
case Competence::RenewEachHalfYear:
if($now->month >= 6)
$newExpirationDate = Carbon::now()->endOfYear(); //Last day of this year at 23:59:59
else
$newExpirationDate = Carbon::now()->month(6)->endOfMonth(); //Last day of the 6th month from this year at 23:59:59
break;
case Competence::RenewEachYear:
$newExpirationDate = Carbon::now()->endOfYear(); //Last day of this year at 23:59:59
break;
case Competence::RenewEachTwoYear:
if($currentExpirationDate->year == Carbon::now()->year) {
//Expires this year
$newExpirationDate = Carbon::now()->endOfYear(); //Last day of this year at 23:59:59
} else {
//Expires next year. So leave it like it is for this year.
$newExpirationDate = $currentExpirationDate;
}
break;
}
return $newExpirationDate;
}
/**
* Get a collection of renew interval select options
*
* @return Collection
*/
public function getCompetenceRenewIntervalOptions(): Collection
{
$models = collect();
$models->push(
(new SelectOption())
->setValue(Competence::RenewEachHalfYear)
->setContent(ucfirst(__('kms/competences.renew_every_types.'.Competence::RenewEachHalfYear)))
->setHtmlContent(ucfirst(__('kms/competences.renew_every_types.'.Competence::RenewEachHalfYear)))
);
$models->push(
(new SelectOption())
->setValue(Competence::RenewEachYear)
->setContent(ucfirst(__('kms/competences.renew_every_types.'.Competence::RenewEachYear)))
->setHtmlContent(ucfirst(__('kms/competences.renew_every_types.'.Competence::RenewEachYear)))
);
$models->push((new SelectOption())
->setValue(Competence::RenewEachTwoYear)
->setContent(ucfirst(__('kms/competences.renew_every_types.'.Competence::RenewEachTwoYear)))
->setHtmlContent(ucfirst(__('kms/competences.renew_every_types.'.Competence::RenewEachTwoYear)))
);
return $models;
}
}