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;
}
}
}