vuongxuongminh /
yii2-searchable
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * @link https://github.com/vuongxuongminh/yii2-searchable |
||
| 4 | * @copyright Copyright (c) 2019 Vuong Xuong Minh |
||
| 5 | * @license [New BSD License](http://www.opensource.org/licenses/bsd-license.php) |
||
| 6 | */ |
||
| 7 | |||
| 8 | namespace vxm\searchable; |
||
| 9 | |||
| 10 | use Yii; |
||
| 11 | |||
| 12 | use yii\db\ActiveQueryInterface; |
||
| 13 | use yii\db\Exception; |
||
| 14 | |||
| 15 | use vxm\searchable\expression\Condition; |
||
| 16 | use vxm\searchable\expression\ConditionBuilder; |
||
| 17 | use vxm\searchable\expression\OrderBy; |
||
| 18 | use vxm\searchable\expression\OrderByBuilder; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * Trait SearchableTrait support implementing full-text search for the active record classes. |
||
| 22 | * |
||
| 23 | * @author Vuong Minh <[email protected]> |
||
| 24 | * @since 1.0.0 |
||
| 25 | */ |
||
| 26 | trait SearchableTrait |
||
| 27 | { |
||
| 28 | |||
| 29 | /** |
||
| 30 | * @inheritDoc |
||
| 31 | * @return \yii\db\Connection |
||
| 32 | */ |
||
| 33 | abstract public static function getDb(); |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @inheritDoc |
||
| 37 | * @return string |
||
| 38 | */ |
||
| 39 | abstract public static function tableName(); |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @inheritDoc |
||
| 43 | * @return mixed |
||
| 44 | */ |
||
| 45 | abstract public static function primaryKey(); |
||
| 46 | |||
| 47 | /** |
||
| 48 | * @inheritDoc |
||
| 49 | * @return \yii\db\ActiveQuery|\yii\db\ActiveQueryInterface |
||
| 50 | */ |
||
| 51 | abstract public static function find(); |
||
| 52 | |||
| 53 | /** |
||
| 54 | * Get searchable support full-text search for this model class. |
||
| 55 | * |
||
| 56 | * @return object|Searchable |
||
| 57 | * @throws \yii\base\InvalidConfigException |
||
| 58 | */ |
||
| 59 | 12 | public static function getSearchable(): Searchable |
|
| 60 | { |
||
| 61 | 12 | return Yii::$app->get('searchable'); |
|
| 62 | } |
||
| 63 | |||
| 64 | /** |
||
| 65 | * Creating active query had been apply search ids condition by given query string. |
||
| 66 | * |
||
| 67 | * @param string $query to search data. |
||
| 68 | * @param string $mode using for query search, [[\vxm\searchable\Searchable::BOOLEAN_SEARCH]] or [[\vxm\searchable\Searchable::FUZZY_SEARCH]]. |
||
| 69 | * If not set [[\vxm\searchable\Searchable::$defaultSearchMode]] will be use. |
||
| 70 | * @param array $config of [[\vxm\searchable\TNTSearch]]. |
||
| 71 | * @return \yii\db\ActiveQuery|ActiveQueryInterface query instance. |
||
| 72 | * @throws \TeamTNT\TNTSearch\Exceptions\IndexNotFoundException |
||
| 73 | * @throws \yii\base\InvalidConfigException |
||
| 74 | */ |
||
| 75 | 6 | public static function search(string $query, ?string $mode = null, array $config = []): ActiveQueryInterface |
|
| 76 | { |
||
| 77 | 6 | $ids = static::searchIds($query, $mode, $config); |
|
| 78 | /** @var \yii\db\ActiveQuery $aq */ |
||
| 79 | 6 | $aq = static::find(); |
|
| 80 | |||
| 81 | 6 | if (empty($ids)) { |
|
| 82 | |||
| 83 | 3 | $aq->andWhere('1 = 0'); |
|
| 84 | } else { |
||
| 85 | /** @var \yii\db\Connection $db */ |
||
| 86 | 4 | $db = static::getDb(); |
|
| 87 | 4 | $db->setQueryBuilder([ |
|
| 88 | 4 | 'expressionBuilders' => [ |
|
| 89 | Condition::class => ConditionBuilder::class, |
||
| 90 | OrderBy::class => OrderByBuilder::class |
||
| 91 | ] |
||
| 92 | ]); |
||
| 93 | $expressionConfig = [ |
||
| 94 | 4 | 'query' => $aq, |
|
| 95 | 4 | 'ids' => $ids |
|
| 96 | ]; |
||
| 97 | 4 | $condition = new Condition($expressionConfig); |
|
| 98 | 4 | $orderBy = new OrderBy($expressionConfig); |
|
| 99 | 4 | $aq->andWhere($condition); |
|
| 100 | 4 | $aq->addOrderBy($orderBy); |
|
| 101 | } |
||
| 102 | |||
| 103 | 6 | return $aq; |
|
| 104 | } |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Search ids by given query string. |
||
| 108 | * |
||
| 109 | * @param string $query to search data. |
||
| 110 | * @param string|null $mode using for query search, [[\vxm\searchable\Searchable::BOOLEAN_SEARCH]] or [[\vxm\searchable\Searchable::FUZZY_SEARCH]]. |
||
| 111 | * If not set [[\vxm\searchable\Searchable::$defaultSearchMode]] will be use. |
||
| 112 | * @param array $config of [[\vxm\searchable\TNTSearch]]. |
||
| 113 | * @return array search key values of indexing data search. |
||
| 114 | * @throws \TeamTNT\TNTSearch\Exceptions\IndexNotFoundException |
||
| 115 | * @throws \yii\base\InvalidConfigException |
||
| 116 | */ |
||
| 117 | 8 | public static function searchIds(string $query, ?string $mode = null, array $config = []): array |
|
| 118 | { |
||
| 119 | 8 | $profileToken = "Searching data via query: `{$query}`"; |
|
| 120 | 8 | Yii::beginProfile($profileToken); |
|
| 121 | |||
| 122 | try { |
||
| 123 | 8 | $result = static::getSearchable()->search(static::class, $query, $mode, $config); |
|
| 124 | |||
| 125 | 8 | return $result['ids']; |
|
| 126 | } finally { |
||
| 127 | |||
| 128 | 8 | Yii::endProfile($profileToken); |
|
| 129 | } |
||
| 130 | } |
||
| 131 | |||
| 132 | /** |
||
| 133 | * Delete all instances of the model from the search index. |
||
| 134 | * |
||
| 135 | * @throws \yii\base\InvalidConfigException |
||
| 136 | */ |
||
| 137 | 5 | public static function deleteAllFromSearch(): void |
|
| 138 | { |
||
| 139 | 5 | static::getSearchable()->deleteAllFromSearch(static::class); |
|
| 140 | 5 | } |
|
| 141 | |||
| 142 | /** |
||
| 143 | * Enable search syncing for this model class. |
||
| 144 | */ |
||
| 145 | 2 | public static function enableSearchSyncing(): void |
|
| 146 | { |
||
| 147 | 2 | SearchableBehavior::enableSyncingFor(static::class); |
|
| 148 | 2 | } |
|
| 149 | |||
| 150 | /** |
||
| 151 | * Disable search syncing for this model class. |
||
| 152 | */ |
||
| 153 | 2 | public static function disableSearchSyncing(): void |
|
| 154 | { |
||
| 155 | 2 | SearchableBehavior::disableSyncingFor(static::class); |
|
| 156 | 2 | } |
|
| 157 | |||
| 158 | /** |
||
| 159 | * Temporarily disable search syncing for the given callback. |
||
| 160 | * |
||
| 161 | * @param callable $callback will be call without syncing mode. |
||
| 162 | * @return mixed value of $callback. |
||
| 163 | */ |
||
| 164 | 2 | public static function withoutSyncingToSearch($callback) |
|
| 165 | { |
||
| 166 | 2 | static::disableSearchSyncing(); |
|
| 167 | |||
| 168 | try { |
||
| 169 | 2 | return $callback(); |
|
| 170 | } finally { |
||
| 171 | 2 | static::enableSearchSyncing(); |
|
| 172 | } |
||
| 173 | } |
||
| 174 | |||
| 175 | /** |
||
| 176 | * Make given model searchable. |
||
| 177 | * |
||
| 178 | * @param \yii\db\ActiveRecord|\yii\db\ActiveRecord[]|static|static[] $models add to searchable index data. |
||
| 179 | * @throws \TeamTNT\TNTSearch\Exceptions\IndexNotFoundException |
||
| 180 | * @throws \yii\base\InvalidConfigException |
||
| 181 | */ |
||
| 182 | 10 | public static function makeSearchable($models): void |
|
| 183 | { |
||
| 184 | 10 | static::getSearchable()->queueMakeSearchable($models); |
|
| 185 | 10 | } |
|
| 186 | |||
| 187 | /** |
||
| 188 | * Delete given model searchable. |
||
| 189 | * |
||
| 190 | * @param \yii\db\ActiveRecord|\yii\db\ActiveRecord[]|static|static[] $models delete from searchable index data. |
||
| 191 | * @throws \TeamTNT\TNTSearch\Exceptions\IndexNotFoundException |
||
| 192 | * @throws \yii\base\InvalidConfigException |
||
| 193 | */ |
||
| 194 | 3 | public static function deleteSearchable($models): void |
|
| 195 | { |
||
| 196 | 3 | static::getSearchable()->queueDeleteFromSearch($models); |
|
| 197 | 3 | } |
|
| 198 | |||
| 199 | /** |
||
| 200 | * Make all instances of the model searchable. |
||
| 201 | * |
||
| 202 | * @throws \TeamTNT\TNTSearch\Exceptions\IndexNotFoundException |
||
| 203 | * @throws \yii\base\InvalidConfigException |
||
| 204 | */ |
||
| 205 | 7 | public static function makeAllSearchable(): void |
|
| 206 | { |
||
| 207 | 7 | foreach (static::find()->orderBy(static::searchableKey())->batch() as $models) { |
|
| 208 | 7 | static::makeSearchable($models); |
|
| 209 | } |
||
| 210 | 7 | } |
|
| 211 | |||
| 212 | /** |
||
| 213 | * Get the index name for the model. |
||
| 214 | * |
||
| 215 | * @return string the name of an index. |
||
| 216 | */ |
||
| 217 | 12 | public static function searchableIndex(): string |
|
| 218 | { |
||
| 219 | 12 | return static::getDb()->quoteSql(static::tableName()); |
|
| 220 | } |
||
| 221 | |||
| 222 | /** |
||
| 223 | * Get the indexable data array for the model. |
||
| 224 | * |
||
| 225 | * @return array ['field' => 'value'] or ['field alias' => 'value']. |
||
| 226 | */ |
||
| 227 | 10 | public function toSearchableArray(): array |
|
| 228 | { |
||
| 229 | 10 | return $this->toArray(); |
|
|
0 ignored issues
–
show
|
|||
| 230 | } |
||
| 231 | |||
| 232 | /** |
||
| 233 | * Get searchable key by default primary key will be use. |
||
| 234 | * |
||
| 235 | * @return string key name. |
||
| 236 | */ |
||
| 237 | 11 | public static function searchableKey(): string |
|
| 238 | { |
||
| 239 | 11 | return current(static::primaryKey()); |
|
| 240 | } |
||
| 241 | |||
| 242 | /** |
||
| 243 | * Determine if the model should be searchable. |
||
| 244 | * |
||
| 245 | * @return bool weather instance should be insert to searchable index data. |
||
| 246 | */ |
||
| 247 | public function shouldBeSearchable(): bool |
||
| 248 | { |
||
| 249 | return true; |
||
| 250 | } |
||
| 251 | |||
| 252 | /** |
||
| 253 | * Make the given model instance searchable. |
||
| 254 | * |
||
| 255 | * @throws \TeamTNT\TNTSearch\Exceptions\IndexNotFoundException |
||
| 256 | * @throws \yii\base\InvalidConfigException |
||
| 257 | */ |
||
| 258 | 4 | public function searchable(): void |
|
| 259 | { |
||
| 260 | 4 | static::makeSearchable($this); |
|
| 261 | 4 | } |
|
| 262 | |||
| 263 | /** |
||
| 264 | * Remove the given model instance from the search index. |
||
| 265 | * |
||
| 266 | * @throws \TeamTNT\TNTSearch\Exceptions\IndexNotFoundException |
||
| 267 | * @throws \yii\base\InvalidConfigException |
||
| 268 | */ |
||
| 269 | 3 | public function unsearchable(): void |
|
| 270 | { |
||
| 271 | 3 | static::deleteSearchable($this); |
|
| 272 | 3 | } |
|
| 273 | |||
| 274 | /** |
||
| 275 | * Get searchable key value by default the primary key will be use. |
||
| 276 | * |
||
| 277 | * @param bool $asArray weather return an array have a key is a searchable key and value is an value of key or only value. |
||
| 278 | * @return string|int|string[]|int[] value of an searchable key. |
||
| 279 | * @throws Exception |
||
| 280 | */ |
||
| 281 | 11 | public function getSearchableKey(bool $asArray = false) |
|
| 282 | { |
||
| 283 | 11 | $key = static::searchableKey(); |
|
| 284 | |||
| 285 | 11 | if ($asArray) { |
|
| 286 | return [$key => $this->$key]; |
||
| 287 | } else { |
||
| 288 | 11 | return $this->$key; |
|
| 289 | } |
||
| 290 | } |
||
| 291 | |||
| 292 | } |
||
| 293 |
This check looks for methods that are used by a trait but not required by it.
To illustrate, let’s look at the following code example
The trait
Idableprovides a methodequalsIdthat in turn relies on the methodgetId(). If this method does not exist on a class mixing in this trait, the method will fail.Adding the
getId()as an abstract method to the trait will make sure it is available.