File: D:/HostingSpaces/SBogers10/zuiderbos.komma.pro/app/Komma/Search/SearchService.php
<?php
namespace Komma\Search;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Komma\Blocks\Models\Block;
use Komma\Kms\Documents\Models\Document;
use Komma\Kms\Schools\School;
use Komma\Newsletters\Models\Newsletter;
use Komma\Pages\Models\Page;
use Komma\Pages\Models\PageTranslation;
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, $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() + $searchResults->documents->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 = [];
$documentResults = [];
// 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;
case 'Komma\\Kms\\Documents\\Models\\Document':
$documentResults[] = $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);
//Get Documents
$foundDocuments = $this->getDocuments($documentResults);
return (object) [
'documents' => $foundDocuments,
'faq' => (object) $foundFaqItems,
'pages' => $resultCollection,
];
}
/*
* Check if the found faq items belongs to this school
*
*/
private function getDocuments($documentResults)
{
$documentsKeys = [];
foreach ($documentResults as $documentResult) {
$documentsKeys[] = $documentResult->id;
}
$documents = Document::whereIn('id', $documentsKeys)->with('file')->get();
return $documents;
}
/*
* 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');
$newsletters = Newsletter::where('active', 1)
->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;
}
}
}
}