Skip to content

Commit 9076242

Browse files
- Fix tests
1 parent 9ca22dc commit 9076242

File tree

1 file changed

+46
-47
lines changed

1 file changed

+46
-47
lines changed

src/Traits/HasEncryptedSearchIndex.php

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
/**
1313
* Trait HasEncryptedSearchIndex
1414
*
15-
* Adds automatic encrypted search indexing to Eloquent models.
15+
* Provides automatic encrypted search indexing for Eloquent models.
1616
*
17-
* When this trait is applied to a model, it maintains an associated
18-
* index table (`encrypted_search_index`) containing deterministic,
19-
* non-reversible tokens derived from selected model attributes.
17+
* When attached to a model, this trait builds and maintains a companion index
18+
* table (`encrypted_search_index`) that stores deterministic, non-reversible
19+
* search tokens derived from model attributes.
2020
*
21-
* The generated tokens make it possible to perform privacy-preserving
22-
* searches (exact or prefix-based) without exposing plaintext data.
21+
* These tokens enable privacy-preserving search queries (exact or prefix-based)
22+
* without revealing plaintext values in the database.
2323
*
2424
* Example usage:
2525
*
@@ -32,45 +32,46 @@
3232
* ];
3333
* }
3434
*
35-
* On every save or delete event:
36-
* - Tokens are created, updated, or removed in the `encrypted_search_index` table.
37-
* - Outdated tokens for the same record are automatically deleted.
35+
* On each save or delete:
36+
* - Tokens are (re)generated and stored in `encrypted_search_index`.
37+
* - Old entries for the record are automatically replaced or removed.
3838
*
39-
* Example search:
40-
* Client::encryptedExact('last_names', 'vermeer')->get();
41-
* Client::encryptedPrefix('first_names', 'wie')->get();
39+
* Search queries:
40+
*
41+
* Client::encryptedExact('last_names', 'vermeer')->get();
42+
* Client::encryptedPrefix('first_names', 'wie')->get();
4243
*/
4344
trait HasEncryptedSearchIndex
4445
{
4546
/**
4647
* Boot logic for the trait.
4748
*
4849
* Automatically updates or removes encrypted search tokens whenever
49-
* a model instance is created, updated, saved, deleted, or restored.
50+
* a model instance is saved, updated, deleted, or restored.
5051
*
5152
* @return void
5253
*/
5354
public static function bootHasEncryptedSearchIndex(): void
5455
{
55-
// Rebuild index when model is created, updated, or saved
56+
// Rebuild index when model is created, updated or saved
5657
foreach (['created', 'updated', 'saved'] as $event) {
57-
static::$event(function (Model $model): void {
58+
static::$event(function (Model $model) {
5859
$model->updateSearchIndex();
5960
});
6061
}
6162

62-
// Always remove tokens when a model is deleted
63-
static::deleted(fn(Model $m): bool => $m->removeSearchIndex());
63+
// Always remove tokens when model is deleted
64+
static::deleted(fn(Model $m) => $m->removeSearchIndex());
6465

65-
// Register forceDeleted/restored only for models using SoftDeletes
66+
// Register forceDeleted/restored events only if the model uses SoftDeletes
6667
if (in_array(SoftDeletes::class, class_uses_recursive(static::class), true)) {
67-
static::forceDeleted(fn(Model $m): bool => $m->removeSearchIndex());
68-
static::restored(fn(Model $m): bool => $m->updateSearchIndex());
68+
static::forceDeleted(fn(Model $m) => $m->removeSearchIndex());
69+
static::restored(fn(Model $m) => $m->updateSearchIndex());
6970
}
7071
}
7172

7273
/**
73-
* Build or refresh all search index entries for this model instance.
74+
* Create or refresh all search index entries for this model instance.
7475
*
7576
* @return void
7677
*/
@@ -83,9 +84,9 @@ public function updateSearchIndex(): void
8384
}
8485

8586
$pepper = (string) config('encrypted-search.search_pepper', '');
86-
$max = (int) config('encrypted-search.max_prefix_depth', 6);
87+
$max = (int) config('encrypted-search.max_prefix_depth', 6);
8788

88-
// Remove existing entries for this record
89+
// Remove existing entries
8990
SearchIndex::where('model_type', static::class)
9091
->where('model_id', $this->getKey())
9192
->delete();
@@ -103,28 +104,26 @@ public function updateSearchIndex(): void
103104
continue;
104105
}
105106

106-
// Exact match token
107107
if (! empty($modes['exact'])) {
108108
$rows[] = [
109109
'model_type' => static::class,
110-
'model_id' => $this->getKey(),
111-
'field' => $field,
112-
'type' => 'exact',
113-
'token' => Tokens::exact($norm, $pepper),
110+
'model_id' => $this->getKey(),
111+
'field' => $field,
112+
'type' => 'exact',
113+
'token' => Tokens::exact($norm, $pepper),
114114
'created_at' => now(),
115115
'updated_at' => now(),
116116
];
117117
}
118118

119-
// Prefix tokens
120119
if (! empty($modes['prefix'])) {
121120
foreach (Tokens::prefixes($norm, $max, $pepper) as $t) {
122121
$rows[] = [
123122
'model_type' => static::class,
124-
'model_id' => $this->getKey(),
125-
'field' => $field,
126-
'type' => 'prefix',
127-
'token' => $t,
123+
'model_id' => $this->getKey(),
124+
'field' => $field,
125+
'type' => 'prefix',
126+
'token' => $t,
128127
'created_at' => now(),
129128
'updated_at' => now(),
130129
];
@@ -150,28 +149,28 @@ public function removeSearchIndex(): void
150149
}
151150

152151
/**
153-
* Scope: perform an exact encrypted search on a specific field.
152+
* Query scope: find models by exact match on an indexed field.
154153
*
155154
* Example:
156-
* Client::encryptedExact('last_names', 'vermeer')->get();
155+
* Client::encryptedExact('last_names', 'vermeer')->get();
157156
*
158157
* @param \Illuminate\Database\Eloquent\Builder $query
159-
* @param string $field The name of the field to search
160-
* @param string $term The plaintext search term
158+
* @param string $field
159+
* @param string $term
161160
* @return \Illuminate\Database\Eloquent\Builder
162161
*/
163162
public function scopeEncryptedExact(Builder $query, string $field, string $term): Builder
164163
{
165164
$pepper = (string) config('encrypted-search.search_pepper', '');
166-
$norm = Normalizer::normalize($term);
165+
$norm = Normalizer::normalize($term);
167166

168167
if (! $norm) {
169168
return $query->whereRaw('1=0');
170169
}
171170

172171
$token = Tokens::exact($norm, $pepper);
173172

174-
return $query->whereIn($this->getQualifiedKeyName(), function ($sub) use ($field, $token): void {
173+
return $query->whereIn($this->getQualifiedKeyName(), function ($sub) use ($field, $token) {
175174
$sub->select('model_id')
176175
->from('encrypted_search_index')
177176
->where('model_type', static::class)
@@ -182,28 +181,28 @@ public function scopeEncryptedExact(Builder $query, string $field, string $term)
182181
}
183182

184183
/**
185-
* Scope: perform a prefix-based encrypted search on a specific field.
184+
* Query scope: find models by prefix match on an indexed field.
186185
*
187186
* Example:
188-
* Client::encryptedPrefix('first_names', 'wi')->get();
187+
* Client::encryptedPrefix('first_names', 'wi')->get();
189188
*
190189
* @param \Illuminate\Database\Eloquent\Builder $query
191-
* @param string $field The field name to search
192-
* @param string $term The prefix term to search for
190+
* @param string $field
191+
* @param string $term
193192
* @return \Illuminate\Database\Eloquent\Builder
194193
*/
195194
public function scopeEncryptedPrefix(Builder $query, string $field, string $term): Builder
196195
{
197196
$pepper = (string) config('encrypted-search.search_pepper', '');
198-
$norm = Normalizer::normalize($term);
197+
$norm = Normalizer::normalize($term);
199198

200199
if (! $norm) {
201200
return $query->whereRaw('1=0');
202201
}
203202

204203
$tokens = Tokens::prefixes($norm, (int) config('encrypted-search.max_prefix_depth', 6), $pepper);
205204

206-
return $query->whereIn($this->getQualifiedKeyName(), function ($sub) use ($field, $tokens): void {
205+
return $query->whereIn($this->getQualifiedKeyName(), function ($sub) use ($field, $tokens) {
207206
$sub->select('model_id')
208207
->from('encrypted_search_index')
209208
->where('model_type', static::class)
@@ -214,9 +213,9 @@ public function scopeEncryptedPrefix(Builder $query, string $field, string $term
214213
}
215214

216215
/**
217-
* Get the encrypted search configuration for this model.
216+
* Resolve the encrypted search configuration for this model.
218217
*
219-
* Models can define searchable fields either through a
218+
* This allows models to define searchable fields either via a
220219
* `getEncryptedSearchFields()` method or a `$encryptedSearch` property.
221220
*
222221
* @return array<string, array<string,bool>>

0 commit comments

Comments
 (0)