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/zuiderbos.komma.pro/Komma/Search/SearchService.php
<?php


namespace Komma\Search;


use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Komma\Blocks\Models\Block;
use Komma\Kms\Schools\School;
use Komma\Pages\Models\Page;
use Komma\Pages\Models\PageTranslation;
use Komma\Pages\PageService;
use Komma\Posts\Models\Post;
use Komma\References\Models\Reference;
use Komma\Search\Models\SearchPages;
use Komma\Search\Models\SearchResults;

class SearchService
{
    public $school = '';
    public $route = '';
    public $foundResultKeys = [];

    /**
     * Get search results by query and the right school
     *
     * @param $searchQuery
     * @param $school
     * @return bool|object
     */
    public function getResults($searchQuery = null, $school){

        if($searchQuery == null) return false;

        $this->school = $school;
        $this->school->route = \Request::segment(1);

        $count = 0;

        // Get results
        $query = \Search::query($searchQuery, '*', ['phrase' => false, 'fuzzy' => 0.5])->get();

        // Get page translation which contains the search query
        $query = $this->likePages($query, $searchQuery);

        // If no results, do spell check on the query
        if($query->count() == 0){
            $this->doSpellCheck($searchQuery);
            $searchResults = [];
        }

        // Else populate the results by faq items and pages
        else{
            $searchResults = $this->populateResults($query);
            $count = $searchResults->faq->count() + $searchResults->pages->count();
        }

        // Save search to DB
        $queryResult = new SearchResults();
        $queryResult->query = $searchQuery;
        $queryResult->results = $count;
        $queryResult->save();

        // Create results object
        $results = (object)[
            'amount'   => $count,
            'results' => $searchResults,
            'query' => $searchQuery
        ];


        return $results;
    }

    /**
     * Populate the results by faq items and pages
     *
     *
     * @param $queryCollection
     */
    private function populateResults($queryCollection){

        $resultCollection = new Collection();
        $foundFaqItems = [];

        $pageResults = [];
        $blockResults = [];
        $referencesResults = [];
        $calenderResults = [];
        $postResults = [];

        // Sort result by class
        foreach ($queryCollection as $queryResult){

            switch( get_class( $queryResult ) ){
                case 'Komma\\Faq\\Models\\FaqTranslation':
                    $foundFaqItems[$queryResult->faq_id] = $queryResult;
                    break;

                case 'Komma\\Search\\Models\\SearchPages':
                    $pageResults[] = $queryResult->page_id;
                    break;

                case 'Komma\\Pages\\Models\\PageTranslation':
                    $pageResults[] = $queryResult->page_id;
                    break;

                case 'Komma\\Blocks\\Models\\BlockTranslation':
                    $blockResults[] = $queryResult->block_id;
                    break;

                case 'Komma\\Posts\\Models\\PostTranslation':
                    $postResults[] = $queryResult->post_id;
                    break;

                case 'Komma\\References\\Models\\Reference':
                    $referencesResults[] = $queryResult->id;
                    break;

                case 'Komma\\References\\Models\\ReferenceTranslation':
                    $referencesResults[] = $queryResult->reference_id;
                    break;

                case 'Komma\\Calender\\Models\\CalenderTranslation':
                    $calenderResults[] = $queryResult;
                    break;

                default:
                    dd(get_class( $queryResult ));
            }

        }

        // Get page objects
        $this->getPageResults($resultCollection, $pageResults);

        // Get page objects by found blocks
        $this->getPagesResultsByBlocks($resultCollection, $blockResults);

        // Check faq items if they belong to this school
        $foundFaqItems = $this->checkFaqForSchool($foundFaqItems);

        // Get page object by reference
        $this->getPagesByReferences($resultCollection, $referencesResults);

        // Get if calender it's belong to this school
        $this->checkCalenderForSchool($resultCollection, $calenderResults);

        // Get page object by post
        $this->getPagesByPosts($resultCollection, $postResults);

        return (object)[
            'faq' => (object)$foundFaqItems,
            'pages' => $resultCollection
        ];

    }

    /*
     * Check if the found faq items belongs to this school
     *
     */
    private function checkFaqForSchool(&$faqItems){

        $schoolFaqItems = $this->school->faq->groupBy('id');

        // Get faq items that belong to this school
        $schoolFaqKeys = $schoolFaqItems->keys();

        $faqCollection = [];

        foreach ($faqItems as $key => $faqItem){

            // If faq item not in school faq continue
            if( ! in_array($key, $schoolFaqKeys)) continue;

            // else add to collection by their key for the order
            $faqCollection[$schoolFaqItems[$key][0]->lft] = $faqItem;
        }

        // sort array by key
        ksort($faqCollection);

        // Made collection from array
        $faqCollection = new Collection($faqCollection);

        return $faqCollection;
    }

