From 4eb435e1485839f2c6bcad0640f2375ba024ac96 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 21 Nov 2023 12:36:11 +0000 Subject: [PATCH 1/3] Use unique_undeleted instead of unique_serial Signed-off-by: snipe --- app/Models/Asset.php | 5 +- app/Providers/ValidationServiceProvider.php | 69 +++++++++++++-------- 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/app/Models/Asset.php b/app/Models/Asset.php index ea436f013..4e5a25974 100644 --- a/app/Models/Asset.php +++ b/app/Models/Asset.php @@ -99,9 +99,9 @@ class Asset extends Depreciable 'expected_checkin' => 'date|nullable', 'location_id' => 'exists:locations,id|nullable', 'rtd_location_id' => 'exists:locations,id|nullable', - 'asset_tag' => 'required|min:1|max:255|unique_undeleted:assets,asset_tag|not_array', + 'asset_tag' => 'required|min:1|max:255|unique_undeleted:assets,asset_tag|not_array', 'purchase_date' => 'date|date_format:Y-m-d|nullable', - 'serial' => 'unique_serial|nullable', + 'serial' => 'unique_undeleted:assets,serial|nullable', 'purchase_cost' => 'numeric|nullable|gte:0', 'supplier_id' => 'exists:suppliers,id|nullable', 'asset_eol_date' => 'date|nullable', @@ -109,6 +109,7 @@ class Asset extends Depreciable 'byod' => 'boolean', ]; + /** * The attributes that are mass assignable. * diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 55d8efa3e..6d0ea0604 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -46,44 +46,63 @@ class ValidationServiceProvider extends ServiceProvider return $validator->passes(); }); - // Unique only if undeleted - // This works around the use case where multiple deleted items have the same unique attribute. - // (I think this is a bug in Laravel's validator?) - // $parameters is the rule parameters, like `unique_undeleted:users,id` - $parameters[0] is users, $parameters[1] is id - // the UniqueUndeletedTrait prefills these so you can just use `unique_undeleted` in your rules (but this would only work directly in the model) + + /** + * Unique only if undeleted. + * + * This works around the use case where multiple deleted items have the same unique attribute. + * (I think this is a bug in Laravel's validator?) + * + * $attribute is the FIELDNAME you're checking against + * $value is the VALUE of the item you're checking against the existing values in the fieldname + * $parameters[0] is the TABLE NAME you're querying + * $parameters[1] is the ID of the item you're querying - this makes it work on saving, checkout, etc, + * since it defaults to 0 if there is no item created yet (new item), but populates the ID if editing + * + * The UniqueUndeletedTrait prefills these parameters, so you can just use + * `unique_undeleted:table,fieldname` in your rules out of the box + */ Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) { + + \Log::debug('Parameters: '); + \Log::debug(print_r($parameters, true)); + + \Log::debug('Attribute: '. $attribute); + \Log::debug('Value: '. $value); + if (count($parameters)) { - $count = DB::table($parameters[0])->select('id')->where($attribute, '=', $value)->whereNull('deleted_at')->where('id', '!=', $parameters[1])->count(); + + // This is a bit of a shim, but serial doesn't have any other rules around it other than that it's nullable + if (($parameters[0]=='assets') && ($attribute == 'serial') && (Setting::getSettings()->unique_serial != '1')) { + \Log::debug('Checking for serial and it is not unique'); + return true; + } + + $count = DB::table($parameters[0]) + ->select('id') + ->where($attribute, '=', $value) + ->whereNull('deleted_at') + ->where('id', '!=', $parameters[1])->count(); return $count < 1; } }); // Unique if undeleted for two columns - // Same as unique_undeleted but taking the combination of two columns as unique constrain. - Validator::extend('two_column_unique_undeleted', function ($attribute, $value, $parameters, $validator) { - if (count($parameters)) { - $count = DB::table($parameters[0]) - ->select('id')->where($attribute, '=', $value) - ->whereNull('deleted_at') - ->where('id', '!=', $parameters[1]) - ->where($parameters[2], $parameters[3])->count(); - - return $count < 1; - } - }); - - - Validator::extend('unique_serial', function ($attribute, $value, $parameters, $validator) { - if(Setting::getSettings()->unique_serial == '1') { - $count = DB::table('assets')->select('id')->where('serial', '=', $value)->whereNull('deleted_at')->count(); + // Same as unique_undeleted but taking the combination of two columns as unique constrain. + Validator::extend('two_column_unique_undeleted', function ($attribute, $value, $parameters, $validator) { + if (count($parameters)) { + $count = DB::table($parameters[0]) + ->select('id')->where($attribute, '=', $value) + ->whereNull('deleted_at') + ->where('id', '!=', $parameters[1]) + ->where($parameters[2], $parameters[3])->count(); return $count < 1; - } else { - return true; } }); + // Prevent circular references // // Example usage in Location model where parent_id references another Location: From 2b9e4110bcb330e8c0a62fb218fde8777455580b Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 21 Nov 2023 13:37:56 +0000 Subject: [PATCH 2/3] Removed debugging Signed-off-by: snipe --- app/Providers/ValidationServiceProvider.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 6d0ea0604..295078caa 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -63,13 +63,7 @@ class ValidationServiceProvider extends ServiceProvider * `unique_undeleted:table,fieldname` in your rules out of the box */ Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) { - - \Log::debug('Parameters: '); - \Log::debug(print_r($parameters, true)); - - \Log::debug('Attribute: '. $attribute); - \Log::debug('Value: '. $value); - + if (count($parameters)) { // This is a bit of a shim, but serial doesn't have any other rules around it other than that it's nullable From 766eee78b204d7788e337c0b365286cbbbe88194 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 21 Nov 2023 13:47:49 +0000 Subject: [PATCH 3/3] Removed debugging Signed-off-by: snipe --- app/Providers/ValidationServiceProvider.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 295078caa..5ee904d20 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -63,12 +63,11 @@ class ValidationServiceProvider extends ServiceProvider * `unique_undeleted:table,fieldname` in your rules out of the box */ Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) { - + if (count($parameters)) { // This is a bit of a shim, but serial doesn't have any other rules around it other than that it's nullable if (($parameters[0]=='assets') && ($attribute == 'serial') && (Setting::getSettings()->unique_serial != '1')) { - \Log::debug('Checking for serial and it is not unique'); return true; }