PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.11.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.11.0
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
fluent-community / vendor / wpfluent / framework / src / WPFluent / Database / Orm / Searchable.php

Searchable.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.11.0, 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 FluentCommunity\Framework\Database\Orm;
4
5 use Exception;
6 use FluentCommunity\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 \FluentCommunity\Framework\Database\Orm\Builder $query
25 * @param string $value
26 * @return \FluentCommunity\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 \FluentCommunity\Framework\Database\Orm\Builder $query
48 * @param string $value
49 * @return \FluentCommunity\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 \FluentCommunity\Framework\Database\Orm\Builder $query
76 * @param string $value
77 * @param bool $fuzzy
78 * @return \FluentCommunity\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