LP1353643 Located URIs search scoping and display
authorLiam Whalen <liam.whalen@bc.libraries.coop>
Tue, 23 Sep 2014 00:53:33 +0000 (17:53 -0700)
committerJeff Davis <jdavis@sitka.bclibraries.ca>
Wed, 29 Jul 2015 20:58:03 +0000 (13:58 -0700)
The current system returns all URIs attached to a record.  This is too
much information when a record has a large number of 856 $u attached to
it.

This code adds new SQL functions to control the search scope of records
with URIs attached to them and the display of URIs once records have
been retrieved.

To do this 7 new libray settings have been created.

opac.luri_anc_vis_depth, which controls the depth of the ancestors
searched when retrieving URIs for a record.

opac.luri_des_vis_depth, which controls the depth of the descentants
searched when retrieving URIs for a record.

opac.luri_ancestor_record_visibility_depth, which controls the depth of
ancestors searched for relevant URIs when searching records containing
856 $u values.

opac.luri_descendants_record_visibility_depth, which controls the depth
of descendants searched for relevant URIs when searching records
containing 856 $u values.

opac.luri_pref_ancestor_record_visibility_depth, which controls the
depth of the preferred library's ancestors searched for relevant URIs
when searching records containing 856 $u values.

opac.luri_pref_descendants_record_visibility_depth, which controls the
depth of the preferred library's descendants searched for relevant URIs
when searching records containing 856 $u values.

These last two settings are needed to allow search for URIs and search
for physical copies to behave in the same mannner regarding the
preferred library.  When search for copies, the preferred library
returns copies that are attached to records belonging to the search
library, but it does not return records that belong only to the
preferred library.  Using these settings, a library can ensure that
records with 856 $u behave in the same manner.

Lastly opac.luri_results_uri_limit determines how many URIs to display
in the search results screen.  This stops too many links from being
displayed for a single result in the search results, which causes the
search results page to be too long.

At Sitka, we set the opac.luri_descendants_record_visibility_depth to
100 at the Consortia level.  This allows the search to return all
records with 856 $u. But, we set the opac.luri_des_vis_depth to 0, which
stops the search results from displaying any links at the Consortia
level. All other settings are 0 for the Consortia level.

At one branch we set the opac.luri_descendants_record_visibility_depth to
100.  But the opac.luri_desc_vis_depth is set to 4. At the same branch
the opac.luri_ancestor_record_visibility_depth is set to 2, which causes
records belonging to the system to be returned, but not records
belonging to the Consortia or the Federation.  As well,
opac.luri_anc_vis_depth is set to 2, to ensure URIs are
retrieved for any records that could be retrieved.

Added link to More results

Signed-off-by: Liam Whalen <liam.whalen@bc.libraries.coop>
Removed extra More...

Open-ILS/src/sql/Pg/020.schema.functions.sql
Open-ILS/src/sql/Pg/300.schema.staged_search.sql
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/990.schema.unapi.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.data.luri_as_copy_settings.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.fenced_actor_org_unit_descendants.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.fenced_actor_org_unit_full_path.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.org_unit_ancestor_fenced_path.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.staged_search.fenced_query_parser_fts.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.unapi.fenced_located_uris.sql [new file with mode: 0644]
Open-ILS/src/templates/opac/parts/result/table.tt2

index c0eb8af..059eec9 100644 (file)
@@ -134,6 +134,39 @@ CREATE OR REPLACE FUNCTION actor.org_unit_descendants( INT, INT ) RETURNS SETOF
     ) SELECT ou.* FROM actor.org_unit ou JOIN descendant_depth USING (id);
 $$ LANGUAGE SQL ROWS 1;
 
+CREATE OR REPLACE FUNCTION actor.org_unit_descendants( INT, INT, INT ) RETURNS SETOF actor.org_unit AS $$
+    WITH RECURSIVE descendant_depth AS (
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                JOIN anscestor_depth ad ON (ad.id = ou.id)
+          WHERE ad.depth = $2
+            UNION ALL
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                JOIN descendant_depth ot ON (ot.id = ou.parent_ou)
+    ), anscestor_depth AS (
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+          WHERE ou.id = $1
+            UNION ALL
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                JOIN anscestor_depth ot ON (ot.parent_ou = ou.id)
+    ) SELECT ou.* FROM actor.org_unit ou JOIN descendant_depth USING (id) WHERE depth <= $3;
+$$ LANGUAGE SQL ROWS 1;
+
 CREATE OR REPLACE FUNCTION actor.org_unit_descendants( INT ) RETURNS SETOF actor.org_unit AS $$
     WITH RECURSIVE descendant_depth AS (
         SELECT  ou.id,
@@ -216,6 +249,16 @@ CREATE OR REPLACE FUNCTION actor.org_unit_full_path ( INT, INT ) RETURNS SETOF a
        SELECT  * FROM actor.org_unit_full_path((actor.org_unit_ancestor_at_depth($1, $2)).id)
 $$ LANGUAGE SQL STABLE ROWS 1;
 
+CREATE OR REPLACE FUNCTION actor.org_unit_full_path ( INT, INT, INT ) RETURNS SETOF actor.org_unit AS $$
+       SELECT  *
+         FROM  actor.org_unit_ancestor_fenced_path($1, $2)
+                       UNION
+       SELECT  *
+         FROM  actor.org_unit_descendants($1, (SELECT depth FROM actor.org_unit AS aou INNER JOIN
+                                                actor.org_unit_type AS aout ON aou.ou_type = aout.id
+                                                WHERE aou.id = $1), $3);
+$$ LANGUAGE SQL STABLE ROWS 1;
+
 CREATE OR REPLACE FUNCTION actor.org_unit_combined_ancestors ( INT, INT ) RETURNS SETOF actor.org_unit AS $$
        SELECT  *
          FROM  actor.org_unit_ancestors($1)
@@ -232,6 +275,17 @@ CREATE OR REPLACE FUNCTION actor.org_unit_common_ancestors ( INT, INT ) RETURNS
          FROM  actor.org_unit_ancestors($2);
 $$ LANGUAGE SQL STABLE ROWS 1;
 
+CREATE OR REPLACE FUNCTION actor.org_unit_ancestor_fenced_path( INT, INT ) RETURNS SETOF actor.org_unit AS $$
+    WITH RECURSIVE org_unit_ancestors_distance(id, distance) AS (
+            SELECT $1, 0
+        UNION
+            SELECT ou.parent_ou, ouad.distance+1
+            FROM actor.org_unit ou JOIN org_unit_ancestors_distance ouad ON (ou.id = ouad.id)
+            WHERE ou.parent_ou IS NOT NULL
+    )
+    SELECT ou.* FROM actor.org_unit ou JOIN org_unit_ancestors_distance ouad USING (id) ORDER BY ouad.distance DESC OFFSET $2;
+$$ LANGUAGE SQL ROWS 1;
+
 -- Given the IDs of two rows in actor.org_unit, *the second being an ancestor
 -- of the first*, return in array form the path from the ancestor to the
 -- descendant, with each point in the path being an org_unit ID.  This is
index 5907e05..73104b8 100644 (file)
@@ -71,6 +71,11 @@ DECLARE
     excluded_count      INT := 0;
 
     luri_as_copy        BOOL;
+    search_anc_rec_vis_depth INT;
+    search_des_rec_vis_depth INT;
+    pref_anc_rec_vis_depth INT;
+    pref_des_rec_vis_depth INT;
+
 BEGIN
 
     check_limit := COALESCE( param_check, 1000 );
@@ -79,6 +84,18 @@ BEGIN
 
     SELECT COALESCE( enabled, FALSE ) INTO luri_as_copy FROM config.global_flag WHERE name = 'opac.located_uri.act_as_copy';
 
+    SELECT COALESCE( substring(value, '\d+'), '0' ) INTO search_anc_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_ancestor_record_visibility_depth', param_search_ou);
+
+    SELECT COALESCE( substring(value, '\d+'), '100' ) INTO search_des_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_descendants_record_visibility_depth', param_search_ou);
+
+    SELECT COALESCE( substring(value, '\d+'), '0') INTO pref_anc_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_pref_ancestor_record_visibility_depth', param_pref_ou);
+
+    SELECT COALESCE( substring(value, '\d+'), '100' ) INTO pref_des_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_pref_descendants_record_visibility_depth', param_pref_ou);
+
     -- core_skip_chk := COALESCE( param_skip_chk, 1 );
 
     IF param_search_ou > 0 THEN
@@ -89,9 +106,11 @@ BEGIN
         END IF;
 
         IF luri_as_copy THEN
-            SELECT ARRAY_AGG(distinct id) INTO luri_org_list FROM actor.org_unit_full_path( param_search_ou );
+            SELECT ARRAY_AGG(distinct id) INTO luri_org_list FROM actor.org_unit_full_path( param_search_ou, 
+                search_anc_rec_vis_depth, search_des_rec_vis_depth );
         ELSE
-            SELECT ARRAY_AGG(distinct id) INTO luri_org_list FROM actor.org_unit_ancestors( param_search_ou );
+            SELECT ARRAY_AGG(distinct id) INTO luri_org_list FROM actor.org_unit_ancestor_fenced_path( param_search_ou, 
+                search_anc_rec_vis_depth );
         END IF;
 
     ELSIF param_search_ou < 0 THEN
@@ -100,9 +119,11 @@ BEGIN
         FOR tmp_int IN SELECT * FROM UNNEST(search_org_list) LOOP
 
             IF luri_as_copy THEN
-                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_full_path( tmp_int );
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_full_path( tmp_int, 
+                    search_anc_rec_vis_depth, search_des_rec_vis_depth );
             ELSE
-                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_ancestors( tmp_int );
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_ancestor_fenced_path( tmp_int, 
+                    search_anc_rec_vis_depth );
             END IF;
 
             luri_org_list := luri_org_list || tmp_int_list;
@@ -116,9 +137,11 @@ BEGIN
 
     IF param_pref_ou IS NOT NULL THEN
             IF luri_as_copy THEN
-                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_full_path( param_pref_ou );
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_full_path( param_pref_ou,
+                    pref_anc_rec_vis_depth, pref_des_rec_vis_depth );
             ELSE
-                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_ancestors( param_pref_ou );
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_ancestor_fenced_path( param_pref_ou,
+                    pref_anc_rec_vis_depth );
             END IF;
 
         luri_org_list := luri_org_list || tmp_int_list;
@@ -398,5 +421,4 @@ BEGIN
 END;
 $func$ LANGUAGE PLPGSQL;
 
 COMMIT;
index 0ce75a4..ec11e11 100644 (file)
@@ -14250,6 +14250,147 @@ VALUES (
     )
 );
 
+-- LURI scoping setting types
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp)
+VALUES (
+    'opac.luri_anc_vis_depth',
+    oils_i18n_gettext(
+        'opac.luri_anc_vis_depth',
+        'Limit the depth of ancestor URI retrieval ',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_anc_vis_depth',
+        'When retrieving URIs for a record, limit the depth of ancestors checked for URI ownership',
+        'coust',
+        'description'
+    ),
+    'opac'
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp)
+VALUES (
+    'opac.luri_ancestor_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_ancestor_record_visibility_depth',
+        'Limit the depth of luri ancestor records returned',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_ancestor_record_visibility_depth',
+        'Limit the records returned for ancestors when searching for records with URIs according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac'
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp)
+VALUES (
+    'opac.luri_des_vis_depth',
+    oils_i18n_gettext(
+        'opac.luri_des_vis_depth',
+        'Limit the depth of descendant URI retrieval',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_des_vis_depth',
+        'When retrieving URIs for a record, limit the depth of descendants checked for URI ownership',
+        'coust',
+        'description'
+    ),
+    'opac'
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp)
+VALUES (
+    'opac.luri_descendants_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_descendants_record_visibility_depth',
+        'Limit the depth of luri descendant records returned',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_descendants_record_visibility_depth',
+        'Limit the records returned for descendants when searching for records with URIs according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac'
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp)
+VALUES (
+    'opac.luri_pref_ancestor_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_pref_ancestor_record_visibility_depth',
+        'Limit the depth of luri ancestor records returned for the pref lib',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_pref_ancestor_record_visibility_depth',
+        'Limit the records returned for ancestors when searching for records with URIs, via the pref lib, according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac'
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp)
+VALUES (
+    'opac.luri_pref_descendants_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_pref_descendants_record_visibility_depth',
+        'Limit the depth of luri descendant records returned for the pref lib',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_pref_descendants_record_visibility_depth',
+        'Limit the records returned for descendatns when searching for records with URIs, via the pref lib, according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac'
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp)
+VALUES (
+    'opac.luri_results_uri_limit',
+    oils_i18n_gettext(
+        'opac.luri_results_uri_limit',
+        'Limit the number of URIs on the results page',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_results_uri_limit',
+        'When retrieving results if a record will display more URIs than the number set here, then limit the number of URIs displayed to this setting''s value',
+        'coust',
+        'description'
+    ),
+    'opac'
+);
+
 INSERT INTO config.floating_group(name) VALUES ('Everywhere');
 INSERT INTO config.floating_group_member(floating_group, org_unit) VALUES (1, 1);
 
index 8ad2ec4..881b7f7 100644 (file)
@@ -159,7 +159,6 @@ CREATE OR REPLACE FUNCTION evergreen.ranked_volumes
     RETURNS TABLE (id BIGINT, name TEXT, label_sortkey TEXT, rank BIGINT)
     AS $$ SELECT * FROM evergreen.ranked_volumes(ARRAY[$1],$2,$3,$4,$5,$6,$7) $$ LANGUAGE SQL STABLE;
 
-
 CREATE OR REPLACE FUNCTION evergreen.located_uris (
     bibid BIGINT[], 
     ouid INT,
@@ -177,7 +176,28 @@ CREATE OR REPLACE FUNCTION evergreen.located_uris (
       WHERE acn.record = ANY ($1)
           AND acn.deleted IS FALSE
           AND auri.active IS TRUE
-          AND ((NOT all_orgs.flag AND aou.id IS NOT NULL) OR (all_orgs.flag AND COALESCE(aou.id,aoud.id) IS NOT NULL))
+          AND ((NOT all_orgs.flag AND aou.id IS NOT NULL AND aou.id IN 
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path($2, (SELECT substring(value, '\d+')::INT 
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2))) OR aou.id IN
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2))))) 
+                OR (all_orgs.flag AND COALESCE(aou.id,aoud.id) IS NOT NULL AND (
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path($2, (SELECT substring(value, '\d+')::INT  
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = $2))) OR 
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2)), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = COALESCE($3, $2)))))))
     UNION
     SELECT acn.id, COALESCE(aou.name,aoud.name) AS name, acn.label_sortkey, evergreen.rank_ou(aou.id, $2, $3) AS pref_ou
       FROM asset.call_number acn
@@ -189,7 +209,28 @@ CREATE OR REPLACE FUNCTION evergreen.located_uris (
       WHERE acn.record = ANY ($1)
           AND acn.deleted IS FALSE
           AND auri.active IS TRUE
-          AND ((NOT all_orgs.flag AND aou.id IS NOT NULL) OR (all_orgs.flag AND COALESCE(aou.id,aoud.id) IS NOT NULL)))x
+          AND ((NOT all_orgs.flag AND aou.id IS NOT NULL and aou.id IN
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path($2, (SELECT substring(value, '\d+')::INT 
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2))) OR aou.id IN
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2))))) 
+                OR (all_orgs.flag AND COALESCE(aou.id,aoud.id) IS NOT NULL AND (
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path($2, (SELECT substring(value, '\d+')::INT  
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = $2))) OR 
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2)), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = COALESCE($3, $2))))))))x
     ORDER BY id, pref_ou DESC;
 $$
 LANGUAGE SQL STABLE;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.luri_as_copy_settings.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.luri_as_copy_settings.sql
