mirror of
https://github.com/snipe/snipe-it.git
synced 2025-01-11 05:47:28 -08:00
Refactoring: A nicer and easier syntax for searching models (#5841)
* Adds the ability to search by dates Adding extra „where“-conditions to the „TextSearch“ queries, allowing the users to search by dates * Adds missing dates to $dates in models * Removes duplicated „where“ conditions * Adds the Searchable trait to models, defining the searchable attributes and relations * Removes the old text search methods * Adds back additional conditions to the search These conditions could not be modeled in the „attributes“ or „relations“, so we include them here * Removes unnecessary check for the deleted_at attribute * Fixes typo in comments * suppresses errors from Codacy We can safely ignore the error codacy is throwing here, since this method is a standin/noop for models who need to implement more advanced searches
This commit is contained in:
parent
240e642fe9
commit
baa3be728d
|
@ -24,7 +24,7 @@ class AccessoriesController extends Controller
|
|||
$this->authorize('view', Accessory::class);
|
||||
$allowed_columns = ['id','name','model_number','eol','notes','created_at','min_amt','company_id'];
|
||||
|
||||
$accessories = Accessory::whereNull('accessories.deleted_at')->with('category', 'company', 'manufacturer', 'users', 'location');
|
||||
$accessories = Accessory::with('category', 'company', 'manufacturer', 'users', 'location');
|
||||
|
||||
if ($request->has('search')) {
|
||||
$accessories = $accessories->TextSearch($request->input('search'));
|
||||
|
|
|
@ -24,7 +24,7 @@ class ComponentsController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Component::class);
|
||||
$components = Company::scopeCompanyables(Component::select('components.*')->whereNull('components.deleted_at')
|
||||
$components = Company::scopeCompanyables(Component::select('components.*')
|
||||
->with('company', 'location', 'category'));
|
||||
|
||||
if ($request->has('search')) {
|
||||
|
|
|
@ -24,7 +24,6 @@ class ConsumablesController extends Controller
|
|||
$this->authorize('index', Consumable::class);
|
||||
$consumables = Company::scopeCompanyables(
|
||||
Consumable::select('consumables.*')
|
||||
->whereNull('consumables.deleted_at')
|
||||
->with('company', 'location', 'category', 'users', 'manufacturer')
|
||||
);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class SuppliersController extends Controller
|
|||
|
||||
$suppliers = Supplier::select(
|
||||
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at','image','notes')
|
||||
)->withCount('assets')->withCount('licenses')->withCount('accessories')->whereNull('deleted_at');
|
||||
)->withCount('assets')->withCount('licenses')->withCount('accessories');
|
||||
|
||||
|
||||
if ($request->has('search')) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -25,6 +26,28 @@ class Accessory extends SnipeModel
|
|||
'requestable' => 'boolean'
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'model_number', 'order_number', 'purchase_date'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'category' => ['name'],
|
||||
'company' => ['name'],
|
||||
'manufacturer' => ['name'],
|
||||
'supplier' => ['name'],
|
||||
'location' => ['name']
|
||||
];
|
||||
|
||||
/**
|
||||
* Set static properties to determine which checkout/checkin handlers we should use
|
||||
*/
|
||||
|
@ -171,40 +194,6 @@ class Accessory extends SnipeModel
|
|||
return $remaining;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->whereHas('category', function ($query) use ($search) {
|
||||
$query->where('categories.name', 'LIKE', '%'.$search.'%');
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('company', function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('manufacturer', function ($query) use ($search) {
|
||||
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('location', function ($query) use ($search) {
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere('accessories.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('accessories.model_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('accessories.order_number', 'LIKE', '%'.$search.'%');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
namespace App\Models;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
@ -24,6 +25,24 @@ class Actionlog extends SnipeModel
|
|||
public $timestamps = true;
|
||||
protected $fillable = [ 'created_at', 'item_type','user_id','item_id','action_type','note','target_id', 'target_type' ];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['action_type', 'note', 'log_meta'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'company' => ['name']
|
||||
];
|
||||
|
||||
// Overridden from Builder to automatically add the company
|
||||
public static function boot()
|
||||
{
|
||||
|
@ -200,31 +219,4 @@ class Actionlog extends SnipeModel
|
|||
->orderBy('created_at', 'asc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text for complex Bootstrap Tables API
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
$search = explode(' OR ', $search);
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
foreach ($search as $search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->whereHas('company', function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere('action_type', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('note', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('log_meta', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ namespace App\Models;
|
|||
use App\Exceptions\CheckoutNotAllowed;
|
||||
use App\Http\Traits\UniqueSerialTrait;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use AssetPresenter;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Log;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -111,7 +113,42 @@ class Asset extends Depreciable
|
|||
'warranty_months',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = [
|
||||
'name',
|
||||
'asset_tag',
|
||||
'serial',
|
||||
'order_number',
|
||||
'purchase_cost',
|
||||
'notes',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'purchase_date',
|
||||
'expected_checkin',
|
||||
'next_audit_date',
|
||||
'last_audit_date'
|
||||
];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'assetstatus' => ['name'],
|
||||
'supplier' => ['name'],
|
||||
'company' => ['name'],
|
||||
'defaultLoc' => ['name'],
|
||||
'model' => ['name', 'model_number'],
|
||||
'model.category' => ['name'],
|
||||
'model.manufacturer' => ['name'],
|
||||
];
|
||||
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
|
@ -580,6 +617,49 @@ class Asset extends Depreciable
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run additional, advanced searches.
|
||||
*
|
||||
* @param Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $term The search term
|
||||
* @return Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function advancedTextSearch(Builder $query, string $term) {
|
||||
/**
|
||||
* Assigned user
|
||||
*/
|
||||
$query = $query->leftJoin('users as assets_users',function ($leftJoin) {
|
||||
$leftJoin->on("assets_users.id", "=", "assets.assigned_to")
|
||||
->where("assets.assigned_type", "=", User::class);
|
||||
});
|
||||
$query = $query
|
||||
->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.username', 'LIKE', '%'.$term.'%')
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%", "%$term%"]);
|
||||
|
||||
/**
|
||||
* Assigned location
|
||||
*/
|
||||
$query = $query->leftJoin('locations as assets_locations',function ($leftJoin) {
|
||||
$leftJoin->on("assets_locations.id","=","assets.assigned_to")
|
||||
->where("assets.assigned_type","=",Location::class);
|
||||
});
|
||||
|
||||
$query = $query->orWhere('assets_locations.name', 'LIKE', '%'.$term.'%');
|
||||
|
||||
/**
|
||||
* Assigned assets
|
||||
*/
|
||||
$query = $query->leftJoin('assets as assigned_assets',function ($leftJoin) {
|
||||
$leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to')
|
||||
->where('assets.assigned_type', '=', Asset::class);
|
||||
});
|
||||
|
||||
$query = $query->orWhere('assigned_assets.name', 'LIKE', '%'.$term.'%');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
|
@ -813,83 +893,6 @@ class Asset extends Depreciable
|
|||
return $query->where("accepted", "=", "accepted");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text for complex Bootstrap Tables API.
|
||||
* This is really horrible, but I can't think of a less-awful way to do it.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
$search = explode(' OR ', $search);
|
||||
|
||||
return $query->leftJoin('users as assets_users',function ($leftJoin) {
|
||||
$leftJoin->on("assets_users.id", "=", "assets.assigned_to")
|
||||
->where("assets.assigned_type", "=", User::class);
|
||||
})->leftJoin('locations as assets_locations',function ($leftJoin) {
|
||||
$leftJoin->on("assets_locations.id","=","assets.assigned_to")
|
||||
->where("assets.assigned_type","=",Location::class);
|
||||
})->leftJoin('assets as assigned_assets',function ($leftJoin) {
|
||||
$leftJoin->on('assigned_assets.id', '=', 'assets.assigned_to')
|
||||
->where('assets.assigned_type', '=', Asset::class);
|
||||
})->where(function ($query) use ($search) {
|
||||
foreach ($search as $search) {
|
||||
$query->whereHas('model', function ($query) use ($search) {
|
||||
$query->whereHas('category', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('categories.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('models.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('models.model_number', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
})->orWhereHas('model', function ($query) use ($search) {
|
||||
$query->whereHas('manufacturer', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('assetstatus', function ($query) use ($search) {
|
||||
$query->where('status_labels.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('supplier', function ($query) use ($search) {
|
||||
$query->where('suppliers.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('company', function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('defaultLoc', function ($query) use ($search) {
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->where('assets_users.first_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets_users.last_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$search%", "%$search%"])
|
||||
->orWhere('assets_users.username', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets_locations.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assigned_assets.name', 'LIKE', '%'.$search.'%');
|
||||
})->orWhere('assets.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.asset_tag', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.serial', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.purchase_cost', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.notes', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
foreach (CustomField::all() as $field) {
|
||||
$query->orWhere('assets.'.$field->db_column_name(), 'LIKE', "%$search%");
|
||||
}
|
||||
})->withTrashed()->whereNull("assets.deleted_at"); //workaround for laravel bug
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text for complex Bootstrap Tables API.
|
||||
*
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Searchable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
@ -19,7 +20,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
|||
use ValidatingTrait;
|
||||
|
||||
|
||||
protected $dates = [ 'deleted_at' ];
|
||||
protected $dates = [ 'deleted_at', 'start_date' , 'completion_date'];
|
||||
protected $table = 'asset_maintenances';
|
||||
// Declaring rules for form validation
|
||||
protected $rules = [
|
||||
|
@ -34,6 +35,23 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
|||
'cost' => 'numeric|nullable'
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['title', 'notes', 'asset_maintenance_type', 'cost', 'start_date', 'completion_date'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
|
||||
public function getCompanyableParents()
|
||||
{
|
||||
return [ 'asset' ];
|
||||
|
@ -139,30 +157,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
|||
* -----------------------------------------------
|
||||
* BEGIN QUERY SCOPES
|
||||
* -----------------------------------------------
|
||||
**/
|
||||
|
||||
**/
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('asset_maintenances.title', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('asset_maintenances.notes', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('asset_maintenances.asset_maintenance_type', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('asset_maintenances.cost', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('asset_maintenances.start_date', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('asset_maintenances.completion_date', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on admin user
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace App\Models;
|
|||
|
||||
use App\Models\Requestable;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
@ -68,6 +69,26 @@ class AssetModel extends SnipeModel
|
|||
'user_id',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'model_number', 'notes', 'eol'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'depreciation' => ['name'],
|
||||
'category' => ['name'],
|
||||
'manufacturer' => ['name'],
|
||||
];
|
||||
|
||||
public function assets()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Asset', 'model_id');
|
||||
|
@ -160,38 +181,7 @@ class AssetModel extends SnipeModel
|
|||
{
|
||||
|
||||
return $query->where('requestable', '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where('models.name', 'LIKE', "%$search%")
|
||||
->orWhere('model_number', 'LIKE', "%$search%")
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('depreciation', function ($query) use ($search) {
|
||||
$query->where('depreciations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('category', function ($query) use ($search) {
|
||||
$query->where('categories.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('manufacturer', function ($query) use ($search) {
|
||||
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text, including catgeory and manufacturer name
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace App\Models;
|
|||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
@ -63,6 +64,21 @@ class Category extends SnipeModel
|
|||
'user_id',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'category_type'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
public function has_models()
|
||||
{
|
||||
|
@ -143,22 +159,4 @@ class Category extends SnipeModel
|
|||
|
||||
return $query->where('require_acceptance', '=', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('category_type', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Auth;
|
||||
use DB;
|
||||
|
@ -35,6 +36,21 @@ final class Company extends SnipeModel
|
|||
protected $injectUniqueIdentifier = true;
|
||||
use ValidatingTrait;
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
@ -192,20 +208,4 @@ final class Company extends SnipeModel
|
|||
{
|
||||
return $this->hasMany(Component::class, 'company_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -67,6 +68,26 @@ class Component extends SnipeModel
|
|||
'serial',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'order_number', 'serial', 'purchase_cost', 'purchase_date'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'category' => ['name'],
|
||||
'company' => ['name'],
|
||||
'location' => ['name'],
|
||||
];
|
||||
|
||||
public function location()
|
||||
{
|
||||
return $this->belongsTo('\App\Models\Location', 'location_id');
|
||||
|
@ -114,49 +135,7 @@ class Component extends SnipeModel
|
|||
$total = $this->qty;
|
||||
$remaining = $total - $checkedout;
|
||||
return $remaining;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
$search = explode(' ', $search);
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
foreach ($search as $search) {
|
||||
$query->whereHas('category', function ($query) use ($search) {
|
||||
$query->where('categories.name', 'LIKE', '%'.$search.'%');
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('company', function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('location', function ($query) use ($search) {
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere('components.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.serial', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.purchase_cost', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on company
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -68,6 +69,27 @@ class Consumable extends SnipeModel
|
|||
'requestable'
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'category' => ['name'],
|
||||
'company' => ['name'],
|
||||
'location' => ['name'],
|
||||
'manufacturer' => ['name'],
|
||||
];
|
||||
|
||||
public function setRequestableAttribute($value)
|
||||
{
|
||||
if ($value == '') {
|
||||
|
@ -163,50 +185,6 @@ class Consumable extends SnipeModel
|
|||
return $remaining;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
$search = explode(' ', $search);
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
foreach ($search as $search) {
|
||||
$query->whereHas('category', function ($query) use ($search) {
|
||||
$query->where('categories.name', 'LIKE', '%'.$search.'%');
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('company', function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('location', function ($query) use ($search) {
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('manufacturer', function ($query) use ($search) {
|
||||
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere('consumables.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('consumables.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('consumables.purchase_cost', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Searchable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Log;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -45,6 +46,22 @@ class Department extends SnipeModel
|
|||
'notes',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'notes'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
|
||||
public function company()
|
||||
{
|
||||
|
@ -76,23 +93,7 @@ class Department extends SnipeModel
|
|||
{
|
||||
return $this->belongsTo('\App\Models\Location', 'location_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextsearch($query, $search)
|
||||
{
|
||||
return $query->where('name', 'LIKE', "%$search%")
|
||||
->orWhere('notes', 'LIKE', "%$search%");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on location name
|
||||
*
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
|
@ -31,6 +32,21 @@ class Depreciation extends SnipeModel
|
|||
*/
|
||||
protected $fillable = ['name','months'];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'months'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
|
||||
public function has_models()
|
||||
|
@ -41,23 +57,5 @@ class Depreciation extends SnipeModel
|
|||
public function has_licenses()
|
||||
{
|
||||
return $this->hasMany('\App\Models\License', 'depreciation_id')->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('months', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\Traits\Searchable;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Group extends SnipeModel
|
||||
|
@ -22,6 +23,21 @@ class Group extends SnipeModel
|
|||
protected $injectUniqueIdentifier = true;
|
||||
use ValidatingTrait;
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'created_at'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
/**
|
||||
* Get user groups
|
||||
|
@ -36,21 +52,4 @@ class Group extends SnipeModel
|
|||
{
|
||||
return json_decode($this->permissions, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use App\Models\Actionlog;
|
|||
use App\Models\Company;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
|
@ -35,7 +36,9 @@ class License extends Depreciable
|
|||
'created_at',
|
||||
'updated_at',
|
||||
'deleted_at',
|
||||
'purchase_date'
|
||||
'purchase_date',
|
||||
'expiration_date',
|
||||
'termination_date'
|
||||
];
|
||||
|
||||
|
||||
|
@ -81,6 +84,34 @@ class License extends Depreciable
|
|||
'user_id',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = [
|
||||
'name',
|
||||
'serial',
|
||||
'notes',
|
||||
'order_number',
|
||||
'purchase_order',
|
||||
'purchase_cost',
|
||||
'purchase_date',
|
||||
'expiration_date',
|
||||
];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'manufacturer' => ['name'],
|
||||
'company' => ['name'],
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
@ -414,39 +445,6 @@ class License extends Depreciable
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('licenses.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.serial', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.notes', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.purchase_order', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.purchase_date', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.purchase_cost', 'LIKE', '%'.$search.'%')
|
||||
->orWhereHas('manufacturer', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
->orWhereHas('company', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on manufacturer
|
||||
*
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Models;
|
|||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Asset;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Models\User;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
@ -60,6 +61,24 @@ class Location extends SnipeModel
|
|||
];
|
||||
protected $hidden = ['user_id'];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'address', 'city', 'state', 'zip', 'created_at'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'parent' => ['name']
|
||||
];
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->hasMany('\App\Models\User', 'location_id');
|
||||
|
@ -171,39 +190,6 @@ class Location extends SnipeModel
|
|||
return $location_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextsearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where('name', 'LIKE', "%$search%")
|
||||
->orWhere('address', 'LIKE', "%$search%")
|
||||
->orWhere('city', 'LIKE', "%$search%")
|
||||
->orWhere('state', 'LIKE', "%$search%")
|
||||
->orWhere('zip', 'LIKE', "%$search%")
|
||||
|
||||
// This doesn't actually work - need to use a table alias maybe?
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('parent', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
// Ugly, ugly code because Laravel sucks at self-joins
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereRaw("parent_id IN (select id from ".DB::getTablePrefix()."locations where name LIKE '%".$search."%') ");
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on parent
|
||||
*
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -47,6 +48,22 @@ class Manufacturer extends SnipeModel
|
|||
'url',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'created_at'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
|
||||
|
||||
public function has_models()
|
||||
|
@ -78,21 +95,4 @@ class Manufacturer extends SnipeModel
|
|||
{
|
||||
return $this->hasMany('\App\Models\Consumable', 'manufacturer_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace App\Models;
|
|||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\Traits\Searchable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -35,6 +36,22 @@ class Statuslabel extends SnipeModel
|
|||
'pending',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
|
||||
/**
|
||||
* Get assets with associated status label
|
||||
|
@ -108,21 +125,4 @@ class Statuslabel extends SnipeModel
|
|||
|
||||
return $statustype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace App\Models;
|
|||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\Traits\Searchable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
@ -40,6 +41,23 @@ class Supplier extends SnipeModel
|
|||
use ValidatingTrait;
|
||||
use UniqueUndeletedTrait;
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
|
@ -104,21 +122,4 @@ class Supplier extends SnipeModel
|
|||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
238
app/Models/Traits/Searchable.php
Normal file
238
app/Models/Traits/Searchable.php
Normal file
|
@ -0,0 +1,238 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Traits;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
* This trait allows for cleaner searching of models,
|
||||
* moving from complex queries to an easier declarative syntax.
|
||||
*
|
||||
* @author Till Deeke <kontakt@tilldeeke.de>
|
||||
*/
|
||||
trait Searchable {
|
||||
|
||||
/**
|
||||
* Performs a search on the model, using the provided search terms
|
||||
*
|
||||
* @param Illuminate\Database\Eloquent\Builder $query The query to start the search on
|
||||
* @param string $search
|
||||
* @return Illuminate\Database\Eloquent\Builder A query with added "where" clauses
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
$terms = $this->prepeareSearchTerms($search);
|
||||
|
||||
foreach($terms as $term) {
|
||||
|
||||
/**
|
||||
* Search the attributes of this model
|
||||
*/
|
||||
$query = $this->searchAttributes($query, $term);
|
||||
|
||||
/**
|
||||
* Search through the custom fields of the model
|
||||
*/
|
||||
$query = $this->searchCustomFields($query, $term);
|
||||
|
||||
/**
|
||||
* Search through the relations of the model
|
||||
*/
|
||||
$query = $this->searchRelations($query, $term);
|
||||
|
||||
/**
|
||||
* Search for additional attributes defined by the model
|
||||
*/
|
||||
$query = $this->advancedTextSearch($query, $term);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the search term, splitting and cleaning it up
|
||||
* @param string $search The search term
|
||||
* @return array An array of search terms
|
||||
*/
|
||||
private function prepeareSearchTerms(string $search) {
|
||||
return explode(' OR ', $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the models attributes for the search term
|
||||
*
|
||||
* @param Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $term
|
||||
* @return Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
private function searchAttributes(Builder $query, string $term) {
|
||||
|
||||
foreach($this->getSearchableAttributes() as $column) {
|
||||
|
||||
/**
|
||||
* Making sure to only search in date columns if the search term consists of characters that can make up a MySQL timestamp!
|
||||
*
|
||||
* @see https://github.com/snipe/snipe-it/issues/4590
|
||||
*/
|
||||
if (!preg_match('/^[0-9 :-]++$/', $term) && in_array($column, $this->getDates())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$table = $this->getTable();
|
||||
|
||||
$query = $query->orWhere($table . '.' . $column, 'LIKE', '%'.$term.'%');
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the models custom fields for the search term
|
||||
*
|
||||
* @param Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $term
|
||||
* @return Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
private function searchCustomFields(Builder $query, string $term) {
|
||||
|
||||
/**
|
||||
* If we are searching on something other that an asset, skip custom fields.
|
||||
*/
|
||||
if (! $this instanceof Asset) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
foreach (CustomField::all() as $field) {
|
||||
$query->orWhere($this->getTable() . '.'. $field->db_column_name(), 'LIKE', '%'.$term.'%');
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the models relations for the search term
|
||||
*
|
||||
* @param Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $term
|
||||
* @return Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
private function searchRelations(Builder $query, string $term) {
|
||||
|
||||
foreach($this->getSearchableRelations() as $relation => $columns) {
|
||||
|
||||
/**
|
||||
* Make the columns into a collection,
|
||||
* for easier handling further down
|
||||
*
|
||||
* @var Illuminate\Support\Collection
|
||||
*/
|
||||
$columns = collect($columns);
|
||||
|
||||
$query = $query->orWhereHas($relation, function($query) use ($relation, $columns, $term) {
|
||||
|
||||
$table = $this->getRelationTable($relation);
|
||||
|
||||
/**
|
||||
* We need to form the query properly, starting with a "where",
|
||||
* otherwise the generated nested select is wrong.
|
||||
*
|
||||
* We can just choose the last column, since they all get "and where"d in the end.
|
||||
* (And because using pop saves us from handling the removal of the first element)
|
||||
*/
|
||||
$last = $columns->pop();
|
||||
$query->where($table . '.' . $last, 'LIKE', '%'.$term.'%');
|
||||
|
||||
foreach($columns as $column) {
|
||||
$query->orWhere($table . '.' . $column, 'LIKE', '%'.$term.'%');
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run additional, advanced searches that can't be done using the attributes or relations.
|
||||
*
|
||||
* This is a noop in this trait, but can be overridden in the implementing model, to allow more advanced searches
|
||||
*
|
||||
* @param Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $term The search term
|
||||
* @return Illuminate\Database\Eloquent\Builder
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function advancedTextSearch(Builder $query, string $term) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the searchable attributes, if defined. Otherwise it returns an empty array
|
||||
*
|
||||
* @return array The attributes to search in
|
||||
*/
|
||||
private function getSearchableAttributes() {
|
||||
return isset($this->searchableAttributes) ? $this->searchableAttributes : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the searchable relations, if defined. Otherwise it returns an empty array
|
||||
*
|
||||
* @return array The relations to search in
|
||||
*/
|
||||
private function getSearchableRelations() {
|
||||
return isset($this->searchableRelations) ? $this->searchableRelations : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table name of a relation.
|
||||
*
|
||||
* This method loops over a relation name,
|
||||
* getting the table name of the last relation in the series.
|
||||
* So "category" would get the table name for the Category model,
|
||||
* "model.manufacturer" would get the tablename for the Manufacturer model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @return string The table name
|
||||
*/
|
||||
private function getRelationTable($relation) {
|
||||
$related = $this;
|
||||
|
||||
foreach(explode('.', $relation) as $relationName) {
|
||||
$related = $related->{$relationName}()->getRelated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we referencing the model that called?
|
||||
* Then get the internal join-tablename, since laravel
|
||||
* has trouble selecting the correct one in this type of
|
||||
* parent-child self-join.
|
||||
*
|
||||
* @todo Does this work with deeply nested resources? Like "category.assets.model.category" or something like that?
|
||||
*/
|
||||
if ($this instanceof $related) {
|
||||
|
||||
/**
|
||||
* Since laravel increases the counter on the hash on retrieval, we have to count it down again.
|
||||
*
|
||||
* This causes side effects! Every time we access this method, laravel increases the counter!
|
||||
*
|
||||
* Format: laravel_reserved_XXX
|
||||
*/
|
||||
$relationCountHash = $this->{$relationName}()->getRelationCountHash();
|
||||
|
||||
$parts = collect(explode('_', $relationCountHash));
|
||||
|
||||
$counter = $parts->pop();
|
||||
|
||||
$parts->push($counter - 1);
|
||||
|
||||
return implode('_', $parts->toArray());
|
||||
}
|
||||
|
||||
return $related->getTable();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Auth\Authenticatable;
|
||||
use Illuminate\Auth\Passwords\CanResetPassword;
|
||||
|
@ -9,6 +10,7 @@ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
|||
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
|
||||
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
@ -68,6 +70,35 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
|||
'locale' => 'max:10|nullable',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'username',
|
||||
'notes',
|
||||
'phone',
|
||||
'jobtitle',
|
||||
'employee_num'
|
||||
];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
'userloc' => ['name'],
|
||||
'department' => ['name'],
|
||||
'groups' => ['name'],
|
||||
'manager' => ['first_name', 'last_name', 'username']
|
||||
];
|
||||
|
||||
public function hasAccess($section)
|
||||
{
|
||||
|
@ -405,6 +436,19 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
|||
return json_decode($this->permissions, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run additional, advanced searches.
|
||||
*
|
||||
* @param Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $term The search term
|
||||
* @return Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function advancedTextSearch(Builder $query, string $term) {
|
||||
$query = $query->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$term%", "%$term%"]);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
public function scopeByGroup($query, $id) {
|
||||
return $query->whereHas('groups', function ($query) use ($id) {
|
||||
|
@ -412,55 +456,6 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextsearch($query, $search)
|
||||
{
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
$query->where('users.first_name', 'LIKE', "%$search%")
|
||||
->orWhere('users.last_name', 'LIKE', "%$search%")
|
||||
->orWhere('users.email', 'LIKE', "%$search%")
|
||||
->orWhere('users.username', 'LIKE', "%$search%")
|
||||
->orWhere('users.notes', 'LIKE', "%$search%")
|
||||
->orWhere('users.phone', 'LIKE', "%$search%")
|
||||
->orWhere('users.jobtitle', 'LIKE', "%$search%")
|
||||
->orWhere('users.employee_num', 'LIKE', "%$search%")
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$search%", "%$search%"])
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('userloc', function ($query) use ($search) {
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('department', function ($query) use ($search) {
|
||||
$query->where('departments.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('groups', function ($query) use ($search) {
|
||||
$query->where('groups.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
|
||||
//Ugly, ugly code because Laravel sucks at self-joins
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereRaw(DB::getTablePrefix()."users.manager_id IN (select id from ".DB::getTablePrefix()."users where first_name LIKE ? OR last_name LIKE ?)", ["%$search%", "%$search%"]);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope for Deleted users
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue