Commit 536d0d9c authored by Artem Pianykh's avatar Artem Pianykh

added search module

parent 0685366d
<?php
return [
'name' => 'Search',
'limit' => 20
];
\ No newline at end of file
<?php
return [
'order' => 'relevance',
'offset' => 0,
'type' => FALSE,
'alpha' => FALSE,
'criterias' => [
'sectors' => [],
'expertises' => []
],
'locations' => [
'location' => FALSE,
'country' => FALSE,
'state' => FALSE,
'city' => FALSE,
'zip' => FALSE,
'miles' => FALSE
],
'clients' => [
'clients_keywords' => FALSE,
'clients_sectors' => []
],
'morph' => [
'keywords' => FALSE,
'size' => FALSE,
'is_mainoffice' => FALSE,
'is_branch' => FALSE,
'is_deverse' => FALSE,
'is_women' => FALSE,
'exclude' => FALSE
]
];
\ No newline at end of file
<?php
return [
//gen
'page' => FALSE, // String
'offset' => 0, // String
'type' => FALSE, // String
'order' => FALSE, // String
'alpha' => FALSE, // String
//criterias
'sectors' => [], // Model
'expertises' => [], // Model
//locations
'location' => FALSE, // String
'country' => FALSE, // Model
'state' => FALSE, // Model
'city' => FALSE, // Model
'zip' => FALSE, // String
'miles' => FALSE, // Model
//clients
'clients_keywords' => FALSE, // String
'clients_sectors' => [], // Model
//morph
'keywords' => FALSE, // String
'size' => FALSE, // Model
'is_mainoffice' => FALSE, // String
'is_branch' => FALSE, // String
'is_deverse' => FALSE, // String
'is_women' => FALSE, // String
'exclude' => FALSE // String
];
\ No newline at end of file
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSearchMorphTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('search_morph', function(Blueprint $table)
{
$table->engine = 'MyISAM';
$table->increments('id');
$table->integer('entityId')->index();
$table->enum('type', ['company', 'individual']);
$table->tinyInteger('sizeId')->index();
$table->tinyInteger('mainOffice')->index();
$table->tinyInteger('branch')->index();
$table->tinyInteger('deverse')->index();
$table->tinyInteger('women')->index();
$table->text('keywords');
});
DB::statement('ALTER TABLE search_morph ADD FULLTEXT search(keywords)');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('search_morph', function($table) {
$table->dropIndex('search');
});
Schema::drop('search_morph');
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSearchClientsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('search_clients', function(Blueprint $table)
{
$table->engine = 'MyISAM';
$table->increments('id');
$table->integer('morphId')->index();
$table->integer('entityId')->index();
$table->enum('type', ['company', 'individual']);
$table->integer('clientId')->index();
$table->integer('sectorId')->index();
$table->text('keywords');
});
DB::statement('ALTER TABLE search_clients ADD FULLTEXT search(keywords)');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('search_clients', function($table) {
$table->dropIndex('search');
});
Schema::drop('search_clients');
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSearchLocationsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('search_locations', function(Blueprint $table)
{
$table->increments('id');
$table->integer('morphId')->index();
$table->integer('entityId')->index();
$table->enum('type', ['company', 'individual']);
$table->unique(['entityId', 'type']);
$table->integer('countryId')->index();
$table->integer('stateId')->index();
$table->integer('cityId')->index();
$table->index(['type', 'countryId']);
$table->index(['type', 'countryId', 'stateId']);
$table->index(['type', 'countryId', 'stateId', 'cityId']);
$table->index(['type', 'countryId', 'cityId']);
$table->index(['countryId', 'stateId']);
$table->index(['countryId', 'cityId']);
$table->index(['countryId', 'stateId', 'cityId']);
$table->float('geoLat')->index();
$table->float('geoLong')->index();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('search_locations');
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSearchSectorsExpertisesTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('search_sectors_expertises', function(Blueprint $table)
{
$table->increments('id');
$table->integer('morphId')->index();
$table->integer('entityId')->index();
$table->integer('sectorsId')->index();
$table->integer('expertisesId')->index();
$table->enum('type', ['company', 'individual']);
$table->index(['entityId', 'type']);
$table->index(['type', 'sectorsId']);
$table->index(['type', 'expertisesId']);
$table->index(['type', 'sectorsId', 'expertisesId']);
$table->index(['sectorsId', 'expertisesId']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('search_sectors_expertises');
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddTitleFieldToSearchMorphTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('search_morph', function(Blueprint $table)
{
$table->string('title')->after('women');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('search_morph', function(Blueprint $table)
{
$table->dropColumn('title');
});
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddIndexToSearchMorphTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('search_morph', function(Blueprint $table)
{
DB::statement('ALTER TABLE search_morph ADD FULLTEXT title(title)');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('search_morph', function(Blueprint $table)
{
});
}
}
<?php
namespace Modules\Search\Entities;
use Illuminate\Database\Eloquent\Model;
/**
* Class Categories
* @package Modules\Search\Entities
*/
class Categories extends Model
{
public $timestamps = FALSE;
protected $table = 'search_sectors_expertises';
protected $fillable = [
'morphId',
'entityId',
'sectorsId',
'categoriesId',
'type'
];
}
\ No newline at end of file
<?php
namespace Modules\Search\Entities;
use Illuminate\Database\Eloquent\Model;
/**
* Class Locations
* @package Modules\Search\Entities
*/
class Locations extends Model
{
public $timestamps = FALSE;
protected $table = 'search_locations';
protected $fillable = [
'morphId',
'entityId',
'type',
'countryId',
'stateId',
'cityId',
'geoLat',
'goeLong'
];
}
\ No newline at end of file
<?php
namespace Modules\Search\Entities;
use Illuminate\Database\Eloquent\Model;
/**
* Class Morph
* @package Modules\Search\Entities
*/
class Morph extends Model
{
public $timestamps = FALSE;
protected $table = 'search_morph';
protected $fillable = [
'entityId',
'type',
'sizeId',
'mainOffice',
'branch',
'deverse',
'woman',
'keywords'
];
/**
* @return array
*/
public static function getAlpha()
{
$alpha = [];
$items = \DB::table('search_morph')->orderBy('title', 'asc')->lists('title');
foreach($items as $item) {
$alpha[] = strtoupper(substr(trim($item), 0, 1));
}
$alpha = array_unique($alpha);
return $alpha;
}
}
\ No newline at end of file
<?php namespace Modules\Search\Entities;
use Illuminate\Database\Eloquent\Model;
/**
* Class SearchClients
* @package Modules\Search\Entities
*/
class SearchClients extends Model
{
public $timestamps = FALSE;
protected $table = 'search_clients';
protected $fillable = [
'morphId',
'entityId',
'type',
'clientId',
'sectorId',
'keywords'
];
}
\ No newline at end of file
<?php namespace Modules\Search\Entities;
use Illuminate\Database\Eloquent\Model;
use \Modules\Companies\Entities\Sector;
use \Modules\Companies\Entities\Expertise;
use \Modules\Companies\Entities\Size;
/**
* Class SearchFilter
* @package Modules\Search\Entities
*/
class SearchFilter extends Model {
private $limit = 0;
private $request = [];
private $doRedirect = FALSE;
private $params = [];
private $filter = [];
private $sections = [
'Aliases',
'General',
'Criterias',
'Locations',
'Clients',
'Morph'
];
/**
* SearchFilter constructor.
* @param $limit
*/
function __construct($limit)
{
$this->limit = $limit;
$this->request = \Request::all();
$this->params = \Config::get('search.params');
$this->filter = \Config::get('search.filter');
$this->processData();
}
/**
* @return array
*/
public function getRequest()
{
return $this->request;
}
/**
* @return array
*/
public function getParams()
{
return $this->params;
}
/**
* @return array
*/
public function getParamsDesc()
{
$params = [];
foreach($this->params as $key => $value) {
if($value == FALSE) continue;
if(is_array($value) && count($value) == 0) continue;
if(is_array($value)) {
$params[$key] = [];
foreach($value as $v) {
$params[$key][] = (isset($v->name)) ? $v->name : $v;
}
} else {
$params[$key] = (isset($value->name)) ? $value->name : $value;
}
}
return $params;
}
/**
* @return array
*/
public function getQuery()
{
$params = [];
foreach($this->params as $key => $value) {
if($value == FALSE) continue;
if(is_array($value) && count($value) == 0) continue;
if(is_array($value)) {
$params[$key] = [];
foreach($value as $v) {
$params[$key][] = (isset($v->slug)) ? $v->slug : $v;
}
} else {
$params[$key] = (isset($value->slug)) ? $value->slug : $value;
}
}
return $params;
}
/**
* @return array
*/
public function getFilter()
{
$this->processFilter($this->filter);
return $this->filter;
}
/**
* @param $filter
*/
private function processFilter(&$filter)
{
foreach($filter as $key => &$item) {
if(is_array($item) && count($item)) {
$this->processFilter($item);
}
if(!isset($this->params[$key])) continue;
if($this->params[$key] == FALSE || (is_array($this->params[$key]) && count($this->params[$key]) == 0)) continue;
$value = $this->params[$key];
if(is_array($value)) {
$item = [];
foreach($value as $v) {
$item[] = (isset($v->id)) ? $v->id : $v;
}
} else {
$item = (isset($value->id)) ? $value->id : $value;
}
}
}
/**
* @return array
*/
private function processData()
{
foreach($this->sections as $section) {
$func = 'process'.$section;
if(method_exists($this, $func)) {
$this->$func();
}
}
return $this->params;
}
/**
* @return void
*/
private function processAliases()
{
$alias = \Request::segment(1);
$slug = \Request::segment(2);
switch ($alias) {
case 'sector':
$this->setCollection($this->params['sectors'], $slug, new Sector());
break;
case 'areas-of-expertise':
$this->setCollection($this->params['expertises'], $slug, new Expertise());
break;
case 'size':
$this->setCollection($this->params['size'], $slug, new Size());
break;
case 'search':
break;
default:
// 404
break;
}
}
/**
* @return void
*/
private function processGeneral()
{
if(isset($this->request['offset'])) {
$this->setInt($this->params['offset'], $this->request['offset']);
}
if(isset($this->request['page'])) {
$page = $this->setInt($this->params['page'], $this->request['page']);
$this->setInt($this->params['offset'], (($page-1) * $this->limit) );
}
if(isset($this->request['order'])) {
switch ($this->request['order']) {
case 'relevance':
$this->params['order'] = 'relevance';
break;
case 'alpha':
$this->params['order'] = 'alpha';
break;
case 'date':
$this->params['order'] = 'date';
break;
}
}
if(isset($this->request['type'])) {
switch ($this->request['type']) {
case 'company':
$this->params['type'] = 'company';
break;
case 'individual':
$this->params['type'] = 'individual';
break;
}
}
if(isset($this->request['alpha'])) {
$this->setString($this->params['alpha'], $this->request['alpha']);
}
}
/**
* @return void
*/
private function processCriterias()
{
if(isset($this->request['sectors'])) {
$this->setCollection($this->params['sectors'], $this->request['sectors'], new Sector());
}
if(isset($this->request['expertises'])) {
$this->setCollection($this->params['expertises'], $this->request['expertises'], new Expertise());
}
}
/**
* @return void
*/
private function processLocations()
{
if(isset($this->request['zip'])) {
$this->setString($this->params['zip'], $this->request['zip']);
}
if(isset($this->request['miles']) && $this->params['zip']) {
$this->setInt($this->params['miles'], $this->request['miles']);
}
if(isset($this->request['country'])) {
$this->setInt($this->params['country'], $this->request['country']);
}
if(isset($this->request['state'])) {
$this->setInt($this->params['state'], $this->request['state']);
}
if(isset($this->request['city'])) {
$this->setInt($this->params['city'], $this->request['city']);
}
if(isset($this->request['location'])) {
switch ($this->request['location']) {
case 'area':
if($this->params['zip'] && $this->params['miles']) {
$this->params['location'] = 'area';
}
break;
case 'exact':
if($this->params['country'] || $this->params['state'] || $this->params['city']) {
$this->params['location'] = 'exact';
}
break;
}
}
}
/**
* @return void
*/
private function processClients()
{
if(isset($this->request['clients_keywords'])) {
$this->setString($this->params['clients_keywords'], $this->request['clients_keywords']);
}
if(isset($this->request['clients_sectors'])) {
$this->setCollection($this->params['clients_sectors'], $this->request['clients_sectors'], new Sector());
}
}
/**
* @return void
*/
private function processMorph()
{
if(isset($this->request['keywords'])) {
$this->setString($this->params['keywords'], $this->request['keywords']);
}
if(isset($this->request['size'])) {
$this->setCollection($this->params['size'], $this->request['size'], new Size());
}
if(isset($this->request['is_mainoffice'])) {
$this->setInt($this->params['is_mainoffice'], $this->request['is_mainoffice']);
}
if(isset($this->request['is_branch'])) {
$this->setInt($this->params['is_branch'], $this->request['is_branch']);
}
if(isset($this->request['is_deverse'])) {
$this->setInt($this->params['is_deverse'], $this->request['is_deverse']);
}
if(isset($this->request['is_women'])) {
$this->setInt($this->params['is_women'], $this->request['is_women']);
}
if(isset($this->request['exclude'])) {
$this->setString($this->params['exclude'], $this->request['exclude']);
}
}
/**
* @param $target
* @param $request
* @return bool|int
*/
private function setInt(&$target, $request)
{
$value = intval($this->getStr($request));
if($value) {
$target = $value;
return $value;
}
return FALSE;
}
/**
* @param $target
* @param $request
* @return bool|string
*/
private function setString(&$target, $request) {
$value = $this->getStr($request);
if($value) {
$target = $value;
return $value;
}
return FALSE;
}
/**
* @param $target
* @param $request
* @param $model
* @return array|bool
*/
private function setCollection(&$target, $request, $model)
{
$slugs = $this->getArray($request);
if(count($slugs) == 0) return FALSE;
$collection = $model::whereIn('slug', $slugs)->get();
if(is_array($target)) {
foreach($collection as $item) {
$target[] = $item;
}
} else {
$target = (isset($collection[0])) ? $collection[0] : FALSE;
}
return $target;
}
/**
* @param $value
* @return array
*/
private function getArray($value)
{
$array = [];
if(!is_array($value)) {
$value = explode(',', $value);
}
foreach($value as $item) {
if($item == '') continue;
if(is_numeric($item)) {
$array[] = intval($item);
} else {
$array[] = $this->getStr($item);
}
}
return $array;
}
/**
* @param $value
* @return string
*/
private function getStr($value) {
$chars_to_replace = [
'\'',
'"',
'/',
'\\'
];
foreach($chars_to_replace as $char) {
if($value == '') continue;
if(strpos($char, $value) === FALSE) continue;
$value = \DB::connection()->getPdo()->quote($value);
}
return trim($value);
}
}
\ No newline at end of file
<?php namespace Modules\Search\Http\Controllers;
/**
* Class SearchController
* @package Modules\Search\Http\Controllers
*/
class SearchController extends Controller {
/**
* @param $entity
* @param $type
*/
public static function addEntity($entity, $type)
{
Self::processEntityMorph($entity, $type);
Self::processEntityCategories($entity, $type);
Self::processEntityLocation($entity, $type);
Self::processEntityClients($entity, $type);
}
/**
* @param $entity
* @param $type
*/
public static function removeEntity($entity, $type)
{
SearchClients::where('entityId', $entity->id)->where('type', $type)->delete();
Locations::where('entityId', $entity->id)->where('type', $type)->delete();
Categories::where('entityId', $entity->id)->where('type', $type)->delete();
Morph::where('entityId', $entity->id)->where('type', $type)->delete();
}
/**
* @param $entity
* @param $type
*/
public static function processEntityMorph($entity, $type)
{
$searchMorph = Morph::firstOrNew([
'entityId' => $entity->id,
'type' => $type
]);
$keywords = '';
if($type == 'company') {
$people = [];
$entityPeople = CompanyPerson::where('companyId', $entity->id)->get();
foreach($entityPeople as $person) {
$people[] = trim($person->firstName . ' ' . $person->lastName);
}
$entityInfo = CompanyInfo::where('companyId', $entity->id);
if($entityInfo->count() > 0) {
$entityInfo = $entityInfo->first();
$keywords = implode(' ', [
$entity->name,
$entityInfo->keywords,
$entityInfo->additionalNotes,
str_replace(["\n","\r"], '', strip_tags($entity->about)),
implode(' ', $people)
]);
}
$searchMorph->sizeId = $entity->sizeId;
$searchMorph->mainOffice = $entity->international;
$searchMorph->branch = $entity->branch;
$searchMorph->deverse = $entityInfo->deverse;
$searchMorph->women = $entityInfo->women;
$searchMorph->title = trim($entity->name);
}
if($type == 'individual') {
$entityInfo = PersonInfo::where('personId', $entity->id);
if($entityInfo->count() > 0) {
$entityInfo = $entityInfo->first();
$keywords = implode(' ', [
$entity->firstName,
$entity->middleName,
$entity->lastName,
$entity->title,
$entityInfo->keywords,
$entityInfo->additionalNotes,
]);
}
$searchMorph->title = trim($entity->firstName . ' ' . $entity->lastName);
}
$searchMorph->keywords = trim($keywords);
$searchMorph->save();
}
/**
* @param $entity
* @param $type
* @return bool
*/
public static function processEntityCategories($entity, $type)
{
$searchMorph = Morph::where('entityId', $entity->id)->where('type', $type)->first();
if($searchMorph === null ) {
return FALSE;
}
if($type == 'company') {
$sectors = Company::find($entity->id)->sectors()->get();
$expertises = Company::find($entity->id)->expertises()->get();
}
if($type == 'individual') {
$sectors = Person::find($entity->id)->sectors()->get();
$expertises = Person::find($entity->id)->expertises()->get();
}
$items = [];
foreach ($sectors as $sector) {
foreach ($expertises as $expertise) {
array_push($items, [
'morphId' => $searchMorph->id,
'entityId' => $entity->id,
'sectorsId' => $sector->id,
'expertisesId' => $expertise->id,
'type' => $type,
]);
}
}
Categories::where('morphId', '=', $searchMorph->id)->delete();
Categories::insert($items);
}
/**
* @param $entity
* @param $type
* @return bool
*/
public static function processEntityLocation($entity, $type)
{
$searchMorph = Morph::where('entityId', $entity->id)->where('type', $type)->first();
if($searchMorph === null ) {
return FALSE;
}
$searchLocation = Locations::firstOrNew([
'morphId' => $searchMorph->id
]);
$searchLocation->entityId = $entity->id;
$searchLocation->type = $type;
$searchLocation->countryId = $entity->countryId;
$searchLocation->stateId = $entity->stateId;
$searchLocation->cityId = $entity->city;
$location = Location::where('id', (int)$entity->city)->first();
if(isset($location->id)) {
$searchLocation['geoLat'] = $location->latitude;
$searchLocation['geoLong'] = $location->longitude;
}
$searchLocation->save();
}
/**
* @param $entity
* @param $type
* @return bool
*/
public static function processEntityClients($entity, $type)
{
$searchMorph = Morph::where('entityId', $entity->id)->where('type', $type)->first();
if($searchMorph === null ) {
return FALSE;
}
if($type == 'company') {
$clients = CompanyClient::where('companyId', '=', $entity->id);
}
if($type == 'individual') {
$clients = PersonClient::where('personId', '=', $entity->id);
}
$clients = $clients->with('sectors')->get();
foreach ($clients as $client) {
Self::addEntityClient($type, $entity->id, $client);
}
}
/**
* @param $type
* @param $entityId
* @param $client
* @return bool
*/
public static function addEntityClient($type, $entityId, $client)
{
$searchMorph = Morph::where('type', $type)->where('entityId', $entityId)->first();
if($searchMorph === null ) {
return FALSE;
}
$keywords = implode(' ', [
$client->name,
str_replace(["\n","\r"], '', strip_tags($client->caseStudy))
]);
foreach($client->sectors as $sector) {
$item = SearchClients::firstOrNew([
'morphId' => $searchMorph->id,
'clientId' => $client->id,
'sectorId' => $sector->id
]);
$item->entityId = $entityId;
$item->type = $type;
$item->keywords = $keywords;
$item->save();
}
}
/**
* @param $type
* @param $entityId
* @param $id
*/
public static function removeEntityClient($type, $entityId, $id)
{
SearchClients::where('entityId', $entityId)->where('type', $type)->where('clientId', $id)->delete();
}
}
\ No newline at end of file
<?php namespace Modules\Search\Http\Controllers;
/**
* Class SearchPublicController
* @package Modules\Search\Http\Controllers
*/
class SearchPublicController extends Controller {
private $doDefaultSearch = TRUE;
private $subSearchExecuted = FALSE;
private $resultIds = [];
private $exludeIds = [];
private $limit = 0;
private $requestData = [];
private $semanticRedirect = TRUE;
private $filterData = [];
private $request = [];
/**
* SearchPublicController constructor.
*/
function __construct()
{
// DEPENDS ON AUTH
$this->limit = (\Auth::user()->get()) ? config('search.limit') : 5;
$this->filter = new SearchFilter($this->limit);
}
/**
* @return View
*/
public function index()
{
if(\Request::get('saveSearch')) {
return $this->saveSearch();
}
$this->filterData = $this->filter->getFilter();
if(\Request::isMethod('post') && !\Request::ajax()) {
$route = $this->responseRedirect();
return redirect($route);
}
if($this->filterData['offset'] == 0) {
Tracking::triggerSearchExecuted();
}
$results = $this->getResults();
if(\Request::ajax()) {
return $this->responseAjax($results);
}
return $this->responseView($results);
}
/**
* @return mixed
*/
public function getLocations()
{
$input = \Request::all();
if(isset($input['parentId'])) {
$cities = Location::getCities($input['parentId']);
return \Response::json($cities);
}
return \Response::json([]);
}
/**
* @return mixed
*/
private function saveSearch()
{
$user = \Auth::user()->get();
$route = \Request::fullUrl();
$route = str_replace(\Request::root(), '', $route);
if(strpos($route, '/') !== 0) {
$route = '/'.$route;
}
$params = $this->filter->getParamsDesc();
$params['total'] = \Request::input('results');
UsersSearches::insert([
'user_id' => $user->id,
'location' => $route,
'params' => json_encode($params)
]);
return Notify::success('Search saved', []);
}
/**
* @return array
*/
private function getResults()
{
$this->filterCriterias();
switch ($this->filterData['locations']['location']) {
case 'area':
$this->filterLocationsArea();
break;
case 'exact':
$this->filterLocationsExact();
break;
}
$this->filterClients();
$this->filterAlpha();
$count = 0;
$items = [];
if($this->filterData['morph']['keywords']) {
$modes = ['like', 'like_milti', 'boolean', 'natural'];
} else {
$modes = ['none'];
}
foreach($modes as $mode) {
$count += $this->filterMorph($mode, 'count');
$modeResults = $this->filterMorph($mode, 'getResults');
foreach($modeResults as $entry) {
$this->exludeIds[] = $entry->id;
}
$items = array_merge($items, $modeResults);
}
if($this->doDefaultSearch) {
$count = $this->defaultCount();
$items = $this->defaultSearch();
}
return [
'total' => $count,
'items' => $this->getOrigin($items)
];
}
/**
* @return void
*/
private function filterCriterias()
{
$doQuery = false;
$filter = $this->filterData['criterias'];
$model = \DB::table('search_sectors_expertises');
if(count($filter['sectors'])) {
$doQuery = true;
$model = $model->whereIn('sectorsId', $filter['sectors']);
}
if(count($filter['expertises'])) {
$doQuery = true;
$model = $model->whereIn('expertisesId', $filter['expertises']);
}
$this->doSubSearch($doQuery, $model);
}
/**
* @return void
*/
private function filterLocationsArea()
{
$filter = $this->filterData['locations'];
$model = \DB::table('search_locations');
if($filter['zip'] == FALSE || $filter['miles'] == FALSE) return;
$curl = new \Ivory\HttpAdapter\CurlHttpAdapter();
$geocoder = new \Geocoder\Provider\GoogleMaps($curl);
$formatter = new \Geocoder\Formatter\StringFormatter();
try {
$covering = $geocoder->geocode($filter['zip']);
$point = $covering->first()->getCoordinates();
$x = $point->getLatitude();
$y = $point->getLongitude();
$xDist = $x * (110.54 / 1.609);
$yDist = $y * (111.32 / 1.609) * cos(deg2rad($x));
$rightUpPointX = $xDist + $filter['miles'];
$rightUpPointY = $yDist + $filter['miles'];
$leftDownPointX = $xDist - $filter['miles'];
$leftDownPointY = $yDist - $filter['miles'];
$rightUpPoint = [
'lat' => $rightUpPointX / (110.54 / 1.609),
'lon' => $rightUpPointY / ((111.32 / 1.609) * cos(deg2rad($x)))
];
$leftDownPoint = [
'lat' => $leftDownPointX / (110.54 / 1.609),
'lon' => $leftDownPointY / ((111.32 / 1.609) * cos(deg2rad($x)))
];
$model = $model->whereBetween('geoLat', [
$leftDownPoint['lat'],
$rightUpPoint['lat']
])->whereBetween('geoLong', [
$leftDownPoint['lon'],
$rightUpPoint['lon']
]);
$entries = $this->doSubSearch(TRUE, $model, 'getAllResults');
$ids = [];
foreach($entries as $entry) {
$pointX = $entry->geoLat - $x;
$pointY = $entry->geoLong - $y;
$pointXdist = $pointX * (110.54 / 1.609);
$pointYdist = $pointY * (111.32 / 1.609) * cos(deg2rad($pointX));
$radius = sqrt(pow($pointXdist,2) + pow($pointYdist, 2));
if($radius < $filter['miles']) {
array_push($ids, $entry->morphId);
}
}
$this->resultIds = array_unique($ids);
} catch(\Exception $e) {}
}
/**
* @return void
*/
private function filterLocationsExact()
{
$doQuery = FALSE;
$filter = $this->filterData['locations'];
$model = \DB::table('search_locations');
if($filter['country']) {
$doQuery = TRUE;
$model = $model->where('countryId', $filter['country']);
}
if($filter['state']) {
$doQuery = TRUE;
$model = $model->where('stateId', $filter['state']);
}
if($filter['city']) {
$doQuery = TRUE;
$model = $model->where('cityId', $filter['city']);
}
$this->doSubSearch($doQuery, $model);
}
/**
* @return void
*/
private function filterClients()
{
$doQuery = false;
$filter = $this->filterData['clients'];
$model = \DB::table('search_clients');
if($filter['clients_keywords']) {
$doQuery = true;
$model = $model->whereRaw('MATCH(keywords) AGAINST(? IN BOOLEAN MODE)', [0 => $filter['clients_keywords']]);
}
if(count($filter['clients_sectors'])) {
$doQuery = true;
$model = $model->whereIn('sectorId', $filter['clients_sectors']);
}
$this->doSubSearch($doQuery, $model);
}
/**
* @return void
*/
private function filterAlpha()
{
$doQuery = false;
$filter = $this->filterData['alpha'];
$model = \DB::table('search_morph');
if($filter) {
$doQuery = true;
$model = $model->where('title', 'like', $filter.'%');
}
$this->doSubSearch($doQuery, $model, 'alpha');
}
/**
* @param bool $searchType
* @param bool $outputType
* @return array
*/
private function filterMorph($searchType = FALSE, $outputType = FALSE)
{
$doQuery = FALSE;
$filter = $this->filterData['morph'];
$model = \DB::table('search_morph');
if($filter['is_mainoffice'] && $filter['is_branch'] == FALSE) {
$doQuery = TRUE;
$model = $model->where('mainOffice', 1);
}
if($filter['is_branch'] && $filter['is_mainoffice'] == FALSE) {
$doQuery = TRUE;
$model = $model->where('branch', 1);
}
if($filter['is_deverse']) {
$doQuery = TRUE;
$model = $model->where('deverse', 1);
}
if($filter['is_women']) {
$doQuery = TRUE;
$model = $model->where('women', 1);
}
if($filter['size']) {
$doQuery = TRUE;
$model = $model->where('sizeId', $filter['size']);
}
if($filter['exclude']) {
$doQuery = TRUE;
$model = $model->whereRaw('(MATCH(keywords) AGAINST(? IN BOOLEAN MODE)) = 0', [0 => '(' . $filter['exclude'] . ')']);
}
if($filter['keywords']) {
$doQuery = TRUE;
switch ($searchType) {
case 'like':
$model = $model->where('title', 'like', $filter['keywords'].'%');
$model->orderBy('title');
break;
case 'like_milti':
$words = explode(' ', $filter['keywords']);
$model = $model->where(function($query) use ($words) {
foreach ($words as $word) {
$query->orWhere('title', 'like', $word.'%');
}
});
$model->orderBy('title');
break;
case 'boolean':
$model = $model->whereRaw('(MATCH(title) AGAINST(? IN BOOLEAN MODE)) > 0', [0 => $filter['keywords']]);
$model->orderBy('title');
break;
case 'natural':
$model = $model->whereRaw('MATCH(keywords) AGAINST(? IN NATURAL LANGUAGE MODE) > 0', [0 => $filter['keywords']]);
if($outputType!='count') {
$model = $model->select(['*', \DB::raw('MATCH(keywords) AGAINST("'.$filter['keywords'].'" IN NATURAL LANGUAGE MODE) as score')]);
$model = $model->orderBy('score', 'DESC');
}
break;
}
} else {
$model = $model->orderBy('title');
}
return $this->doSearch($doQuery, $model, $outputType);
}
/**
* @param $doQuery
* @param $model
* @param bool $returnMode
* @return array
*/
private function doSubSearch($doQuery, $model, $returnMode = FALSE)
{
if($returnMode!='alpha') {
if($this->filterData['type']) {
$model = $model->where('type', $this->filterData['type']);
}
if(count($this->resultIds)) {
$model = $model->whereIn('morphId', $this->resultIds);
}
if(count($this->exludeIds)) {
$model = $model->whereNotIn('morphId', $this->resultIds);
}
} else {
if($this->filterData['type']) {
$model = $model->where('type', $this->filterData['type']);
}
if(count($this->resultIds)) {
$model = $model->whereIn('id', $this->resultIds);
}
if(count($this->exludeIds)) {
$model = $model->whereNotIn('id', $this->resultIds);
}
}
if($doQuery) {
$this->doDefaultSearch = FALSE;
$this->subSearchExecuted = TRUE;
return $this->queryResults($model, $returnMode);
}
}
/**
* @param $doQuery
* @param $model
* @param bool $returnMode
* @return array
*/
private function doSearch($doQuery, $model, $returnMode = FALSE)
{
if($this->filterData['type']) {
$doQuery = TRUE;
$model = $model->where('type', $this->filterData['type']);
}
if(count($this->resultIds)) {
$doQuery = TRUE;
$model = $model->whereIn('id', $this->resultIds);
}
if(count($this->exludeIds)) {
$doQuery = TRUE;
$model = $model->whereNotIn('id', $this->exludeIds);
}
if($this->subSearchExecuted && count($this->resultIds) == 0) {
$doQuery = FALSE;
}
if($doQuery) {
$this->doDefaultSearch = FALSE;
if($this->subSearchExecuted && count($this->resultIds) == 0) {
return $this->queryResults(FALSE, $returnMode);
}
switch($this->filterData['order']) {
case 'alpha':
$model->orderBy('title');
break;
}
return $this->queryResults($model, $returnMode);
} else {
return $this->queryResults(FALSE, $returnMode);
}
}
/**
* @param $model
* @param bool $returnMode
* @return array|int
*/
private function queryResults($model, $returnMode = FALSE)
{
switch ($returnMode) {
case 'getAllResults':
return ($model) ? $model->get() : [];
break;
case 'count':
return ($model) ? $model->count() : 0;
break;
case 'getResults':
//dd($model->toSql());
return ($model) ? $model->limit($this->limit)->offset($this->filterData['offset'])->get() : [];
break;
case 'ids':
return ($model) ? $model->lists('id') : [];
break;
case 'morphId':
return ($model) ? $model->lists('id') : [];
break;
case 'alpha':
$this->resultIds = ($model) ? array_unique($model->lists('id')) : [];
break;
default:
$this->resultIds = ($model) ? array_unique($model->lists('morphId')) : [];
break;
}
}
/**
* @return mixed
*/
private function defaultCount()
{
return Morph::count();
}
/**
* @return mixed
*/
private function defaultSearch()
{
return Morph::limit($this->limit)->orderBy('title', 'asc')->offset($this->filterData['offset'])->get();
}
/**
* @param $results
* @return mixed
*/
private function getOrigin($results)
{
$companyIDs = [];
$peopleIDs = [];
foreach($results as $entity) {
if($entity->type=='company') {
$companyIDs[]= $entity->entityId;
}
if($entity->type == 'individual') {
$peopleIDs[] = $entity->entityId;
}
}
$companies = Company::whereIn('id', $companyIDs)->where('tmp', 0)->get();
foreach($results as $key => $entity) {
if($entity->type != 'company') continue;
foreach($companies as $company) {
if($entity->entityId != $company->id) continue;
$company->sectors = SectorsHelper::Sort($company->sectors);
$company->expertises = ExpertisesHelper::Sort($company->expertises);
$company->entryType = 'company';
$results[$key] = $company;
}
}
$people = Person::whereIn('id', $peopleIDs)->where('tmp', 0)->get();
foreach($results as $key => $entity) {
if($entity->type != 'individual') continue;
foreach($people as $person) {
if($entity->entityId != $person->id) continue;
$person->sectors = SectorsHelper::Sort($person->sectors);
$person->expertises = ExpertisesHelper::Sort($person->expertises);
$person->entryType = 'individual';
$results[$key] = $person;
}
}
$trackingSearchCommunicatorsShown = [];
foreach ($results as $key => $item) {
if(!isset($item->entryType)) {
unset($results[$key]);
continue;
}
$trackingSearchCommunicatorsShown[] = [
'communicatorType' => ($item->entryType == 'company') ? 0 : 1,
'communicatorId' => $item->id
];
}
Tracking::triggerCommunicatorsSearchShown($trackingSearchCommunicatorsShown);
$user = \Auth::user()->get();
if($user) {
$favourites = UserFavourites::where('userId', $user->id)->get();
foreach ($results as $key => $item) {
foreach ($favourites as $fav) {
if($item->entryType == $fav->type && $item->id == $fav->entityId) {
$results[$key]->favourite = TRUE;
}
}
}
}
return $results;
}
/**
* @return string
*/
private function responseRedirect()
{
$params = $this->filter->getQuery();
if(isset($params['offset'])) {
$page = floor($params['offset'] / $this->limit) + 1;
unset($params['offset']);
}
$count = 0;
foreach($params as $param) {
if(is_array($param)) {
$count += count($param);
continue;
}
$count++;
}
if($count == 1) {
$params_routes = [
'sectors' => 'public-search-sector',
'expertises' => 'public-search-expertise',
'size' => 'public-search-size'
];
foreach($params_routes as $key => $route) {
if(!isset($params[$key])) continue;
return route($route).'/'.( is_array($params[$key]) ? current($params[$key]) : $params[$key] ) . ( isset($page) ? '?page='.$page : '' );
}
}
foreach($params as $key => &$param) {
if(is_array($param)) {
$param = $key . '=' . implode(',', $param);
} else {
$param = $key . '=' . $param;
}
}
if(isset($page)) {
$params['page'] = 'page=' . $page;
}
return route('public-search-index').( count($params) ? '?'.implode('&', $params) : '' );
}
/**
* @param $results
* @return mixed
*/
private function responseView($results)
{
if(count($this->filterData['criterias']['sectors'])) {
$sectors = SectorsHelper::GetAndSelectById($this->filterData['criterias']['sectors']);
} else {
$sectors = SectorsHelper::GetAndSort();
}
if(count($this->filterData['criterias']['expertises'])) {
$expertises = ExpertisesHelper::GetAndSelectById($this->filterData['criterias']['expertises']);
} else {
$expertises = ExpertisesHelper::GetAndSort();
}
if(count($this->filterData['clients']['clients_sectors'])) {
$clientSectors = SectorsHelper::GetAndSelectById($this->filterData['clients']['clients_sectors']);
} else {
$clientSectors = SectorsHelper::GetAndSort();
}
$sizes = Size::all();
foreach($sizes as $size) {
if($this->filterData['morph']['size'] == $size->id){
$size->selected = true;
}
}
$countries = Location::getCountries();
foreach($countries as $country) {
if($this->filterData['locations']['country'] == $country->id) {
$country->selected = true;
}
}
return \View::make('search::public.results', [
'user' => (\Auth::user()->get()) ? TRUE : FALSE,
'alpha' => Morph::getAlpha(),
'sectors' => $sectors,
'expertises' => $expertises,
'sizes' => $sizes,
'countries' => $countries,
'states' => Location::getStates(),
'cities' => FALSE,
'clientSectors' => $clientSectors,
'filter' => $this->filterData,
'results' => $results,
]);
}
/**
* @param $results
* @return mixed
*/
private function responseAjax($results)
{
$view = \View::make('search::public.results', [
'bladeExtend' => 'shared::layouts.ajax-search',
'results' => $results,
'route'
]);
return \Response::json([
'url' => $this->responseRedirect(),
'total' => $results['total'],
'html' => $view->render()
]);
}
}
\ No newline at end of file
<?php namespace Modules\Search\Listeners;
/**
* Class SearchEventsListener
* @package Modules\Search\Listeners
*/
class SearchEventsListener
{
/**
* @param $events
*/
public function subscribe($events)
{
$events->listen('communicator.approved', 'Modules\Search\Listeners\SearchEventsListener@onCommunicatorApproved');
$events->listen('communicator.subscribed', 'Modules\Search\Listeners\SearchEventsListener@onCommunicatorSubscribed');
}
/**
* @param $communicatorType
* @param $communicator
*/
public function onCommunicatorApproved($communicatorType, $communicator)
{
if(is_numeric($communicator)) {
$communicator = Communicators::type($communicatorType)->get($communicator);
}
if($communicator->subscriber) {
SearchController::addEntity($communicator, $communicatorType);
}
}
/**
* @param $communicatorType
* @param $communicator
*/
public function onCommunicatorSubscribed($communicatorType, $communicator)
{
if(is_numeric($communicator)) {
$communicator = Communicators::type($communicatorType)->get($communicator);
}
if($communicator->approved) {
SearchController::addEntity($communicator, $communicatorType);
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment