This commit is contained in:
2024-09-01 18:54:23 +05:00
parent 76d18365a5
commit 061f09eca1
1597 changed files with 109451 additions and 1 deletions

View File

@@ -0,0 +1,89 @@
<?php
namespace Laravel\Nova\Query\Search;
use Illuminate\Database\Query\Expression;
class Column
{
/**
* The search column.
*
* @var \Illuminate\Database\Query\Expression|string
*/
public $column;
/**
* Construct a new search.
*
* @param \Illuminate\Database\Query\Expression|string $column
* @return void
*/
public function __construct($column)
{
$this->column = $column;
}
/**
* Create Column instance for raw expression value.
*
* @param string $column
* @return mixed
*/
public static function raw($column)
{
return new static(new Expression($column));
}
/**
* Create Column instance from raw expression or fluent string.
*
* @param \Illuminate\Database\Query\Expression|string $column
* @return mixed
*/
public static function from($column)
{
if ($column instanceof Expression) {
return new static($column);
}
if (strpos($column, '->') !== false) {
return new SearchableJson($column);
} elseif (strpos($column, '.') !== false) {
[$relation, $columnName] = explode('.', $column, 2);
return new SearchableRelation($relation, $columnName);
}
return new static($column);
}
/**
* Apply the search.
*
* @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query
* @param string $search
* @param string $connectionType
* @param string $whereOperator
* @return \Illuminate\Database\Eloquent\Builder
*/
public function __invoke($query, $search, string $connectionType, string $whereOperator = 'orWhere')
{
return $query->{$whereOperator}(
$this->columnName($query),
$connectionType == 'pgsql' ? 'ilike' : 'like',
"%{$search}%"
);
}
/**
* Get the column name.
*
* @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query
* @return string
*/
protected function columnName($query)
{
return $this->column instanceof Expression ? $this->column : $query->qualifyColumn($this->column);
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Laravel\Nova\Query\Search;
class PrimaryKey extends Column
{
/**
* Max primary key size.
*
* @var int
*/
protected $maxPrimaryKeySize;
/**
* Construct a new search.
*
* @param \Illuminate\Database\Query\Expression|string $column
* @param int $maxPrimaryKeySize
* @return void
*/
public function __construct($column, $maxPrimaryKeySize = PHP_INT_MAX)
{
$this->column = $column;
$this->maxPrimaryKeySize = $maxPrimaryKeySize;
}
/**
* Apply the search.
*
* @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query
* @param string|int $search
* @param string $connectionType
* @param string $whereOperator
* @return \Illuminate\Database\Eloquent\Builder
*/
public function __invoke($query, $search, string $connectionType, string $whereOperator = 'orWhere')
{
$model = $query->getModel();
$canSearchPrimaryKey = ctype_digit($search) &&
in_array($model->getKeyType(), ['int', 'integer']) &&
($connectionType != 'pgsql' || $search <= $this->maxPrimaryKeySize);
if (! $canSearchPrimaryKey) {
return parent::__invoke($query, $search, $connectionType, $whereOperator);
}
return $query->{$whereOperator}($model->getQualifiedKeyName(), $search);
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Laravel\Nova\Query\Search;
use Illuminate\Support\Str;
class SearchableJson extends Column
{
/**
* The search JSON seletor path.
*
* @var \Illuminate\Database\Query\Expression|string
*/
public $jsonSelectorPath;
/**
* Construct a new search.
*
* @param \Illuminate\Database\Query\Expression|string $jsonSelectorPath
* @return void
*/
public function __construct($jsonSelectorPath)
{
$this->jsonSelectorPath = $jsonSelectorPath;
}
/**
* Apply the search.
*
* @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query
* @param string $search
* @param string $connectionType
* @param string $whereOperator
* @return \Illuminate\Database\Eloquent\Builder
*/
public function __invoke($query, $search, string $connectionType, string $whereOperator = 'orWhere')
{
$path = $query->getGrammar()->wrap($this->jsonSelectorPath);
$likeOperator = $connectionType == 'pgsql' ? 'ilike' : 'like';
if (in_array($connectionType, ['pgsql', 'sqlite'])) {
return $query->{$whereOperator}($this->jsonSelectorPath, $likeOperator, "%{$search}%");
}
return $query->{$whereOperator.'Raw'}("lower({$path}) {$likeOperator} ?", ['%'.Str::lower($search).'%']);
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Laravel\Nova\Query\Search;
class SearchableMorphToRelation extends SearchableRelation
{
/**
* The available morph types.
*
* @var array<int, class-string<\Illuminate\Database\Eloquent\Model|\Laravel\Nova\Resource>|string>
*/
public $types = [];
/**
* Construct a new search.
*
* @param string $relation
* @param \Illuminate\Database\Query\Expression|string $column
* @param array<int, class-string<\Illuminate\Database\Eloquent\Model|\Laravel\Nova\Resource>|string> $types
* @return void
*/
public function __construct(string $relation, $column, array $types = [])
{
$this->types = $types;
parent::__construct($relation, $column);
}
/**
* Apply the search.
*
* @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query
* @param string $search
* @param string $connectionType
* @param string $whereOperator
* @return \Illuminate\Database\Eloquent\Builder
*/
public function __invoke($query, $search, string $connectionType, string $whereOperator = 'orWhere')
{
return $query->{$whereOperator.'HasMorph'}($this->relation, $this->morphTypes(), function ($query) use ($search, $connectionType) {
return Column::from($this->column)->__invoke(
$query, $search, $connectionType, 'where'
);
});
}
/**
* Get available morph types.
*
* @return array<int, class-string<\Illuminate\Database\Eloquent\Model>|string>|string
*/
protected function morphTypes()
{
if (empty($this->types)) {
return '*';
}
return collect($this->types)
->map(function ($resource) {
return $resource::$model ?? $resource;
})->all();
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Laravel\Nova\Query\Search;
class SearchableRelation extends Column
{
/**
* The relationship name.
*
* @var string
*/
public $relation;
/**
* Construct a new search.
*
* @param string $relation
* @param \Illuminate\Database\Query\Expression|string $column
* @return void
*/
public function __construct(string $relation, $column)
{
$this->relation = $relation;
parent::__construct($column);
}
/**
* Apply the search.
*
* @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query
* @param string $search
* @param string $connectionType
* @param string $whereOperator
* @return \Illuminate\Database\Eloquent\Builder
*/
public function __invoke($query, $search, string $connectionType, string $whereOperator = 'orWhere')
{
return $query->{$whereOperator.'Has'}($this->relation, function ($query) use ($search, $connectionType) {
return Column::from($this->column)->__invoke(
$query, $search, $connectionType, 'where'
);
});
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Laravel\Nova\Query\Search;
class SearchableText extends Column
{
/**
* Apply the search.
*
* @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation $query
* @param string $search
* @param string $connectionType
* @param string $whereOperator
* @return \Illuminate\Database\Eloquent\Builder
*/
public function __invoke($query, $search, string $connectionType, string $whereOperator = 'orWhere')
{
if (in_array($connectionType, ['mysql', 'pgsql'])) {
$query->{$whereOperator.'FullText'}(
$this->columnName($query), $search
);
}
return $query;
}
}