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\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