From bc73c1f9de227b9b18862a67ff6abf556fcaa17e Mon Sep 17 00:00:00 2001 From: Stefo Date: Thu, 2 Oct 2025 22:39:53 +0200 Subject: [PATCH 1/2] fix(#633): handle invalid UUIDs in not_found_by parameter --- .../services/caches/search/SearchAssistant.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/okapi/services/caches/search/SearchAssistant.php b/okapi/services/caches/search/SearchAssistant.php index 24c32049..7e5e6551 100644 --- a/okapi/services/caches/search/SearchAssistant.php +++ b/okapi/services/caches/search/SearchAssistant.php @@ -467,6 +467,23 @@ public function prepare_common_search_params() throw new InvalidParam('not_found_by', $e->whats_wrong_about_it); } + if (empty($users) || !is_array($users)) { + throw new InvalidParam('not_found_by', "No valid users found for the given parameter."); + } + + $user_uuids = explode("|", $tmp); + + $invalid_uuids = []; + foreach ($user_uuids as $uuid) { + if (!isset($users[$uuid])) { + $invalid_uuids[] = $uuid; + } + } + + if (!empty($invalid_uuids)) { + throw new InvalidParam('not_found_by', "The following UUID(s) are invalid or not found: " . implode(", ", $invalid_uuids)); + } + $internal_user_ids = array_map(function ($user) { return $user["internal_id"]; }, $users); if (Settings::get('USE_SQL_SUBQUERIES')) { $found_cache_subquery = self::get_found_cache_ids_subquery($internal_user_ids); From 8452079e993a3aad157380ca6f98d7af5b792c81 Mon Sep 17 00:00:00 2001 From: stefopl <92673167+stefopl@users.noreply.github.com> Date: Fri, 8 May 2026 07:10:21 +0200 Subject: [PATCH 2/2] refactor: extract duplicate found_by and not_found_by filter logic into a reusable method --- .../caches/search/SearchAssistant.php | 115 +++++++----------- 1 file changed, 45 insertions(+), 70 deletions(-) diff --git a/okapi/services/caches/search/SearchAssistant.php b/okapi/services/caches/search/SearchAssistant.php index 7e5e6551..dd778904 100644 --- a/okapi/services/caches/search/SearchAssistant.php +++ b/okapi/services/caches/search/SearchAssistant.php @@ -418,81 +418,13 @@ public function prepare_common_search_params() # found_by # - if ($tmp = $this->request->get_parameter('found_by')) - { - try { - $users = OkapiServiceRunner::call("services/users/users", new OkapiInternalRequest( - $this->request->consumer, null, array('user_uuids' => $tmp, 'fields' => 'internal_id'))); - } catch (InvalidParam $e) { # too many uuids - throw new InvalidParam('found_by', $e->whats_wrong_about_it); - } - - if (empty($users) || !is_array($users)) { - throw new InvalidParam('found_by', "No valid users found for the given parameter."); - } - - $user_uuids = explode("|", $tmp); - - $invalid_uuids = []; - foreach ($user_uuids as $uuid) { - if (!isset($users[$uuid])) { - $invalid_uuids[] = $uuid; - } - } - - if (!empty($invalid_uuids)) { - throw new InvalidParam('found_by', "The following UUID(s) are invalid or not found: " . implode(", ", $invalid_uuids)); - } - - $internal_user_ids = array_map(function ($user) { return $user["internal_id"]; }, $users); - if (Settings::get('USE_SQL_SUBQUERIES')) { - $found_cache_subquery = self::get_found_cache_ids_subquery($internal_user_ids); - $where_conds[] = "caches.cache_id in (".$found_cache_subquery.")"; - } else { - $found_cache_ids = self::get_found_cache_ids($internal_user_ids); - $where_conds[] = "caches.cache_id in ('".implode("','", array_map('\okapi\core\Db::escape_string', $found_cache_ids))."')"; - } - } + $this->apply_found_by_filter($where_conds); # # not_found_by # - if ($tmp = $this->request->get_parameter('not_found_by')) - { - try { - $users = OkapiServiceRunner::call("services/users/users", new OkapiInternalRequest( - $this->request->consumer, null, array('user_uuids' => $tmp, 'fields' => 'internal_id'))); - } catch (InvalidParam $e) { # too many uuids - throw new InvalidParam('not_found_by', $e->whats_wrong_about_it); - } - - if (empty($users) || !is_array($users)) { - throw new InvalidParam('not_found_by', "No valid users found for the given parameter."); - } - - $user_uuids = explode("|", $tmp); - - $invalid_uuids = []; - foreach ($user_uuids as $uuid) { - if (!isset($users[$uuid])) { - $invalid_uuids[] = $uuid; - } - } - - if (!empty($invalid_uuids)) { - throw new InvalidParam('not_found_by', "The following UUID(s) are invalid or not found: " . implode(", ", $invalid_uuids)); - } - - $internal_user_ids = array_map(function ($user) { return $user["internal_id"]; }, $users); - if (Settings::get('USE_SQL_SUBQUERIES')) { - $found_cache_subquery = self::get_found_cache_ids_subquery($internal_user_ids); - $where_conds[] = "caches.cache_id not in (".$found_cache_subquery.")"; - } else { - $found_cache_ids = self::get_found_cache_ids($internal_user_ids); - $where_conds[] = "caches.cache_id not in ('".implode("','", array_map('\okapi\core\Db::escape_string', $found_cache_ids))."')"; - } - } + $this->apply_found_by_filter($where_conds, true); # # recommended_only @@ -832,6 +764,49 @@ public function prepare_common_search_params() } } + private function apply_found_by_filter(&$where_conds, $is_exclude = false) + { + $param_name = $is_exclude ? 'not_found_by' : 'found_by'; + + if ($tmp = $this->request->get_parameter($param_name)) + { + try { + $users = OkapiServiceRunner::call("services/users/users", new OkapiInternalRequest( + $this->request->consumer, null, array('user_uuids' => $tmp, 'fields' => 'internal_id'))); + } catch (InvalidParam $e) { # too many uuids + throw new InvalidParam($param_name, $e->whats_wrong_about_it); + } + + if (empty($users) || !is_array($users)) { + throw new InvalidParam($param_name, "No valid users found for the given parameter."); + } + + $user_uuids = explode("|", $tmp); + + $invalid_uuids = []; + foreach ($user_uuids as $uuid) { + if (!isset($users[$uuid])) { + $invalid_uuids[] = $uuid; + } + } + + if (!empty($invalid_uuids)) { + throw new InvalidParam($param_name, "The following UUID(s) are invalid or not found: " . implode(", ", $invalid_uuids)); + } + + $internal_user_ids = array_map(function ($user) { return $user["internal_id"]; }, $users); + $operator = $is_exclude ? "not in" : "in"; + + if (Settings::get('USE_SQL_SUBQUERIES')) { + $found_cache_subquery = self::get_found_cache_ids_subquery($internal_user_ids); + $where_conds[] = "caches.cache_id $operator (".$found_cache_subquery.")"; + } else { + $found_cache_ids = self::get_found_cache_ids($internal_user_ids); + $where_conds[] = "caches.cache_id $operator ('".implode("','", array_map('\okapi\core\Db::escape_string', $found_cache_ids))."')"; + } + } + } + /** * Search for caches using conditions and options stored in the instance * of this class. These conditions are usually initialized by the call