HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
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;
    }
}