From 79ff5c5a272828763c988765e1769d4343078597 Mon Sep 17 00:00:00 2001 From: Travis Miller Date: Wed, 22 Jul 2020 09:24:53 -0500 Subject: [PATCH] Fixed #8252 - circular references in location parents --- app/Models/Location.php | 3 ++- app/Providers/ValidationServiceProvider.php | 30 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/app/Models/Location.php b/app/Models/Location.php index ff36010341aa..86c3551c636b 100755 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -26,7 +26,8 @@ class Location extends SnipeModel 'address' => 'max:80|nullable', 'address2' => 'max:80|nullable', 'zip' => 'min:3|max:10|nullable', - 'manager_id' => 'exists:users,id|nullable' + 'manager_id' => 'exists:users,id|nullable', + 'parent_id' => 'non_circular:locations,id' ); /** diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index 78f5f2c4e6fc..231b3f63c604 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -71,6 +71,36 @@ public function boot() }); + Validator::extend('non_circular', function ($attribute, $value, $parameters, $validator) { + if (count($parameters) < 2) { + throw new \Exception('Required validator parameters: :'); + } + + // Parameters from the rule implementation ($pk will likely be 'id') + list($table, $pk) = $parameters; + + // Data from the edited model + $data = $validator->getData(); + + // The primary key value from the edited model + $data_pk = array_get($data, $pk); + $value_pk = $value; + + // If we’re editing an existing model and there is a parent value set… + while ($data_pk && $value_pk) { + // It’s not valid for any parent id to be equel to the existing model’s id + if ($data_pk == $value_pk) { + return false; + } + + // Traverse up the parents to get the next parent id + $value_pk = DB::table($table)->select($attribute)->where($pk, '=', $value_pk)->value($attribute); + } + + return true; + }); + + // Yo dawg. I heard you like validators. // This validates the custom validator regex in custom fields. // We're just checking that the regex won't throw an exception, not