new file mode 100644 (file)
index 0000000..edd11db
--- /dev/null
@@ -0,0 +1,153 @@
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp, update_perm, view_perm)
+VALUES (
+    'opac.luri_anc_vis_depth',
+    oils_i18n_gettext(
+        'opac.luri_anc_vis_depth',
+        'Limit the depth of ancestor URI retrieval ',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_anc_vis_depth',
+        'When retrieving URIs for a record, limit the depth of ancestors checked for URI ownership',
+        'coust',
+        'description'
+    ),
+    'opac',
+    93,
+    192
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp, update_perm, view_perm)
+VALUES (
+    'opac.luri_ancestor_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_ancestor_record_visibility_depth',
+        'Limit the depth of luri ancestor records returned',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_ancestor_record_visibility_depth',
+        'Limit the records returned for ancestors when searching for records with URIs according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac',
+    93,
+    192
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp, update_perm, view_perm)
+VALUES (
+    'opac.luri_des_vis_depth',
+    oils_i18n_gettext(
+        'opac.luri_des_vis_depth',
+        'Limit the depth of descendant URI retrieval',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_des_vis_depth',
+        'When retrieving URIs for a record, limit the depth of descendants checked for URI ownership',
+        'coust',
+        'description'
+    ),
+    'opac',
+    93,
+    192
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp, update_perm, view_perm)
+VALUES (
+    'opac.luri_descendants_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_descendants_record_visibility_depth',
+        'Limit the depth of luri descendant records returned',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_descendants_record_visibility_depth',
+        'Limit the records returned for descendants when searching for records with URIs according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac',
+    93,
+    192
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp, update_perm, view_perm)
+VALUES (
+    'opac.luri_pref_ancestor_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_pref_ancestor_record_visibility_depth',
+        'Limit the depth of luri ancestor records returned for the pref lib',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_pref_ancestor_record_visibility_depth',
+        'Limit the records returned for ancestors when searching for records with URIs, via the pref lib, according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac',
+    93,
+    192
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp, update_perm, view_perm)
+VALUES (
+    'opac.luri_pref_descendants_record_visibility_depth',
+    oils_i18n_gettext(
+        'opac.luri_pref_descendants_record_visibility_depth',
+        'Limit the depth of luri descendant records returned for the pref lib',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_pref_descendants_record_visibility_depth',
+        'Limit the records returned for descendatns when searching for records with URIs, via the pref lib, according to the depth specified',
+        'coust',
+        'description'
+    ),
+    'opac',
+    93,
+    192
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, datatype, description, grp, update_perm, view_perm)
+VALUES (
+    'opac.luri_results_uri_limit',
+    oils_i18n_gettext(
+        'opac.luri_results_uri_limit',
+        'Limit the number of URIs on the results page',
+        'coust',
+        'label'
+    ),
+    'integer',
+    oils_i18n_gettext(
+        'opac.luri_results_uri_limit',
+        'When retrieving results if a record will display more URIs than the number set here, then limit the number of URIs displayed to this setting''s value',
+        'coust',
+        'description'
+    ),
+    'opac',
+    93,
+    192
+);
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.fenced_actor_org_unit_descendants.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.fenced_actor_org_unit_descendants.sql
new file mode 100644 (file)
index 0000000..40034ba
--- /dev/null
@@ -0,0 +1,38 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+CREATE OR REPLACE FUNCTION actor.org_unit_descendants( INT, INT, INT ) RETURNS SETOF actor.org_unit AS $$
+    WITH RECURSIVE descendant_depth AS (
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                JOIN anscestor_depth ad ON (ad.id = ou.id)
+          WHERE ad.depth = $2
+            UNION ALL
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                JOIN descendant_depth ot ON (ot.id = ou.parent_ou)
+    ), anscestor_depth AS (
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+          WHERE ou.id = $1
+            UNION ALL
+        SELECT  ou.id,
+                ou.parent_ou,
+                out.depth
+          FROM  actor.org_unit ou
+                JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                JOIN anscestor_depth ot ON (ot.parent_ou = ou.id)
+    ) SELECT ou.* FROM actor.org_unit ou JOIN descendant_depth USING (id) WHERE depth <= $3;
+$$ LANGUAGE SQL ROWS 1;
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.fenced_actor_org_unit_full_path.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.fenced_actor_org_unit_full_path.sql
new file mode 100644 (file)
index 0000000..b9857a0
--- /dev/null
@@ -0,0 +1,13 @@
+BEGIN;
+
+CREATE OR REPLACE FUNCTION actor.org_unit_full_path ( INT, INT, INT ) RETURNS SETOF actor.org_unit AS $$
+       SELECT  *
+         FROM  actor.org_unit_ancestor_fenced_path($1, $2)
+                       UNION
+       SELECT  *
+         FROM  actor.org_unit_descendants($1, (SELECT depth FROM actor.org_unit AS aou INNER JOIN
+                                                actor.org_unit_type AS aout ON aou.ou_type = aout.id
+                                                WHERE aou.id = $1), $3);
+$$ LANGUAGE SQL STABLE ROWS 1;
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.org_unit_ancestor_fenced_path.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.functions.org_unit_ancestor_fenced_path.sql
new file mode 100644 (file)
index 0000000..28a0dbe
--- /dev/null
@@ -0,0 +1,16 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+CREATE OR REPLACE FUNCTION actor.org_unit_ancestor_fenced_path( INT, INT ) RETURNS SETOF actor.org_unit AS $$
+    WITH RECURSIVE org_unit_ancestors_distance(id, distance) AS (
+            SELECT $1, 0
+        UNION
+            SELECT ou.parent_ou, ouad.distance+1
+            FROM actor.org_unit ou JOIN org_unit_ancestors_distance ouad ON (ou.id = ouad.id)
+            WHERE ou.parent_ou IS NOT NULL
+    )
+    SELECT ou.* FROM actor.org_unit ou JOIN org_unit_ancestors_distance ouad USING (id) ORDER BY ouad.distance DESC OFFSET $2;
+$$ LANGUAGE SQL ROWS 1;
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.staged_search.fenced_query_parser_fts.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.staged_search.fenced_query_parser_fts.sql
new file mode 100644 (file)
index 0000000..642e122
--- /dev/null
@@ -0,0 +1,391 @@
+BEGIN;
+
+CREATE OR REPLACE FUNCTION search.query_parser_fts (
+
+    param_search_ou INT,
+    param_depth     INT,
+    param_query     TEXT,
+    param_statuses  INT[],
+    param_locations INT[],
+    param_offset    INT,
+    param_check     INT,
+    param_limit     INT,
+    metarecord      BOOL,
+    staff           BOOL,
+    deleted_search  BOOL,
+    param_pref_ou   INT DEFAULT NULL
+) RETURNS SETOF search.search_result AS $func$
+DECLARE
+
+    current_res         search.search_result%ROWTYPE;
+    search_org_list     INT[];
+    luri_org_list       INT[];
+    tmp_int_list        INT[];
+
+    check_limit         INT;
+    core_limit          INT;
+    core_offset         INT;
+    tmp_int             INT;
+
+    core_result         RECORD;
+    core_cursor         REFCURSOR;
+    core_rel_query      TEXT;
+
+    total_count         INT := 0;
+    check_count         INT := 0;
+    deleted_count       INT := 0;
+    visible_count       INT := 0;
+    excluded_count      INT := 0;
+
+    luri_as_copy        BOOL;
+    search_anc_rec_vis_depth INT;
+    search_des_rec_vis_depth INT;
+    pref_anc_rec_vis_depth INT;
+    pref_des_rec_vis_depth INT;
+
+BEGIN
+
+    check_limit := COALESCE( param_check, 1000 );
+    core_limit  := COALESCE( param_limit, 25000 );
+    core_offset := COALESCE( param_offset, 0 );
+
+    SELECT COALESCE( enabled, FALSE ) INTO luri_as_copy FROM config.global_flag WHERE name = 'opac.located_uri.act_as_copy';
+
+    SELECT COALESCE( substring(value, '\d+'), '0' ) INTO search_anc_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_ancestor_record_visibility_depth', param_search_ou);
+
+    SELECT COALESCE( substring(value, '\d+'), '100' ) INTO search_des_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_descendants_record_visibility_depth', param_search_ou);
+
+    SELECT COALESCE( substring(value, '\d+'), '0') INTO pref_anc_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_pref_ancestor_record_visibility_depth', param_pref_ou);
+
+    SELECT COALESCE( substring(value, '\d+'), '100' ) INTO pref_des_rec_vis_depth
+        FROM actor.org_unit_ancestor_setting('opac.luri_pref_descendants_record_visibility_depth', param_pref_ou);
+
+    -- core_skip_chk := COALESCE( param_skip_chk, 1 );
+
+    IF param_search_ou > 0 THEN
+        IF param_depth IS NOT NULL THEN
+            SELECT ARRAY_AGG(distinct id) INTO search_org_list FROM actor.org_unit_descendants( param_search_ou, param_depth );
+        ELSE
+            SELECT ARRAY_AGG(distinct id) INTO search_org_list FROM actor.org_unit_descendants( param_search_ou );
+        END IF;
+
+        IF luri_as_copy THEN
+            SELECT ARRAY_AGG(distinct id) INTO luri_org_list FROM actor.org_unit_full_path( param_search_ou, 
+                search_anc_rec_vis_depth, search_des_rec_vis_depth );
+        ELSE
+            SELECT ARRAY_AGG(distinct id) INTO luri_org_list FROM actor.org_unit_ancestor_fenced_path( param_search_ou, 
+                search_anc_rec_vis_depth );
+        END IF;
+
+    ELSIF param_search_ou < 0 THEN
+        SELECT ARRAY_AGG(distinct org_unit) INTO search_org_list FROM actor.org_lasso_map WHERE lasso = -param_search_ou;
+
+        FOR tmp_int IN SELECT * FROM UNNEST(search_org_list) LOOP
+
+            IF luri_as_copy THEN
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_full_path( tmp_int, 
+                    search_anc_rec_vis_depth, search_des_rec_vis_depth );
+            ELSE
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_ancestor_fenced_path( tmp_int, 
+                    search_anc_rec_vis_depth );
+            END IF;
+
+            luri_org_list := luri_org_list || tmp_int_list;
+        END LOOP;
+
+        SELECT ARRAY_AGG(DISTINCT x.id) INTO luri_org_list FROM UNNEST(luri_org_list) x(id);
+
+    ELSIF param_search_ou = 0 THEN
+        -- reserved for user lassos (ou_buckets/type='lasso') with ID passed in depth ... hack? sure.
+    END IF;
+
+    IF param_pref_ou IS NOT NULL THEN
+            IF luri_as_copy THEN
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_full_path( param_pref_ou,
+                    pref_anc_rec_vis_depth, pref_des_rec_vis_depth );
+            ELSE
+                SELECT ARRAY_AGG(distinct id) INTO tmp_int_list FROM actor.org_unit_ancestor_fenced_path( param_pref_ou,
+                    pref_anc_rec_vis_depth );
+            END IF;
+
+        luri_org_list := luri_org_list || tmp_int_list;
+    END IF;
+
+    OPEN core_cursor FOR EXECUTE param_query;
+
+    LOOP
+
+        FETCH core_cursor INTO core_result;
+        EXIT WHEN NOT FOUND;
+        EXIT WHEN total_count >= core_limit;
+
+        total_count := total_count + 1;
+
+        CONTINUE WHEN total_count NOT BETWEEN  core_offset + 1 AND check_limit + core_offset;
+
+        check_count := check_count + 1;
+
+        IF NOT deleted_search THEN
+
+            PERFORM 1 FROM biblio.record_entry b WHERE NOT b.deleted AND b.id IN ( SELECT * FROM unnest( core_result.records ) );
+            IF NOT FOUND THEN
+                -- RAISE NOTICE ' % were all deleted ... ', core_result.records;
+                deleted_count := deleted_count + 1;
+                CONTINUE;
+            END IF;
+
+            PERFORM 1
+              FROM  biblio.record_entry b
+                    JOIN config.bib_source s ON (b.source = s.id)
+              WHERE s.transcendant
+                    AND b.id IN ( SELECT * FROM unnest( core_result.records ) );
+
+            IF FOUND THEN
+                -- RAISE NOTICE ' % were all transcendant ... ', core_result.records;
+                visible_count := visible_count + 1;
+
+                current_res.id = core_result.id;
+                current_res.rel = core_result.rel;
+
+                tmp_int := 1;
+                IF metarecord THEN
+                    SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
+                END IF;
+
+                IF tmp_int = 1 THEN
+                    current_res.record = core_result.records[1];
+                ELSE
+                    current_res.record = NULL;
+                END IF;
+
+                RETURN NEXT current_res;
+
+                CONTINUE;
+            END IF;
+
+            PERFORM 1
+              FROM  asset.call_number cn
+                    JOIN asset.uri_call_number_map map ON (map.call_number = cn.id)
+                    JOIN asset.uri uri ON (map.uri = uri.id)
+              WHERE NOT cn.deleted
+                    AND cn.label = '##URI##'
+                    AND uri.active
+                    AND ( param_locations IS NULL OR array_upper(param_locations, 1) IS NULL )
+                    AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
+                    AND cn.owning_lib IN ( SELECT * FROM unnest( luri_org_list ) )
+              LIMIT 1;
+
+            IF FOUND THEN
+                -- RAISE NOTICE ' % have at least one URI ... ', core_result.records;
+                visible_count := visible_count + 1;
+
+                current_res.id = core_result.id;
+                current_res.rel = core_result.rel;
+
+                tmp_int := 1;
+                IF metarecord THEN
+                    SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
+                END IF;
+
+                IF tmp_int = 1 THEN
+                    current_res.record = core_result.records[1];
+                ELSE
+                    current_res.record = NULL;
+                END IF;
+
+                RETURN NEXT current_res;
+
+                CONTINUE;
+            END IF;
+
+            IF param_statuses IS NOT NULL AND array_upper(param_statuses, 1) > 0 THEN
+
+                PERFORM 1
+                  FROM  asset.call_number cn
+                        JOIN asset.copy cp ON (cp.call_number = cn.id)
+                  WHERE NOT cn.deleted
+                        AND NOT cp.deleted
+                        AND cp.status IN ( SELECT * FROM unnest( param_statuses ) )
+                        AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
+                        AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                  LIMIT 1;
+
+                IF NOT FOUND THEN
+                    PERFORM 1
+                      FROM  biblio.peer_bib_copy_map pr
+                            JOIN asset.copy cp ON (cp.id = pr.target_copy)
+                      WHERE NOT cp.deleted
+                            AND cp.status IN ( SELECT * FROM unnest( param_statuses ) )
+                            AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
+                            AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                      LIMIT 1;
+
+                    IF NOT FOUND THEN
+                    -- RAISE NOTICE ' % and multi-home linked records were all status-excluded ... ', core_result.records;
+                        excluded_count := excluded_count + 1;
+                        CONTINUE;
+                    END IF;
+                END IF;
+
+            END IF;
+
+            IF param_locations IS NOT NULL AND array_upper(param_locations, 1) > 0 THEN
+
+                PERFORM 1
+                  FROM  asset.call_number cn
+                        JOIN asset.copy cp ON (cp.call_number = cn.id)
+                  WHERE NOT cn.deleted
+                        AND NOT cp.deleted
+                        AND cp.location IN ( SELECT * FROM unnest( param_locations ) )
+                        AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
+                        AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                  LIMIT 1;
+
+                IF NOT FOUND THEN
+                    PERFORM 1
+                      FROM  biblio.peer_bib_copy_map pr
+                            JOIN asset.copy cp ON (cp.id = pr.target_copy)
+                      WHERE NOT cp.deleted
+                            AND cp.location IN ( SELECT * FROM unnest( param_locations ) )
+                            AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
+                            AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                      LIMIT 1;
+
+                    IF NOT FOUND THEN
+                        -- RAISE NOTICE ' % and multi-home linked records were all copy_location-excluded ... ', core_result.records;
+                        excluded_count := excluded_count + 1;
+                        CONTINUE;
+                    END IF;
+                END IF;
+
+            END IF;
+
+            IF staff IS NULL OR NOT staff THEN
+
+                PERFORM 1
+                  FROM  asset.opac_visible_copies
+                  WHERE circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                        AND record IN ( SELECT * FROM unnest( core_result.records ) )
+                  LIMIT 1;
+
+                IF NOT FOUND THEN
+                    PERFORM 1
+                      FROM  biblio.peer_bib_copy_map pr
+                            JOIN asset.opac_visible_copies cp ON (cp.copy_id = pr.target_copy)
+                      WHERE cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                            AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
+                      LIMIT 1;
+
+                    IF NOT FOUND THEN
+
+                        -- RAISE NOTICE ' % and multi-home linked records were all visibility-excluded ... ', core_result.records;
+                        excluded_count := excluded_count + 1;
+                        CONTINUE;
+                    END IF;
+                END IF;
+
+            ELSE
+
+                PERFORM 1
+                  FROM  asset.call_number cn
+                        JOIN asset.copy cp ON (cp.call_number = cn.id)
+                  WHERE NOT cn.deleted
+                        AND NOT cp.deleted
+                        AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                        AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
+                  LIMIT 1;
+
+                IF NOT FOUND THEN
+
+                    PERFORM 1
+                      FROM  biblio.peer_bib_copy_map pr
+                            JOIN asset.copy cp ON (cp.id = pr.target_copy)
+                      WHERE NOT cp.deleted
+                            AND cp.circ_lib IN ( SELECT * FROM unnest( search_org_list ) )
+                            AND pr.peer_record IN ( SELECT * FROM unnest( core_result.records ) )
+                      LIMIT 1;
+
+                    IF NOT FOUND THEN
+
+                        PERFORM 1
+                          FROM  asset.call_number cn
+                                JOIN asset.copy cp ON (cp.call_number = cn.id)
+                          WHERE cn.record IN ( SELECT * FROM unnest( core_result.records ) )
+                                AND NOT cp.deleted
+                          LIMIT 1;
+
+                        IF NOT FOUND THEN
+                            -- Recheck Located URI visibility in the case of no "foreign" copies
+                            PERFORM 1
+                              FROM  asset.call_number cn
+                                    JOIN asset.uri_call_number_map map ON (map.call_number = cn.id)
+                                    JOIN asset.uri uri ON (map.uri = uri.id)
+                              WHERE NOT cn.deleted
+                                    AND cn.label = '##URI##'
+                                    AND uri.active
+                                    AND cn.record IN ( SELECT * FROM unnest( core_result.records ) )
+                                    AND cn.owning_lib NOT IN ( SELECT * FROM unnest( luri_org_list ) )
+                              LIMIT 1;
+
+                            IF FOUND THEN
+                                -- RAISE NOTICE ' % were excluded for foreign located URIs... ', core_result.records;
+                                excluded_count := excluded_count + 1;
+                                CONTINUE;
+                            END IF;
+                        ELSE
+                            -- RAISE NOTICE ' % and multi-home linked records were all visibility-excluded ... ', core_result.records;
+                            excluded_count := excluded_count + 1;
+                            CONTINUE;
+                        END IF;
+                    END IF;
+
+                END IF;
+
+            END IF;
+
+        END IF;
+
+        visible_count := visible_count + 1;
+
+        current_res.id = core_result.id;
+        current_res.rel = core_result.rel;
+
+        tmp_int := 1;
+        IF metarecord THEN
+            SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
+        END IF;
+
+        IF tmp_int = 1 THEN
+            current_res.record = core_result.records[1];
+        ELSE
+            current_res.record = NULL;
+        END IF;
+
+        RETURN NEXT current_res;
+
+        IF visible_count % 1000 = 0 THEN
+            -- RAISE NOTICE ' % visible so far ... ', visible_count;
+        END IF;
+
+    END LOOP;
+
+    current_res.id = NULL;
+    current_res.rel = NULL;
+    current_res.record = NULL;
+    current_res.total = total_count;
+    current_res.checked = check_count;
+    current_res.deleted = deleted_count;
+    current_res.visible = visible_count;
+    current_res.excluded = excluded_count;
+
+    CLOSE core_cursor;
+
+    RETURN NEXT current_res;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.unapi.fenced_located_uris.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.unapi.fenced_located_uris.sql
new file mode 100644 (file)
index 0000000..733a8dc
--- /dev/null
@@ -0,0 +1,79 @@
+BEGIN;
+
+CREATE OR REPLACE FUNCTION evergreen.located_uris (
+    bibid BIGINT[], 
+    ouid INT,
+    pref_lib INT DEFAULT NULL
+) RETURNS TABLE (id BIGINT, name TEXT, label_sortkey TEXT, rank INT) AS $$
+    WITH all_orgs AS (SELECT COALESCE( enabled, FALSE ) AS flag FROM config.global_flag WHERE name = 'opac.located_uri.act_as_copy')
+    SELECT DISTINCT ON (id) * FROM (
+    SELECT acn.id, COALESCE(aou.name,aoud.name), acn.label_sortkey, evergreen.rank_ou(aou.id, $2, $3) AS pref_ou
+      FROM asset.call_number acn
+           INNER JOIN asset.uri_call_number_map auricnm ON acn.id = auricnm.call_number
+           INNER JOIN asset.uri auri ON auri.id = auricnm.uri
+           LEFT JOIN actor.org_unit_ancestors( COALESCE($3, $2) ) aou ON (acn.owning_lib = aou.id)
+           LEFT JOIN actor.org_unit_descendants( COALESCE($3, $2) ) aoud ON (acn.owning_lib = aoud.id),
+           all_orgs
+      WHERE acn.record = ANY ($1)
+          AND acn.deleted IS FALSE
+          AND auri.active IS TRUE
+          AND ((NOT all_orgs.flag AND aou.id IS NOT NULL AND aou.id IN 
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path($2, (SELECT substring(value, '\d+')::INT 
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2))) OR aou.id IN
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2))))) 
+                OR (all_orgs.flag AND COALESCE(aou.id,aoud.id) IS NOT NULL AND (
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path($2, (SELECT substring(value, '\d+')::INT  
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = $2))) OR 
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2)), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = COALESCE($3, $2)))))))
+    UNION
+    SELECT acn.id, COALESCE(aou.name,aoud.name) AS name, acn.label_sortkey, evergreen.rank_ou(aou.id, $2, $3) AS pref_ou
+      FROM asset.call_number acn
+           INNER JOIN asset.uri_call_number_map auricnm ON acn.id = auricnm.call_number
+           INNER JOIN asset.uri auri ON auri.id = auricnm.uri
+           LEFT JOIN actor.org_unit_ancestors( $2 ) aou ON (acn.owning_lib = aou.id)
+           LEFT JOIN actor.org_unit_descendants( $2 ) aoud ON (acn.owning_lib = aoud.id),
+           all_orgs
+      WHERE acn.record = ANY ($1)
+          AND acn.deleted IS FALSE
+          AND auri.active IS TRUE
+          AND ((NOT all_orgs.flag AND aou.id IS NOT NULL and aou.id IN
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path($2, (SELECT substring(value, '\d+')::INT 
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2))) OR aou.id IN
+                (SELECT id FROM actor.org_unit_ancestor_fenced_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2))))) 
+                OR (all_orgs.flag AND COALESCE(aou.id,aoud.id) IS NOT NULL AND (
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path($2, (SELECT substring(value, '\d+')::INT  
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = $2), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = $2))) OR 
+                COALESCE(aou.id, aoud.id) IN
+                    (SELECT id FROM actor.org_unit_full_path(COALESCE($3, $2), (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_anc_vis_depth' AND org_unit = COALESCE($3, $2)), 
+                (SELECT substring(value, '\d+')::INT
+                    FROM actor.org_unit_setting
+                    WHERE name = 'opac.luri_des_vis_depth' AND org_unit = COALESCE($3, $2))))))))x
+    ORDER BY id, pref_ou DESC;
+$$
+LANGUAGE SQL STABLE;
+
+COMMIT;
index bb9c472..6d6e792 100644 (file)
@@ -297,6 +297,11 @@ END;
                                                                 </td>
                                                             </tr>
                                                         [% END %]