    /**
     * Fill resultCollection with page objects
     * if page belongs to this school
     *
     * @param $resultCollection
     * @param $pageTranslations
     */
    private function getPageResults(&$resultCollection, $pageTranslations){

        // Get pages with translation and their routes
        $pages = Page::whereIn('id', $pageTranslations)
            ->with('translation', 'translation.route')
            ->get();

        // Loop through pages
        foreach ($pages as $page){

            // Only add to results collection when page code name starts with the right school
            if(!starts_with($page->code_name, $this->school->type)) continue;
            $resultCollection->add($page);

            // Also add the code names of the pages to found results
            if( ! in_array( $page->code_name, $this->foundResultKeys ) ) $this->foundResultKeys[] = $page->code_name;

        }
    }

    /**
     * Fill resultCollection with page objects
     * found by the blocks translations of the query
     * and where the blocks belongs to this school
     *
     * @param $resultCollection
     * @param array $blockIds
     */
    private function getPagesResultsByBlocks(&$resultCollection, Array $blockIds){

        // Get blocks
        $blocks = Block::whereIn('id', $blockIds)->get();

        $pageCodeNames = [];

        // Loop through blocks
        foreach ($blocks as $block){

            // Check if it's the right school
            if( ! starts_with($block->code_name, $this->school->type)) continue;
            // Check if it isn't already found
            if( in_array($block->code_name, $this->foundResultKeys) ) continue;

            // Add to page code name array
            $pageCodeNames[] = $block->code_name;

            // And to the found page keys
            $this->foundResultKeys[] = $block->code_name;
        }

        // Get pages with translation and their routes
        $pages = Page::whereIn('code_name', $pageCodeNames)
            ->with('translation', 'translation.route')
            ->get();

        // Merge collections
        $resultCollection = $resultCollection->merge($pages);

    }

    /**
     * Fill resultCollection with page objects
     * if post belongs to this school
     *
     * @param $resultCollection
     * @param $pageTranslations
     */
    private function getPagesByPosts(&$resultCollection, $postResults){

        // Get references that belong to this school
        $schoolNews = $this->school->news->groupBy('id');
        $schoolNewsKeys = $schoolNews->keys();

        $newsKeys = [];

        foreach ($postResults as $postResult){

            // If reference not in school references continue
            if( ! in_array($postResult, $schoolNewsKeys)) continue;

            // Already prevent duplicated keys
            if( in_array($postResult, $newsKeys)) continue;

            // else add to collection by their key for the order
            $newsKeys[] = $postResult;
        }

        // Get references with translation and their routes
        $posts = Post::whereIn('id', $newsKeys)
            ->with(['translations', 'translations.routes'])
            ->get();

        foreach ($posts as $post){

            // We need all translations because reference can belong to multiple schools and so can have multiple routes
            // And to use ->routes eloquent we need to use the ->translations (because of KMS 4.2)
            foreach ($post->translations as $postTranslation){

                // Loop through routes of an translation
                foreach ($postTranslation->routes as $route){

                    // If route of translations starts with the same school route
                    if(starts_with($route->route, $this->school->route)){

                        // Append translation and route to reference
                        $post->translation = $postTranslation;
                        $post->translation->route = $route;
                        $post->translation->name = 'Nieuws | '.$post->translation->name;

                        // Now the reference in right format for results
                        $resultCollection->add($post);

                    }
                }
            }

        }
    }

    /**
     * Fill resultCollection with page objects
     * if reference belongs to this school
     *
     * @param $resultCollection
     * @param $pageTranslations
     */
    private function getPagesByReferences(&$resultCollection, $referencesResults){

        // Get references that belong to this school
        $schoolReferences = $this->school->references->groupBy('id');
        $schoolReferenceKeys = $schoolReferences->keys();

        $referencesKeys = [];

        foreach ($referencesResults as $referencesResult){

            // If reference not in school references continue
            if( ! in_array($referencesResult, $schoolReferenceKeys)) continue;

            // Already prevent duplicated keys
            if( in_array($referencesResult, $referencesKeys)) continue;

            // else add to collection by their key for the order
            $referencesKeys[] = $referencesResult;
        }

        // Get references with translation and their routes
        $references = Reference::whereIn('id', $referencesResults)
            ->with(['translations', 'translations.routes'])
            ->get();

        foreach ($references as $reference){

            // We need all translations because reference can belong to multiple schools and so can have multiple routes
            // And to use ->routes eloquent we need to use the ->translations (because of KMS 4.2)
            foreach ($reference->translations as $referenceTranslation){

                // Loop through routes of an translation
                foreach ($referenceTranslation->routes as $route){

                    // If route of translations starts with the same school route
                    if(starts_with($route->route, $this->school->route)){

                        // Append translation and route to reference
                        $reference->translation = $referenceTranslation;
                        $reference->translation->route = $route;
                        $reference->translation->name = 'Interview met '.$reference->name;

                        // Now the reference in right format for results
                        $resultCollection->add($reference);

                    }
                }
            }

        }
    }


