Prototype for global search

This commit is contained in:
David Bomba 2024-09-22 14:49:43 +10:00
parent 096299a83c
commit a424c43c6e
13 changed files with 1061 additions and 58 deletions

View File

@ -26,29 +26,15 @@ class InvoiceWasPaid implements ShouldBroadcast
{
use SerializesModels, DefaultInvoiceBroadcast;
/**
* @var Invoice
*/
public $invoice;
public $payment;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Invoice $invoice
* @param Company $company
* @param Payment $payment
* @param array $event_vars
*/
public function __construct(Invoice $invoice, Payment $payment, Company $company, array $event_vars)
public function __construct(public Invoice $invoice, public Payment $payment, public Company $company, public array $event_vars)
{
$this->invoice = $invoice;
$this->payment = $payment;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -11,10 +11,12 @@
namespace App\Http\Controllers;
use App\Http\Requests\Search\GenericSearchRequest;
use App\Models\User;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\User;
use Elastic\Elasticsearch\ClientBuilder;
use App\Http\Requests\Search\GenericSearchRequest;
class SearchController extends Controller
{
@ -26,6 +28,14 @@ class SearchController extends Controller
public function __invoke(GenericSearchRequest $request)
{
if(Ninja::isHosted() && $request->has('search') && $request->input('search') !== '') {
try{
return $this->search($request->input('search', ''));
} catch(\Exception $e) {
nlog("elk down?");
}
}
/** @var \App\Models\User $user */
$user = auth()->user();
@ -41,6 +51,95 @@ class SearchController extends Controller
}
public function search(string $search)
{
$user = auth()->user();
$company = $user->company();
$elastic = ClientBuilder::fromConfig(config('elastic.client.connections.default'));
$params = [
'index' => 'clients,invoices,client_contacts',
'body' => [
'query' => [
'bool' => [
'must' => [
'multi_match' => [
'query' => $search,
'fields' => ['*'],
'fuzziness' => 'AUTO',
],
],
'filter' => [
'match' => [
'company_key' => $company->company_key,
],
],
],
],
'size' => 1000,
],
];
$results = $elastic->search($params);
$this->mapResults($results['hits']['hits'] ?? []);
return response()->json([
'clients' => $this->clients,
'client_contacts' => $this->client_contacts,
'invoices' => $this->invoices,
'settings' => $this->settingsMap(),
], 200);
}
private function mapResults(array $results)
{
foreach($results as $result) {
switch($result['_index']) {
case 'clients':
if($result['_source']['is_deleted'])
continue;
$this->clients[] = [
'name' => $result['_source']['name'],
'type' => '/client',
'id' => $result['_source']['hashed_id'],
'path' => "/clients/{$result['_source']['hashed_id']}"
];
break;
case 'invoices':
if ($result['_source']['is_deleted']) {
continue;
}
$this->invoices[] = [
'name' => $result['_source']['name'],
'type' => '/invoice',
'id' => $result['_source']['hashed_id'],
'path' => "/invoices/{$result['_source']['hashed_id']}/edit"
];
break;
case 'client_contacts':
if($result['_source']['__soft_deleted'])
continue;
$this->client_contacts[] = [
'name' => $result['_source']['name'],
'type' => '/client',
'id' => $result['_source']['hashed_id'],
'path' => "/clients/{$result['_source']['hashed_id']}"
];
break;
}
}
}
private function clientMap(User $user)
{
@ -81,20 +180,14 @@ class SearchController extends Controller
$invoices = Invoice::query()
->company()
->with('client')
->where('invoices.is_deleted', 0)
// ->whereHas('client', function ($q) {
// $q->where('is_deleted', 0);
// })
->leftJoin('clients', function ($join) {
$join->on('invoices.client_id', '=', 'clients.id')
->where('clients.is_deleted', 0);
})
->where('is_deleted', 0)
->whereHas('client', function ($q) {
$q->where('is_deleted', 0);
})
->when(!$user->hasPermission('view_all') || !$user->hasPermission('view_invoice'), function ($query) use ($user) {
$query->where('invoices.user_id', $user->id);
})
->orderBy('invoices.id', 'desc')
->orderBy('id', 'desc')
->take(3000)
->get();

View File

@ -37,7 +37,7 @@ class ShowCalculatedFieldRequest extends Request
'date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,all_time,custom',
'start_date' => 'bail|sometimes|date',
'end_date' => 'bail|sometimes|date',
'field' => 'required|bail|in:active_invoices, outstanding_invoices, completed_payments, refunded_payments, active_quotes, unapproved_quotes, logged_tasks, invoiced_tasks, paid_tasks, logged_expenses, pending_expenses, invoiced_expenses, invoice_paid_expenses',
'field' => 'required|bail|in:active_invoices,outstanding_invoices,completed_payments,refunded_payments,active_quotes,unapproved_quotes logged_tasks,invoiced_tasks,paid_tasks,logged_expenses,pending_expenses,invoiced_expenses,invoice_paid_expenses',
'calculation' => 'required|bail|in:sum,avg,count',
'period' => 'required|bail|in:current,previous,total',
'format' => 'sometimes|bail|in:time,money',

View File

@ -11,23 +11,24 @@
namespace App\Models;
use Laravel\Scout\Searchable;
use App\Utils\Traits\AppSetup;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\MakesDates;
use App\DataMapper\FeesAndLimits;
use App\Models\Traits\Excludable;
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\DataMapper\FeesAndLimits;
use App\Libraries\Currency\Conversion\CurrencyApi;
use App\Models\Presenters\ClientPresenter;
use App\Models\Traits\Excludable;
use App\Services\Client\ClientService;
use App\Utils\Traits\AppSetup;
use App\Utils\Traits\ClientGroupSettingsSaver;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\MakesDates;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laracasts\Presenter\PresentableTrait;
use App\Models\Presenters\ClientPresenter;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Utils\Traits\ClientGroupSettingsSaver;
use App\Libraries\Currency\Conversion\CurrencyApi;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Contracts\Translation\HasLocalePreference;
/**
* App\Models\Client
@ -124,6 +125,9 @@ class Client extends BaseModel implements HasLocalePreference
use ClientGroupSettingsSaver;
use Excludable;
use Searchable;
protected $presenter = ClientPresenter::class;
protected $hidden = [
@ -232,6 +236,38 @@ class Client extends BaseModel implements HasLocalePreference
'custom_value4',
];
public function toSearchableArray()
{
return [
'name' => $this->present()->name(),
'is_deleted' => $this->is_deleted,
'hashed_id' => $this->hashed_id,
'number' => $this->number,
'id_number' => $this->id_number,
'vat_number' => $this->vat_number,
'balance' => $this->balance,
'paid_to_date' => $this->paid_to_date,
'phone' => $this->phone,
'address1' => $this->address1,
'address2' => $this->address2,
'city' => $this->city,
'state' => $this->state,
'postal_code' => $this->postal_code,
'website' => $this->website,
'private_notes' => $this->private_notes,
'public_notes' => $this->public_notes,
'shipping_address1' => $this->shipping_address1,
'shipping_address2' => $this->shipping_address2,
'shipping_city' => $this->shipping_city,
'shipping_state' => $this->shipping_state,
'shipping_postal_code' => $this->shipping_postal_code,
'custom_value1' => $this->custom_value1,
'custom_value2' => $this->custom_value2,
'custom_value3' => $this->custom_value3,
'custom_value4' => $this->custom_value4,
'company_key' => $this->company->company_key,
];
}
public function getEntityType()
{

View File

@ -13,6 +13,7 @@ namespace App\Models;
use App\Utils\Ninja;
use Illuminate\Support\Str;
use Laravel\Scout\Searchable;
use App\Jobs\Mail\NinjaMailer;
use App\Utils\Traits\AppSetup;
use App\Utils\Traits\MakesHash;
@ -100,6 +101,8 @@ class ClientContact extends Authenticatable implements HasLocalePreference
use HasFactory;
use AppSetup;
use Searchable;
/* Used to authenticate a contact */
protected $guard = 'contact';
@ -165,6 +168,23 @@ class ClientContact extends Authenticatable implements HasLocalePreference
'email',
];
public function toSearchableArray()
{
return [
'name' => $this->present()->search_display(),
'hashed_id' => $this->client->hashed_id,
'email' => $this->email,
'first_name' => $this->first_name,
'last_name' => $this->last_name,
'phone' => $this->phone,
'custom_value1' => $this->custom_value1,
'custom_value2' => $this->custom_value2,
'custom_value3' => $this->custom_value3,
'custom_value4' => $this->custom_value4,
'company_key' => $this->company->company_key,
];
}
/*
V2 type of scope
*/

View File

@ -11,22 +11,23 @@
namespace App\Models;
use App\Events\Invoice\InvoiceReminderWasEmailed;
use App\Events\Invoice\InvoiceWasEmailed;
use App\Helpers\Invoice\InvoiceSum;
use App\Helpers\Invoice\InvoiceSumInclusive;
use App\Models\Presenters\EntityPresenter;
use App\Services\Invoice\InvoiceService;
use App\Services\Ledger\LedgerService;
use App\Utils\Ninja;
use App\Utils\Traits\Invoice\ActionsInvoice;
use Laravel\Scout\Searchable;
use Illuminate\Support\Carbon;
use App\Utils\Traits\MakesDates;
use App\Utils\Traits\MakesInvoiceValues;
use App\Helpers\Invoice\InvoiceSum;
use App\Utils\Traits\MakesReminders;
use App\Utils\Traits\NumberFormatter;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon;
use App\Services\Ledger\LedgerService;
use App\Services\Invoice\InvoiceService;
use App\Utils\Traits\MakesInvoiceValues;
use App\Events\Invoice\InvoiceWasEmailed;
use Laracasts\Presenter\PresentableTrait;
use App\Models\Presenters\EntityPresenter;
use App\Helpers\Invoice\InvoiceSumInclusive;
use App\Utils\Traits\Invoice\ActionsInvoice;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Events\Invoice\InvoiceReminderWasEmailed;
/**
* App\Models\Invoice
@ -144,6 +145,8 @@ class Invoice extends BaseModel
use MakesReminders;
use ActionsInvoice;
use Searchable;
protected $presenter = EntityPresenter::class;
protected $touches = [];
@ -235,6 +238,25 @@ class Invoice extends BaseModel
public const STATUS_UNPAID = -2; //status < 4 || < 3 && !is_deleted && !trashed()
public function toSearchableArray()
{
return [
'name' => $this->client->present()->name() . ' - ' . $this->number,
'hashed_id' => $this->hashed_id,
'number' => $this->number,
'is_deleted' => $this->is_deleted,
'amount' => (float) $this->amount,
'balance' => (float) $this->balance,
'due_date' => $this->due_date,
'date' => $this->date,
'custom_value1' => $this->custom_value1,
'custom_value2' => $this->custom_value2,
'custom_value3' => $this->custom_value3,
'custom_value4' => $this->custom_value4,
'company_key' => $this->company->company_key,
];
}
public function getEntityType()
{
return self::class;

View File

@ -141,8 +141,8 @@ trait ChartCalculations
}
match ($data['calculation']) {
'sum' => $result = $q->sum('refunded'),
'avg' => $result = $q->avg('refunded'),
'sum' => $result = $q->sum('amount'),
'avg' => $result = $q->avg('amount'),
'count' => $result = $q->count(),
default => $result = 0,
};
@ -287,14 +287,14 @@ trait ChartCalculations
return $query->get()
->when($data['currency_id'] == '999', function ($collection) {
$collection->map(function ($e) {
return $collection->map(function ($e) {
/** @var \App\Models\Expense $e */
return $e->amount * $e->exchange_rate;
});
})
->when($data['currency_id'] != '999', function ($collection) {
$collection->map(function ($e) {
return $collection->map(function ($e) {
/** @var \App\Models\Expense $e */
return $e->amount;

View File

@ -166,6 +166,10 @@ class InvoiceTransformer extends EntityTransformer
$data['reminder_schedule'] = (string) $invoice->reminderSchedule();
}
if (request()->has('is_locked') && request()->query('is_locked') == 'true') {
$data['is_locked'] = (bool) $invoice->isLocked();
}
return $data;
}

View File

@ -41,6 +41,7 @@
"authorizenet/authorizenet": "^2.0",
"awobaz/compoships": "^2.1",
"aws/aws-sdk-php": "^3.319",
"babenkoivan/elastic-scout-driver": "^4.0",
"bacon/bacon-qr-code": "^2.0",
"beganovich/snappdf": "dev-master",
"braintree/braintree_php": "^6.0",
@ -68,6 +69,7 @@
"josemmo/facturae-php": "^1.7",
"laracasts/presenter": "^0.2.1",
"laravel/framework": "^11.0",
"laravel/scout": "^10.11",
"laravel/slack-notification-channel": "^3",
"laravel/socialite": "^5",
"laravel/tinker": "^2.7",

611
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "a1fac503f165997d7aa339239e002230",
"content-hash": "79894c80128f463131a8bf601f5fbfcb",
"packages": [
{
"name": "adrienrn/php-mimetyper",
@ -631,6 +631,217 @@
},
"time": "2024-09-13T18:05:10+00:00"
},
{
"name": "babenkoivan/elastic-adapter",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://github.com/babenkoivan/elastic-adapter.git",
"reference": "3a1fbb2d30c0b9e84c50204c1406cb7e44e6d2a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/babenkoivan/elastic-adapter/zipball/3a1fbb2d30c0b9e84c50204c1406cb7e44e6d2a1",
"reference": "3a1fbb2d30c0b9e84c50204c1406cb7e44e6d2a1",
"shasum": ""
},
"require": {
"babenkoivan/elastic-client": "^3.0",
"php": "^8.2"
},
"require-dev": {
"dg/bypass-finals": "^1.7",
"friendsofphp/php-cs-fixer": "^3.14",
"orchestra/testbench": "^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^11.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Elastic\\Adapter\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ivan Babenko",
"email": "babenko.i.a@gmail.com"
}
],
"description": "Adapter for official PHP Elasticsearch client",
"keywords": [
"adapter",
"client",
"elastic",
"elasticsearch",
"php"
],
"support": {
"issues": "https://github.com/babenkoivan/elastic-adapter/issues",
"source": "https://github.com/babenkoivan/elastic-adapter/tree/v4.0.0"
},
"funding": [
{
"url": "https://ko-fi.com/ivanbabenko",
"type": "ko-fi"
},
{
"url": "https://paypal.me/babenkoi",
"type": "paypal"
}
],
"time": "2024-06-18T06:57:10+00:00"
},
{
"name": "babenkoivan/elastic-client",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/babenkoivan/elastic-client.git",
"reference": "65f4a4c9dc3b5f6ba4e68e59ad26a68393aae995"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/babenkoivan/elastic-client/zipball/65f4a4c9dc3b5f6ba4e68e59ad26a68393aae995",
"reference": "65f4a4c9dc3b5f6ba4e68e59ad26a68393aae995",
"shasum": ""
},
"require": {
"elasticsearch/elasticsearch": "^8.0",
"php": "^8.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.14",
"orchestra/testbench": "^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^11.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Elastic\\Client\\ServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Elastic\\Client\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ivan Babenko",
"email": "babenko.i.a@gmail.com"
}
],
"description": "The official PHP Elasticsearch client integrated with Laravel",
"keywords": [
"client",
"elastic",
"elasticsearch",
"laravel",
"php"
],
"support": {
"issues": "https://github.com/babenkoivan/elastic-client/issues",
"source": "https://github.com/babenkoivan/elastic-client/tree/v3.0.0"
},
"funding": [
{
"url": "https://ko-fi.com/ivanbabenko",
"type": "ko-fi"
},
{
"url": "https://paypal.me/babenkoi",
"type": "paypal"
}
],
"time": "2024-06-18T06:53:01+00:00"
},
{
"name": "babenkoivan/elastic-scout-driver",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://github.com/babenkoivan/elastic-scout-driver.git",
"reference": "f3791521fb3216850335f491a1461a16738125cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/babenkoivan/elastic-scout-driver/zipball/f3791521fb3216850335f491a1461a16738125cd",
"reference": "f3791521fb3216850335f491a1461a16738125cd",
"shasum": ""
},
"require": {
"babenkoivan/elastic-adapter": "^4.0",
"php": "^8.2"
},
"require-dev": {
"babenkoivan/elastic-migrations": "^4.0",
"friendsofphp/php-cs-fixer": "^3.14",
"laravel/legacy-factories": "^1.3",
"laravel/scout": "^10.0",
"orchestra/testbench": "^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^11.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Elastic\\ScoutDriver\\ServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Elastic\\ScoutDriver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ivan Babenko",
"email": "babenko.i.a@gmail.com"
}
],
"description": "Elasticsearch driver for Laravel Scout",
"keywords": [
"driver",
"elastic",
"elasticsearch",
"laravel",
"php",
"scout"
],
"support": {
"issues": "https://github.com/babenkoivan/elastic-scout-driver/issues",
"source": "https://github.com/babenkoivan/elastic-scout-driver/tree/v4.0.0"
},
"funding": [
{
"url": "https://ko-fi.com/ivanbabenko",
"type": "ko-fi"
},
{
"url": "https://paypal.me/babenkoi",
"type": "paypal"
}
],
"time": "2024-06-18T07:06:48+00:00"
},
{
"name": "bacon/bacon-qr-code",
"version": "2.0.8",
@ -1950,6 +2161,122 @@
],
"time": "2023-10-06T06:47:41+00:00"
},
{
"name": "elastic/transport",
"version": "v8.10.0",
"source": {
"type": "git",
"url": "https://github.com/elastic/elastic-transport-php.git",
"reference": "8be37d679637545e50b1cea9f8ee903888783021"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/elastic/elastic-transport-php/zipball/8be37d679637545e50b1cea9f8ee903888783021",
"reference": "8be37d679637545e50b1cea9f8ee903888783021",
"shasum": ""
},
"require": {
"composer-runtime-api": "^2.0",
"open-telemetry/api": "^1.0",
"php": "^7.4 || ^8.0",
"php-http/discovery": "^1.14",
"php-http/httplug": "^2.3",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0 || ^2.0",
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
"nyholm/psr7": "^1.5",
"open-telemetry/sdk": "^1.0",
"php-http/mock-client": "^1.5",
"phpstan/phpstan": "^1.4",
"phpunit/phpunit": "^9.5",
"symfony/http-client": "^5.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Elastic\\Transport\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "HTTP transport PHP library for Elastic products",
"keywords": [
"PSR_17",
"elastic",
"http",
"psr-18",
"psr-7",
"transport"
],
"support": {
"issues": "https://github.com/elastic/elastic-transport-php/issues",
"source": "https://github.com/elastic/elastic-transport-php/tree/v8.10.0"
},
"time": "2024-08-14T08:55:07+00:00"
},
{
"name": "elasticsearch/elasticsearch",
"version": "v8.15.0",
"source": {
"type": "git",
"url": "https://github.com/elastic/elasticsearch-php.git",
"reference": "34c2444fa8d4c3e6c8b009bd8dea90bca007203b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/elastic/elasticsearch-php/zipball/34c2444fa8d4c3e6c8b009bd8dea90bca007203b",
"reference": "34c2444fa8d4c3e6c8b009bd8dea90bca007203b",
"shasum": ""
},
"require": {
"elastic/transport": "^8.10",
"guzzlehttp/guzzle": "^7.0",
"php": "^7.4 || ^8.0",
"psr/http-client": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"psr/log": "^1|^2|^3"
},
"require-dev": {
"ext-yaml": "*",
"ext-zip": "*",
"mockery/mockery": "^1.5",
"nyholm/psr7": "^1.5",
"php-http/message-factory": "^1.0",
"php-http/mock-client": "^1.5",
"phpstan/phpstan": "^1.4",
"phpunit/phpunit": "^9.5",
"psr/http-factory": "^1.0",
"symfony/finder": "~4.0",
"symfony/http-client": "^5.0|^6.0|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Elastic\\Elasticsearch\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHP Client for Elasticsearch",
"keywords": [
"client",
"elastic",
"elasticsearch",
"search"
],
"support": {
"issues": "https://github.com/elastic/elasticsearch-php/issues",
"source": "https://github.com/elastic/elasticsearch-php/tree/v8.15.0"
},
"time": "2024-08-14T14:32:50+00:00"
},
{
"name": "endroid/qr-code",
"version": "5.0.7",
@ -4820,6 +5147,84 @@
},
"time": "2024-08-12T22:06:33+00:00"
},
{
"name": "laravel/scout",
"version": "v10.11.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/scout.git",
"reference": "642b4750127b5242a089571c9314037a7453cc0a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/scout/zipball/642b4750127b5242a089571c9314037a7453cc0a",
"reference": "642b4750127b5242a089571c9314037a7453cc0a",
"shasum": ""
},
"require": {
"illuminate/bus": "^9.0|^10.0|^11.0",
"illuminate/contracts": "^9.0|^10.0|^11.0",
"illuminate/database": "^9.0|^10.0|^11.0",
"illuminate/http": "^9.0|^10.0|^11.0",
"illuminate/pagination": "^9.0|^10.0|^11.0",
"illuminate/queue": "^9.0|^10.0|^11.0",
"illuminate/support": "^9.0|^10.0|^11.0",
"php": "^8.0",
"symfony/console": "^6.0|^7.0"
},
"require-dev": {
"algolia/algoliasearch-client-php": "^3.2",
"meilisearch/meilisearch-php": "^1.0",
"mockery/mockery": "^1.0",
"orchestra/testbench": "^7.31|^8.11|^9.0",
"php-http/guzzle7-adapter": "^1.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.3|^10.4",
"typesense/typesense-php": "^4.9.3"
},
"suggest": {
"algolia/algoliasearch-client-php": "Required to use the Algolia engine (^3.2).",
"meilisearch/meilisearch-php": "Required to use the Meilisearch engine (^1.0).",
"typesense/typesense-php": "Required to use the Typesense engine (^4.9)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "10.x-dev"
},
"laravel": {
"providers": [
"Laravel\\Scout\\ScoutServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Scout\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel Scout provides a driver based solution to searching your Eloquent models.",
"keywords": [
"algolia",
"laravel",
"search"
],
"support": {
"issues": "https://github.com/laravel/scout/issues",
"source": "https://github.com/laravel/scout"
},
"time": "2024-09-11T21:32:42+00:00"
},
{
"name": "laravel/serializable-closure",
"version": "v1.3.4",
@ -7633,6 +8038,134 @@
],
"time": "2024-09-09T07:06:30+00:00"
},
{
"name": "open-telemetry/api",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/api.git",
"reference": "87de95d926f46262885d0d390060c095af13e2e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/api/zipball/87de95d926f46262885d0d390060c095af13e2e5",
"reference": "87de95d926f46262885d0d390060c095af13e2e5",
"shasum": ""
},
"require": {
"open-telemetry/context": "^1.0",
"php": "^7.4 || ^8.0",
"psr/log": "^1.1|^2.0|^3.0",
"symfony/polyfill-php80": "^1.26",
"symfony/polyfill-php81": "^1.26",
"symfony/polyfill-php82": "^1.26"
},
"conflict": {
"open-telemetry/sdk": "<=1.0.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.0.x-dev"
}
},
"autoload": {
"files": [
"Trace/functions.php"
],
"psr-4": {
"OpenTelemetry\\API\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "opentelemetry-php contributors",
"homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors"
}
],
"description": "API for OpenTelemetry PHP.",
"keywords": [
"Metrics",
"api",
"apm",
"logging",
"opentelemetry",
"otel",
"tracing"
],
"support": {
"chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V",
"docs": "https://opentelemetry.io/docs/php",
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2024-02-06T01:32:25+00:00"
},
{
"name": "open-telemetry/context",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/context.git",
"reference": "e9d254a7c89885e63fd2fde54e31e81aaaf52b7c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/e9d254a7c89885e63fd2fde54e31e81aaaf52b7c",
"reference": "e9d254a7c89885e63fd2fde54e31e81aaaf52b7c",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"symfony/polyfill-php80": "^1.26",
"symfony/polyfill-php81": "^1.26",
"symfony/polyfill-php82": "^1.26"
},
"suggest": {
"ext-ffi": "To allow context switching in Fibers"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.0.x-dev"
}
},
"autoload": {
"files": [
"fiber/initialize_fiber_handler.php"
],
"psr-4": {
"OpenTelemetry\\Context\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "opentelemetry-php contributors",
"homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors"
}
],
"description": "Context implementation for OpenTelemetry PHP.",
"keywords": [
"Context",
"opentelemetry",
"otel"
],
"support": {
"chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V",
"docs": "https://opentelemetry.io/docs/php",
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2024-01-13T05:50:44+00:00"
},
{
"name": "paragonie/constant_time_encoding",
"version": "v3.0.0",
@ -13134,6 +13667,82 @@
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php82",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php82.git",
"reference": "5d2ed36f7734637dacc025f179698031951b1692"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/5d2ed36f7734637dacc025f179698031951b1692",
"reference": "5d2ed36f7734637dacc025f179698031951b1692",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php82\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php82/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php83",
"version": "v1.31.0",

24
config/elastic.client.php Normal file
View File

@ -0,0 +1,24 @@
<?php declare(strict_types=1);
return [
'default' => env('ELASTIC_CONNECTION', 'default'),
'connections' => [
'default' => [
'hosts' => [
env('ELASTIC_HOST'),
],
// configure basic authentication
'basicAuthentication' => [
env('ELASTIC_USERNAME'),
env('ELASTIC_PASSWORD'),
],
// configure HTTP client (Guzzle by default)
'httpClientOptions' => [
'timeout' => 2,
'verify_host' => false, // Disable SSL verification
'verify_peer' => false,
],
],
],
];

View File

@ -0,0 +1,5 @@
<?php declare(strict_types=1);
return [
'refresh_documents' => env('ELASTIC_SCOUT_DRIVER_REFRESH_DOCUMENTS', false),
];

202
config/scout.php Normal file
View File

@ -0,0 +1,202 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Search Engine
|--------------------------------------------------------------------------
|
| This option controls the default search connection that gets used while
| using Laravel Scout. This connection is used when syncing all models
| to the search service. You should adjust this based on your needs.
|
| Supported: "algolia", "meilisearch", "typesense",
| "database", "collection", "null"
|
*/
'driver' => env('SCOUT_DRIVER', 'algolia'),
/*
|--------------------------------------------------------------------------
| Index Prefix
|--------------------------------------------------------------------------
|
| Here you may specify a prefix that will be applied to all search index
| names used by Scout. This prefix may be useful if you have multiple
| "tenants" or applications sharing the same search infrastructure.
|
*/
'prefix' => env('SCOUT_PREFIX', ''),
/*
|--------------------------------------------------------------------------
| Queue Data Syncing
|--------------------------------------------------------------------------
|
| This option allows you to control if the operations that sync your data
| with your search engines are queued. When this is set to "true" then
| all automatic data syncing will get queued for better performance.
|
*/
'queue' => env('SCOUT_QUEUE', true),
/*
|--------------------------------------------------------------------------
| Database Transactions
|--------------------------------------------------------------------------
|
| This configuration option determines if your data will only be synced
| with your search indexes after every open database transaction has
| been committed, thus preventing any discarded data from syncing.
|
*/
'after_commit' => false,
/*
|--------------------------------------------------------------------------
| Chunk Sizes
|--------------------------------------------------------------------------
|
| These options allow you to control the maximum chunk size when you are
| mass importing data into the search engine. This allows you to fine
| tune each of these chunk sizes based on the power of the servers.
|
*/
'chunk' => [
'searchable' => 500,
'unsearchable' => 500,
],
/*
|--------------------------------------------------------------------------
| Soft Deletes
|--------------------------------------------------------------------------
|
| This option allows to control whether to keep soft deleted records in
| the search indexes. Maintaining soft deleted records can be useful
| if your application still needs to search for the records later.
|
*/
'soft_delete' => true,
/*
|--------------------------------------------------------------------------
| Identify User
|--------------------------------------------------------------------------
|
| This option allows you to control whether to notify the search engine
| of the user performing the search. This is sometimes useful if the
| engine supports any analytics based on this application's users.
|
| Supported engines: "algolia"
|
*/
'identify' => env('SCOUT_IDENTIFY', false),
/*
|--------------------------------------------------------------------------
| Algolia Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your Algolia settings. Algolia is a cloud hosted
| search engine which works great with Scout out of the box. Just plug
| in your application ID and admin API key to get started searching.
|
*/
'algolia' => [
'id' => env('ALGOLIA_APP_ID', ''),
'secret' => env('ALGOLIA_SECRET', ''),
],
/*
|--------------------------------------------------------------------------
| Meilisearch Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your Meilisearch settings. Meilisearch is an open
| source search engine with minimal configuration. Below, you can state
| the host and key information for your own Meilisearch installation.
|
| See: https://www.meilisearch.com/docs/learn/configuration/instance_options#all-instance-options
|
*/
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY'),
'index-settings' => [
// 'users' => [
// 'filterableAttributes'=> ['id', 'name', 'email'],
// ],
],
],
/*
|--------------------------------------------------------------------------
| Typesense Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your Typesense settings. Typesense is an open
| source search engine using minimal configuration. Below, you will
| state the host, key, and schema configuration for the instance.
|
*/
'typesense' => [
'client-settings' => [
'api_key' => env('TYPESENSE_API_KEY', 'xyz'),
'nodes' => [
[
'host' => env('TYPESENSE_HOST', 'localhost'),
'port' => env('TYPESENSE_PORT', '8108'),
'path' => env('TYPESENSE_PATH', ''),
'protocol' => env('TYPESENSE_PROTOCOL', 'http'),
],
],
'nearest_node' => [
'host' => env('TYPESENSE_HOST', 'localhost'),
'port' => env('TYPESENSE_PORT', '8108'),
'path' => env('TYPESENSE_PATH', ''),
'protocol' => env('TYPESENSE_PROTOCOL', 'http'),
],
'connection_timeout_seconds' => env('TYPESENSE_CONNECTION_TIMEOUT_SECONDS', 2),
'healthcheck_interval_seconds' => env('TYPESENSE_HEALTHCHECK_INTERVAL_SECONDS', 30),
'num_retries' => env('TYPESENSE_NUM_RETRIES', 3),
'retry_interval_seconds' => env('TYPESENSE_RETRY_INTERVAL_SECONDS', 1),
],
'model-settings' => [
// User::class => [
// 'collection-schema' => [
// 'fields' => [
// [
// 'name' => 'id',
// 'type' => 'string',
// ],
// [
// 'name' => 'name',
// 'type' => 'string',
// ],
// [
// 'name' => 'created_at',
// 'type' => 'int64',
// ],
// ],
// 'default_sorting_field' => 'created_at',
// ],
// 'search-parameters' => [
// 'query_by' => 'name'
// ],
// ],
],
],
];