From 45e2d151b31f4ce6ed444a21894285ae265ac28c Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Fri, 14 Dec 2012 13:49:51 -0500
Subject: [PATCH] Set up links to collection view rather than record view for
 appropriate records when collections are enabled.

---
 config/vufind/config.ini                      | 10 +++
 languages/en-gb.ini                           |  1 +
 languages/en.ini                              |  1 +
 .../VuFind/Hierarchy/TreeDataSource/Solr.php  |  6 +-
 module/VuFind/src/VuFind/Record/Router.php    | 20 ++++-
 .../src/VuFind/RecordDriver/SolrDefault.php   | 87 +++++++++++++++++++
 module/VuFind/xsl/Hierarchy/RecordList.xsl    | 17 +++-
 module/VuFind/xsl/Hierarchy/RecordTree.xsl    | 13 ++-
 themes/blueprint/css/styles.css               | 14 +++
 .../SolrDefault/result-list.phtml             | 10 +++
 themes/jquerymobile/css/styles.css            | 14 +++
 11 files changed, 187 insertions(+), 6 deletions(-)

diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index 7be4d08207d..8439384ecad 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -779,6 +779,16 @@ HMACkey = mySuperSecretValue
 ; Default file_permission seems to be 0600.
 ;file_permission = 0600
 
+; This section controls the "Collections" module -- the special view for records
+; that represent collections, and the mechanism for browsing these records.
+; Collections are only supported in the blueprint and jquerymobile themes.
+;[Collections]
+; Control whether or not the collections module is enabled in search results.
+; If set to true any search results which are collection level items will
+; link to the respective collections page rather than the record page
+; (default = false).
+;collections = true
+
 ; This section addresses hierarchical records in the Solr index
 [Hierarchy]
 ; Name of hierarchy driver to use if no value is specified in the hierarchytype
diff --git a/languages/en-gb.ini b/languages/en-gb.ini
index ad18485e28a..d287172d2c9 100644
--- a/languages/en-gb.ini
+++ b/languages/en-gb.ini
@@ -611,6 +611,7 @@ ils_offline_login_message = "Your account details will be unavailable during thi
 ils_offline_status = "Our Library Management System is currently under maintenance."
 ils_offline_title = "System Under Maintenance"
 in = in
+in_collection_label = "In collection:"
 information = "Information"
 items = items
 items_added_to_bookbag = "item(s) added to your Book Bag"
diff --git a/languages/en.ini b/languages/en.ini
index 165051a4df2..c92f7e40125 100644
--- a/languages/en.ini
+++ b/languages/en.ini
@@ -611,6 +611,7 @@ ils_offline_login_message = "Your account details will be unavailable during thi
 ils_offline_status = "Our Library Management System is currently under maintenance."
 ils_offline_title = "System Under Maintenance"
 in = in
+in_collection_label = "In collection:"
 information = "Information"
 items = items
 items_added_to_bookbag = "item(s) added to your Book Bag"
diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
index 77978d2c9d6..f5d200a31b5 100644
--- a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
+++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
@@ -106,9 +106,10 @@ class Solr extends AbstractBase
             $xml = file_get_contents($cacheFile);
         } else {
             $starttime = microtime(true);
+            $isCollection = $top->isCollection() ? "true" : "false";
             $xml = '<root><item id="' .
                 htmlspecialchars($id) .
-                '">' .
+                '" isCollection="' . $isCollection . '">' .
                 '<content><name>' . htmlspecialchars($top->getTitle()) .
                 '</name></content>';
             $count = 0;
@@ -160,8 +161,9 @@ class Solr extends AbstractBase
 
             $this->debug("$parentID: " . $current->getUniqueID());
             $xmlNode = '';
+            $isCollection = $current->isCollection() ? "true" : "false";
             $xmlNode .= '<item id="' . htmlspecialchars($current->getUniqueID()) .
-                '"><content><name>' .
+                '" isCollection="' . $isCollection . '"><content><name>' .
                 htmlspecialchars($current->getTitle()) . '</name></content>';
             $xmlNode .= $this->getChildren($current->getUniqueID(), $count);
             $xmlNode .= '</item>';
diff --git a/module/VuFind/src/VuFind/Record/Router.php b/module/VuFind/src/VuFind/Record/Router.php
index 5ac79183c56..1d7d5e76dd5 100644
--- a/module/VuFind/src/VuFind/Record/Router.php
+++ b/module/VuFind/src/VuFind/Record/Router.php
@@ -63,9 +63,27 @@ class Router
      */
     public static function getTabRouteDetails($driver, $tab = null)
     {
-        return static::getRouteDetails(
+        $route = static::getRouteDetails(
             $driver, '', empty($tab) ? array() : array('tab' => $tab)
         );
+
+        // If collections are active and the record route was selected, we need
+        // to check if the driver is actually a collection; if so, we should switch
+        // routes.
+        if ('record' == $route['route']) {
+            $config = \VuFind\Config\Reader::getConfig();
+            if (isset($config->Collections->collections)
+                && $config->Collections->collections
+            ) {
+                if (is_object($driver)
+                    && true === $driver->tryMethod('isCollection')
+                ) {
+                    $route['route'] = 'collection';
+                }
+                // TODO: make routing work correctly in non-object $driver case
+            }
+        }
+        return $route;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
index acea10715c5..d06fb32fe55 100644
--- a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
+++ b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
@@ -1129,6 +1129,93 @@ class SolrDefault extends AbstractBase
             ? $this->fields['hierarchy_top_title'] : array();
     }
 
+    /**
+     * Get an associative array (id => title) of collections containing this record.
+     *
+     * @return array
+     */
+    public function getContainingCollections()
+    {
+        // If collections are disabled or this record is not part of a hierarchy, go
+        // no further....
+        $config = ConfigReader::getConfig();
+        if (!isset($config->Collections->collections)
+            || !$config->Collections->collections
+            || !($hierarchyDriver = $this->getHierarchyDriver())
+        ) {
+            return false;
+        }
+
+        // Initialize some variables needed within the switch below:
+        $isCollection = $this->isCollection();
+        $titles = $ids = array();
+
+        // Check config setting for what constitutes a collection, act accordingly:
+        switch ($hierarchyDriver->getCollectionLinkType()) {
+        case 'All':
+            if (isset($this->fields['hierarchy_parent_title'])
+                && isset($this->fields['hierarchy_parent_id'])
+            ) {
+                $titles = $this->fields['hierarchy_parent_title'];
+                $ids = $this->fields['hierarchy_parent_id'];
+            }
+            break;
+        case 'Top':
+            if (isset($this->fields['hierarchy_top_title'])
+                && isset($this->fields['hierarchy_top_id'])
+            ) {
+                foreach ($this->fields['hierarchy_top_id'] as $i => $topId) {
+                    // Don't mark an item as its own parent -- filter out parent
+                    // collections whose IDs match that of the current collection.
+                    if (!$isCollection
+                        || $topId !== $this->fields['is_hierarchy_id']
+                    ) {
+                        $ids[] = $topId;
+                        $titles[] = $this->fields['hierarchy_top_title'][$i];
+                    }
+                }
+            }
+            break;
+        }
+
+        // Map the titles and IDs to a useful format:
+        $c = count($ids);
+        $retVal = array();
+        for ($i = 0; $i < $c; $i++) {
+            $retVal[$ids[$i]] = $titles[$i];
+        }
+        return $retVal;
+    }
+
+    /**
+     * Get the value of whether or not this is a collection level record
+     *
+     * @return bool
+     */
+    public function isCollection()
+    {
+        if (!($hierarchyDriver = $this->getHierarchyDriver())) {
+            // Not a hierarchy type record
+            return false;
+        }
+
+        // Check config setting for what constitutes a collection
+        switch ($hierarchyDriver->getCollectionLinkType()) {
+        case 'All':
+            return (isset($this->fields['is_hierarchy_id']));
+        case 'Top':
+            return isset($this->fields['is_hierarchy_title'])
+                && isset($this->fields['is_hierarchy_id'])
+                && in_array(
+                    $this->fields['is_hierarchy_id'],
+                    $this->fields['hierarchy_top_id']
+                );
+        default:
+            // Default to not be a collection level record
+            return false;
+        }
+    }
+
     /**
      * Get the positions of this item within parent collections.  Returns an array
      * of parent ID => sequence number.
diff --git a/module/VuFind/xsl/Hierarchy/RecordList.xsl b/module/VuFind/xsl/Hierarchy/RecordList.xsl
index 71aa6969c06..adc4fdd1e05 100644
--- a/module/VuFind/xsl/Hierarchy/RecordList.xsl
+++ b/module/VuFind/xsl/Hierarchy/RecordList.xsl
@@ -13,12 +13,25 @@
           <xsl:variable name="id" select="@id" />
           <li>
           <xsl:attribute name="id">tree-<xsl:value-of select="$id"/></xsl:attribute>
+          <xsl:variable name="isCollection" select="@isCollection" />
           <xsl:attribute name="class">
+          <xsl:if test="$isCollection = 'true'">hierarchy </xsl:if>
           <xsl:choose>
-            <xsl:when test="$recordID = $id">currentRecord</xsl:when>
+            <xsl:when test="$isCollection = 'true' and $recordID = $id">currentHierarchy</xsl:when>
+            <xsl:when test="$isCollection != 'true' and $recordID = $id">currentRecord</xsl:when>
           </xsl:choose>
           </xsl:attribute>
-        <xsl:variable name="baseModule">Record</xsl:variable>
+        <xsl:variable name="baseModule">
+          <xsl:choose>
+            <xsl:when test="$context = 'Record'">
+                <xsl:choose>
+                    <xsl:when test="$isCollection = 'true'">Collection</xsl:when>
+                    <xsl:otherwise>Record</xsl:otherwise>
+                </xsl:choose>
+            </xsl:when>
+            <xsl:otherwise>Collection</xsl:otherwise>
+          </xsl:choose>
+        </xsl:variable>
           <a href="{$baseURL}/{$baseModule}/{$id}/HierarchyTree?hierarchy={$collectionID}&amp;recordID={$id}#tree-{$id}" title="{$titleText}">
               <xsl:value-of select="./content/name" />
           </a>
diff --git a/module/VuFind/xsl/Hierarchy/RecordTree.xsl b/module/VuFind/xsl/Hierarchy/RecordTree.xsl
index 03d39bfd63e..88e41dfd11c 100644
--- a/module/VuFind/xsl/Hierarchy/RecordTree.xsl
+++ b/module/VuFind/xsl/Hierarchy/RecordTree.xsl
@@ -10,7 +10,18 @@
 
     <xsl:template match="item">
         <xsl:variable name="id" select="@id" />
-        <xsl:variable name="baseModule">Record</xsl:variable>
+        <xsl:variable name="isCollection" select="@isCollection" />
+        <xsl:variable name="baseModule">
+          <xsl:choose>
+            <xsl:when test="$context = 'Record'">
+                <xsl:choose>
+                    <xsl:when test="$isCollection = 'true'">Collection</xsl:when>
+                    <xsl:otherwise>Record</xsl:otherwise>
+                </xsl:choose>
+            </xsl:when>
+            <xsl:otherwise>Collection</xsl:otherwise>
+          </xsl:choose>
+        </xsl:variable>
         <item>
           <content>
               <name class="JSTreeID"><xsl:value-of select="$id"/></name>
diff --git a/themes/blueprint/css/styles.css b/themes/blueprint/css/styles.css
index 32fdf39f6e5..1900d85d4b2 100644
--- a/themes/blueprint/css/styles.css
+++ b/themes/blueprint/css/styles.css
@@ -1904,6 +1904,20 @@ div#closeContextHelp:active {
     background-position: 0 0.25em;
 }
 
+#hierarchyTree #treeList li.hierarchy {
+    background-image:url(../images/fugue/collection.png);
+    background-repeat: no-repeat;
+    padding: 0.25em 0 0 23px;
+    background-position: 0 0.25em;
+}
+
+#hierarchyTree #treeList li.currentHierarchy {
+    background-image:url(../images/fugue/collectionCurrent.png);
+    background-repeat: no-repeat;
+    padding: 0.25em 0 0 23px;
+    background-position: 0 0.25em;
+}
+
 #hierarchyTree #treeList li.currentHierarchy > a, #hierarchyTree #treeList li.currentRecord > a {
     color: #000;
     font-weight: bold;
diff --git a/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml b/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml
index 0e3dad9504e..8fbac62c3df 100644
--- a/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml
+++ b/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml
@@ -42,6 +42,16 @@
         <?=!empty($summAuthor) ? '<br />' : ''?>
         <?=$this->transEsc('Published') . ' ' . $this->escapeHtml($summDate[0])?>
       <? endif; ?>
+      <? $summInCollection = $this->driver->getContainingCollections(); if (!empty($summInCollection)): ?>
+        <? foreach ($summInCollection as $collId => $collText): ?>
+          <div>
+            <b><?=$this->transEsc("in_collection_label")?></b>
+            <a class="collectionLinkText" href="<?=$this->url('collection', array('id' => $collId))?>?recordID=<?=urlencode($this->driver->getUniqueID())?>">
+               <?=$this->escapeHtml($collText)?>
+            </a>
+          </div>
+        <? endforeach; ?>
+      <? endif; ?>
     </div>
 
     <div class="last">
diff --git a/themes/jquerymobile/css/styles.css b/themes/jquerymobile/css/styles.css
index 263a3aae887..9f04686ed86 100644
--- a/themes/jquerymobile/css/styles.css
+++ b/themes/jquerymobile/css/styles.css
@@ -267,6 +267,20 @@ p.citationText {
     background-position: 0 0.25em;
 }
 
+#hierarchyTree #treeList li.hierarchy {
+    background-image:url(../images/fugue/collection.png);
+    background-repeat: no-repeat;
+    padding: 0.25em 0 0 23px;
+    background-position: 0 0.25em;
+}
+
+#hierarchyTree #treeList li.currentHierarchy {
+    background-image:url(../images/fugue/collectionCurrent.png);
+    background-repeat: no-repeat;
+    padding: 0.25em 0 0 23px;
+    background-position: 0 0.25em;
+}
+
 #hierarchyTree #treeList li.currentHierarchy > a, #hierarchyTree #treeList li.currentRecord > a {
     color: #000;
     font-weight: bold;
-- 
GitLab