+                                                        [% 
+                                                        IF ctx.search_ou;
+                                                            limit_uris_displayed = ctx.get_org_setting(ctx.search_ou, 'opac.luri_results_uri_limit');
+                                                        END;
+                                                        %]
                                                         [% FOR uri IN args.uris %]
                                                             <tr name='bib_uri_list' class='result_table_title_cell'>
                                                                 <td valign='top'>
@@ -304,6 +309,22 @@ END;
                                                                 </td>
                                                                 <td><a href="[% uri.href %]">[% uri.link | html %]</a>[% ' - ' _ uri.note | html IF uri.note %]</td>
                                                             </tr>
+                                                            [%
+                                                            IF loop.count >= limit_uris_displayed;
+                                                            %]
+                                                                <tr>
+                                                                    <td>
+                                                                        <a class='record_title search_link' name='record_[% rec.id %]'
+                                                                            href="[% record_url %]"
+                                                                            [% html_text_attr('title', l('Display record details for "[_1]"', attrs.title)) %]>
+                                                                            More...
+                                                                        </a>
+                                                                    </td>
+                                                                </tr>
+                                                            [%
+                                                                LAST;
+                                                            END;
+                                                            %]
                                                             [% END %]
                                                          [% END %]
                                                             [%- IF args.holdings.size > 0;