PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / vendor / wpfluent / framework / src / WPFluent / Database / Orm / Searchable.php

Searchable.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at vendor/wpfluent/framework/src/WPFluent/Database/Orm/Searchable.php

141 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\Framework\Database\Orm;
4
5 use Exception;
6 use FluentCart\Framework\Database\Schema;
7
8 trait Searchable
9 {
10 /**
11 * The property is intentionally NOT declared on the trait. Declaring it
12 * here with a default would make any model that redeclares it with its
13 * own columns (protected $searchableColumns = [...]) an incompatible
14 * trait composition and fatal in PHP. Models simply declare the property
15 * themselves; getSearchableColumns() reads it and defaults to an empty
16 * array when a model leaves it unset.
17 *
18 * @var array
19 */
20
21 /**
22 * Search the model in a case-insensitive manner.
23 *
24 * @param \FluentCart\Framework\Database\Orm\Builder $query
25 * @param string $value
26 * @return \FluentCart\Framework\Database\Orm\Builder
27 * @throws \Exception
28 */
29 public function scopeSearch($query, $value)
30 {
31 $columns = $this->ensureSearchableColumns();
32
33 $value = strtolower($value);
34
35 return $query->where(function($query) use ($columns, $value) {
36 foreach ($columns as $column) {
37 $query->orWhereRaw(
38 'LOWER(' . $column . ') LIKE ?', ['%' . $value . '%']
39 );
40 }
41 });
42 }
43
44 /**
45 * Search the searchable columns phonetically (SOUNDEX / "sounds like").
46 *
47 * @param \FluentCart\Framework\Database\Orm\Builder $query
48 * @param string $value
49 * @return \FluentCart\Framework\Database\Orm\Builder
50 * @throws \Exception
51 */
52 public function scopeSoundsLike($query, $value)
53 {
54 $columns = $this->ensureSearchableColumns();
55
56 return $query->where(function($query) use ($columns, $value) {
57 foreach ($columns as $column) {
58 $query->orWhereSoundsLike($column, $value);
59 }
60 });
61 }
62
63 /**
64 * Search the searchable columns by full-text relevance, returning rows
65 * ranked by how well they match (a "relevance" column is added).
66 *
67 * On MySQL/MariaDB this uses native FULLTEXT ranking and requires a
68 * FULLTEXT index on the searchable columns (see Schema::fullText()). When
69 * $fuzzy is true, recall is widened with a phonetic ("sounds like") match
70 * so misspellings still surface (below the ranked hits).
71 *
72 * SQLite has no native FULLTEXT, so it degrades to a case-insensitive
73 * LIKE match across the columns (unranked).
74 *
75 * @param \FluentCart\Framework\Database\Orm\Builder $query
76 * @param string $value
77 * @param bool $fuzzy
78 * @return \FluentCart\Framework\Database\Orm\Builder
79 * @throws \Exception
80 */
81 public function scopeRelevanceSearch($query, $value, $fuzzy = false)
82 {
83 $columns = $this->ensureSearchableColumns();
84
85 if (Schema::isSqlite()) {
86 return $query->where(function($query) use ($columns, $value, $fuzzy) {
87 foreach ($columns as $column) {
88 $query->orWhereLike($column, $value);
89
90 if ($fuzzy) {
91 $query->orWhereSoundsLike($column, $value);
92 }
93 }
94 });
95 }
96
97 return $query
98 ->selectRelevance($columns, $value)
99 ->where(function($query) use ($columns, $value, $fuzzy) {
100 $query->whereFullText($columns, $value);
101
102 if ($fuzzy) {
103 foreach ($columns as $column) {
104 $query->orWhereSoundsLike($column, $value);
105 }
106 }
107 })
108 ->orderByRelevance();
109 }
110
111 /**
112 * Get the model's searchable columns, defaulting to an empty array when
113 * the model does not declare the $searchableColumns property.
114 *
115 * @return array
116 */
117 protected function getSearchableColumns()
118 {
119 return $this->searchableColumns ?? [];
120 }
121
122 /**
123 * Ensure searchable columns are defined on the model and return them.
124 *
125 * @return array
126 * @throws \Exception
127 */
128 protected function ensureSearchableColumns()
129 {
130 $columns = $this->getSearchableColumns();
131
132 if (empty($columns)) {
133 throw new Exception(
134 'No searchable columns were defined in ' . get_class($this) . '.'
135 );
136 }
137
138 return $columns;
139 }
140 }
141