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/ste.komma.pro/app/Trainings/TrainingService.php
<?php


namespace App\Trainings;


use App\Base\Service;
use App\Console\Commands\GetTrainingsFromC4;
use App\Locations\Models\Location;
use App\SteLanguages\Models\SteLanguage;
use App\Trainings\Resources\Training;
use App\Types\TrainingFilter;
use App\Types\TrainingFilterOption;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;

final class TrainingService extends Service
{

    /**
     * Get the Trainings from the cache
     * Possible trigger the Artisan command if cache is empty (should be impossible)
     *
     * @param  bool  $isCallback
     * @return mixed
     */
    private function getTrainingsFromCache($isCallback = false)
    {
        if( Cache::has('trainings') ) {
            return Cache::get('trainings');
        }

        // On the second run of this function we crash
        if($isCallback) throw new \BadMethodCallException(self::class.': Something wrong with the C4 import. Because training do not get filled into the cache.');

        /** @var GetTrainingsFromC4 $loadFromC4Command */
        $loadFromC4Command = app(GetTrainingsFromC4::class);
        $loadFromC4Command->handle(false);
        return $this->getTrainingsFromCache(true);
    }

    /**
     * Get the amount of upcoming trainings
     *
     * @param  int  $amount
     * @return mixed
     */
    public function getUpcomingTrainings(int $amount = null)
    {
        $trainings = $this->getTrainingsFromCache()
            ->sortBy('start_date');

        if(isset($amount)) return $trainings->take($amount);
        return $trainings;
    }

    public function getTrainingForFilters(array $filters)
    {
        $trainings = $this->getTrainingsFromCache();

        foreach ($filters as $key => $value)
        {
            switch ($key) {
                case 'levels':
                    $trainings = $trainings->whereIn('filterable_level', $value);
                    continue 2;
                case 'type':
                    $trainings = $trainings->whereIn('training_type', $value);
                    continue 2;
                case 'amountOfWeeks':
                    $trainings = $trainings->whereIn('amount_of_weeks', $value);
                    continue 2;
                case 'eachWeek':
                    $trainings = $trainings->whereIn('lessons_each_week', $value);
                    continue 2;
                case 'locations':
                    $trainings = $trainings->whereIn('location_id', $value);
                    continue 2;
                case 'languages':
                    $trainings = $trainings->where('language_id', $value);
                    continue 2;
            }
        }

        return $trainings;
    }

    /**
     * @param  string  $c4Id
     * @return Training|null
     */
    public function getTrainingByC4Id(string $c4Id): ?Training
    {
        $c4Training = $this->getTrainingsFromCache()
            ->where('c4_id', $c4Id)
            ->first();

        if(!$c4Training) abort(404);

        // Try to find training in kms
        $kmsTraining = \App\Trainings\Models\Training::where('c4_id', $c4Id)
            ->with('translation')
            ->first();

        if($kmsTraining) $c4Training->translation = $kmsTraining->translation;
        return $c4Training;

    }

