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/blije-gasten.komma.pro/app/Komma/Shop/Search/SearchService.php
<?php


namespace App\Komma\Shop\Search;


use App\Komma\Base\Service;
use App\Komma\Kms\Core\AbstractTranslationModel;
use App\Komma\Shop\Categories\Models\CategoryTranslation;
use App\Komma\Shop\Products\Product\ProductTranslation;
use App\Komma\Shop\Search\Types\SearchResult;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;

class SearchService extends Service
{

    /**
     * The models that can be searched trough. They are recognized because they use the Searchable trait
     *
     * @var array
     */
    public static $searchableModelClasses = [
//        Product::class,
//        Category::class,
        ProductTranslation::class,
        CategoryTranslation::class
    ];


    /**
     * Get collection of models that match the given term
     *
     * @param  string  $term
     * @return Collection
     */
    public function searchByTerm(string $term): Collection
    {

        //Make a collection that will hold al found models
        $foundModels = collect();

        foreach (self::$searchableModelClasses as $searchableModelClass) {

            //Check if the search method isset
            if (!method_exists($searchableModelClass, 'search')) {
                throw new \BadMethodCallException(self::class.': Search function not found within '. $searchableModelClass . '. Did you implement the SearchableTrait?');
            }

            // Create query for calling the search
            $searchQuery = $searchableModelClass::search($term);

            // Apply the language filter if AbstractTranslationModel
            if(is_subclass_of($searchableModelClass, AbstractTranslationModel::class)) {
                $searchQuery = $searchQuery->where('language_id', app()->getLanguage()->id);
            }

            // Get the models
            // Note we use the paginate to be able to load relation on the search models
            $searchModels = $searchQuery->paginate(25);

            // Eager load the translatable on the model if AbstractTranslationModel
            if(is_subclass_of($searchableModelClass, AbstractTranslationModel::class)) {
                $searchModels->load('translatable', 'translatable.images');

                // On productsTranslation we also want to load the categories
                if(is_a($searchableModelClass, ProductTranslation::class, true)) {
                    $searchModels->load('translatable.categories', 'translatable.categories.translation');
                }
            }

            // Append the search models to the found collection
            $foundModels = $foundModels->merge($searchModels->items());
        }

        return $foundModels;
    }

    /**
     * Convert models into search results
     * We do this so we can easily loop in the blade instead of having complex if else constructions
     *
     * @param  Collection  $models
     * @param $links
     * @return Collection
     */
    public function convertModelsIntoSearchResults(Collection $models, $links): Collection
    {
        $searchResults = collect();

        foreach ($models as $model) {

            $searchResult = null;

            // Create the SearchResult for the given model
            switch (get_class($model)) {
                case ProductTranslation::class:
                    $searchResult = $this->simpleTranslationModelConversion($model, $links, 'products');
                    break;

                case CategoryTranslation::class:
                    $searchResult = $this->simpleTranslationModelConversion($model, $links, 'categories');
                    break;

                default:
                    throw new \InvalidArgumentException(self::class . ': Model (' . get_class($model) . ') has been defined for converting into a SearchResult');
            }

            // If search result ins't defined continue
            if(!isset($searchResult)) continue;

            //TODO: If it's possible to have double models (so Categories and CategoryTranslation are listed for searching) then create a check that prevent duplicated models
            $searchResults->push($searchResult);
        }

        return $searchResults;
    }

    /**
     * Simple conversion for an AbstractTranslationModel.
     *
     * Meaning that the model has a name and slug,
     * has a translatable model that is active
     * and is mapped by a page.
     *
     * @param  AbstractTranslationModel  $model
     * @param $links
     * @param  string  $linksName
     * @return SearchResult|null
     */
    private function simpleTranslationModelConversion(AbstractTranslationModel $model, $links, string $linksName): ? SearchResult
    {
        // Related page for mapping should be defined in links
        if(!isset($links->{$linksName})) return null;

        // Model should have a name and a slug
        if(empty($model->name) && empty($model->slug)) return null;

        // Model should have a translatable and it translatable should be active
        if(!isset($model->translatable) && !$model->translatable->active) return null;

        // Possibly add an image to the search result
        $image = null;
        if(isset($model->translatable->images) && $model->translatable->images->isNotEmpty()) {
            $image = $model->translatable->images->first();
        }

        // Get only the translation model
        $translationModel = clone $model;
        $translationModel->unsetRelation('translatable');

        // Recreate the model from the translatable to translation
        $rootModel = $model->translatable;
        $rootModel->setRelation('translation', $translationModel);

        // Model is valid for creating the search result
        return new SearchResult($rootModel, $translationModel->name, $links->{$linksName}->route . '/' . $translationModel->slug, $image);
    }

}