    /**
     * Find if calender items belongs to this school
     * then if they are past today
     * add calender page of this school with name of calender item
     *
     * @param $resultCollection
     * @param $calenderItems
     */
    private function checkCalenderForSchool(&$resultCollection, $calenderItems){

        // Get calender items of this school
        $schoolCalender = $this->school->calenderItems->groupBy('id');
        $schoolCalenderKeys = $schoolCalender->keys();

        $calenderCollection = new Collection();

        foreach ($calenderItems as $key => $calenderItem){

            // If calender item not in calender faq continue
            if( ! in_array($calenderItem->calender_id, $schoolCalenderKeys)) continue;

            // Preload date
            $calenderItemDate = $schoolCalender[$calenderItem->calender_id][0]->getDate();

            // Check if date is today or later
            if($calenderItemDate >= Carbon::today()){

                // Add to collection
                $calenderItem->date = $calenderItemDate;
                $calenderCollection->add($calenderItem);
            }

        }

        // Order collection by date
        $calenderCollection = $calenderCollection->sortBy('date');

        // Preload calender page of this school
        $calenderPage = Page::where('code_name', $this->school->type.'-actual-calender')
            ->with(['translation', 'translation.route'])
            ->first();

        // Loop through calender activities and make result in correct format
        foreach ($calenderCollection as $item){

            $resultItem = $item;
            $resultItem->translation = $item;

            $resultItem->translation->name = $calenderPage->translation->name.' | '.$item->name;
            $resultItem->translation->route = $calenderPage->translation->route;

            $resultCollection->add($resultItem);
        }

    }

    /**
     * Get pageTranslations which contains the given search query
     *
     * @param $queryCollection
     * @param $searchQuery
     * @return mixed
     */
    private function likePages($queryCollection, $searchQuery){

        $pages = PageTranslation::where('name', 'LIKE', '%'.$searchQuery.'%')
            ->get();

        foreach ($pages as $page){
            $queryCollection->add($page);
        }

        return $queryCollection;
    }

    private function doSpellCheck($searchQuery){
        //dd('do spell check on '.$searchQuery);
    }

    public function updateSearchTable(){

        $convertedPages = 0;
        $unIndexedPages = 0;

        $pages = Page::where('lft', '>', 2)
            ->with('translation')
            ->get();

        $blocks = Block::where('active', 1)
        ->with('translation')
        ->get()
        ->keyBy('code_name');

        $schools = School::all();


        foreach ($pages as $page){

            $page->schoolId = $this->getSchoolId($page, $schools);

            // Check if page is active and is bind to a school
            if($page->active && isset( $page->schoolId )){
                $searchPage = SearchPages::firstOrNew(['code_name' => $page->code_name]);
                $searchPage->page_id = $page->id;
                $searchPage->school_id = $page->schoolId;
                $searchPage->name = $page->translation->name;

                if(isset($blocks[$page->code_name])){
                    $pageBlock = $blocks[$page->code_name];
                    $searchPage->streamer = $pageBlock->translation->name;

                    $content = '';
                    $dynamicContent = json_decode($pageBlock->translation->description);
                    foreach ($dynamicContent as $contentBlock){
                        if(isset($contentBlock->description)) $content.= html_entity_decode(htmlspecialchars_decode(strip_tags($contentBlock->description), ENT_HTML5)).' ';
                    }

                    $searchPage->description = $content;

                }
                $convertedPages++;
                $searchPage->save();
            }
            // Else delete this page if found
            else{
                $searchPage = SearchPages::where('code_name', $page->code_name)->first();
                if(isset($searchPage)){
                    $unIndexedPages++;
                    $searchPage->delete();
                }
            }


        }

        return 'Pages indexed: '.$convertedPages.' | Pages unindexed: '.$unIndexedPages.' | Updated search Table on: ' . date("Y-m-d H:i:s");
    }

    // Find school id by page code name
    private function getSchoolId(Page $page, $schools){
        foreach ($schools as $school){
            if(starts_with($page->code_name, $school->type)) return $school->id;
        }
    }
}