    /**
     * Make filters out of the Training related attributes
     *
     * @return Collection
     */
    public function getFilters(): Collection
    {
        $filters = collect();

        $trainings = $this->getTrainingsFromCache();

        $counters = [];
        $loadedLanguages = [];

        $steLanguages = collect();
        $locations = collect();
        foreach ($trainings as $training)
        {
            if(!isset($counters[$training->training_type])) $counters[$training->training_type] = 1;
            else $counters[$training->training_type]++;

            if(!isset($loadedLanguages[$training->api_response->taal_code])) $loadedLanguages[$training->api_response->taal_code] = 1;
            else $loadedLanguages[$training->api_response->taal_code]++;

            if($steLanguages->where('id', $training->language->id)->count() == 0) $steLanguages->push($training->language);
            if($locations->where('id', $training->location->id)->count() == 0) $locations->push($training->location);
        }

        debug($counters);
        debug($loadedLanguages);

        // Languages
        $languageFilter = new TrainingFilter('languages', __('site/trainings.filters.language'), TrainingFilter::FILTER_TYPE_SELECT);
        $languageFilterOption = new TrainingFilterOption(__('site/trainings.all_languages'), 0);
        $languageFilter->addOption($languageFilterOption);

        foreach ($steLanguages as $steLanguage) {
            $languageFilterOption = new TrainingFilterOption($steLanguage->translation->name, $steLanguage->id);
            $languageFilter->addOption($languageFilterOption);;
        }
        $filters->push($languageFilter);


        // Locations
        $locationFilter = new TrainingFilter('locations', __('site/trainings.filters.location'));
        $locationFilter->setIcon('pin-icon');

        foreach ($locations as $location) {

            if($location->id === Location::ONLINE_ID) $locationFilterOption = new TrainingFilterOption($location->name, $location->id);
            else $locationFilterOption = new TrainingFilterOption($location->name . ', ' . $location->city , $location->id);

            $locationFilter->addOption($locationFilterOption);;
        }
        $filters->push($locationFilter);


        // Levels
        $levelFilter = new TrainingFilter('levels', __('site/trainings.filters.level'), TrainingFilter::FILTER_TYPE_LEVEL);
        foreach (Training::$filterLevels as $level) $levelFilter->addOption(new TrainingFilterOption($level, $level));
        $levelFilter->addExtraData('groupNames', [
            'a' => __('site/trainings.levelNames.a'),
            'b' => __('site/trainings.levelNames.b'),
            'c' => __('site/trainings.levelNames.c'),
        ]);
        $filters->push($levelFilter);


        // Type
        $typeFilter = new TrainingFilter('type', __('site/trainings.filters.type'));
        $uniqueTrainingTypes = $trainings->unique('training_type')->sortBy('training_type')->pluck('training_type')->toArray();

        foreach (config('c4.preferred_type_order') as $c4Type) {

            if(!in_array($c4Type, $uniqueTrainingTypes)) continue;

            if(app('translator')->has('site/trainings.c4.' . $c4Type, null, false)) $label = app('translator')->get('site/trainings.c4.' . $c4Type, [], null, false);
            else $label = $c4Type;

            $typeFilter->addOption(new TrainingFilterOption($label, $c4Type));
        }

        $uniqueTrainingTypes = array_diff($uniqueTrainingTypes, config('c4.preferred_type_order'));

        foreach ($uniqueTrainingTypes as $type) {
            if(empty($type)) continue; // Skip the 'None'

            if(app('translator')->has('site/trainings.c4.' . $type, null, false)) $label = app('translator')->get('site/trainings.c4.' . $type, [], null, false);
            else $label = $type;

            $typeFilter->addOption(new TrainingFilterOption($label, $type));
        }

        $filters->push($typeFilter);


        // Day
//        $dayFilter = new TrainingFilter('days',  __('site/trainings.filters.day'));
//        for ($d = 1; $d <= 7; $d++) $dayFilter->addOption(new TrainingFilterOption( strtoupper(__('calendar.day_names_min.' . $d)), $d));
//        $filters->push($dayFilter);


        // Amount of weeks
//        $amountOfWeeksFilter = new TrainingFilter('amountOfWeeks',  __('site/trainings.filters.amount_of_weeks'));
//        $uniqueAmountOfWeeks = $trainings->unique('amount_of_weeks')->sortBy('amount_of_weeks')->pluck('amount_of_weeks');
//        foreach ($uniqueAmountOfWeeks as $amountOfWeeksOption) $amountOfWeeksFilter->addOption(new TrainingFilterOption($amountOfWeeksOption . ' ' . __('calendar.weeks'), $amountOfWeeksOption));
//        $filters->push($amountOfWeeksFilter);


//        // Trainings each week
//        $trainingsEachWeekFilter = new TrainingFilter('eachWeek', __('site/trainings.filters.each_week'));
//        $uniqueTrainingsEachWeek = $trainings->unique('lessons_each_week')->sortBy('lessons_each_week')->pluck('lessons_each_week');
//        foreach ($uniqueTrainingsEachWeek as $trainingsEachWeek) {
//            (app()->getLocale() == 'nl') ? $label = $trainingsEachWeek : $label = __('site/trainings.c4.' . $trainingsEachWeek);
//            $trainingsEachWeekFilter->addOption(new TrainingFilterOption($label, $trainingsEachWeek));
//        }
//        $filters->push($trainingsEachWeekFilter);

        return $filters;
    }

    /**
     * Get training or make if not present in the database
     *
     * @param  SteLanguage  $language
     * @param  string  $level
     * @return Training
     */
    public function firstOrNew(SteLanguage $language, string $level): Training
    {
        $training = Training::where('ste_language_id', $language->id)
            ->where('level', $level)
            ->with('translations', 'steLanguage')
            ->first();

        if( isset($training) && $training->translations->count() < sizeof(config('languages.available')) ) {
            \Log::warning('C4 import: Not all translations are filled in for the Training "' . strtoupper($language->iso_2) . ' | '. $level . '". We should notify the project owner to contact STE about filling all the translations for this KMS Training.');
        }

        if(!isset($training)) {
            \Log::warning('C4 import: Training not found for language "' . $language->iso_2 . '" and level "'. $level . '". We have created a training, but we should notify the project owner to contact STE about filling the KMS Training for this fresh created training.');

            $training = Training::create([
                'ste_language_id' => $language->id,
                'level' => $level
            ]);
        }

        return $training;
    }

}