diff --git a/module/VuDL/src/VuDL/Connection/AbstractBase.php b/module/VuDL/src/VuDL/Connection/AbstractBase.php index 30e9372a8d26335d1e404c53945e9b1611915bae..4ed1d0edbe6b32b8acbd3d3591481b2aa0da698f 100644 --- a/module/VuDL/src/VuDL/Connection/AbstractBase.php +++ b/module/VuDL/src/VuDL/Connection/AbstractBase.php @@ -53,7 +53,7 @@ class AbstractBase implements \VuFindHttp\HttpServiceAwareInterface * @var array */ protected $parentLists = array(); - + /** * HTTP service * @@ -70,7 +70,7 @@ class AbstractBase implements \VuFindHttp\HttpServiceAwareInterface { $this->config = $config; } - + /** * Set the HTTP service to be used for HTTP requests. * @@ -94,7 +94,7 @@ class AbstractBase implements \VuFindHttp\HttpServiceAwareInterface ? $this->config->General->root_id : null; } - + /** * Get VuDL detail fields. * @@ -106,7 +106,7 @@ class AbstractBase implements \VuFindHttp\HttpServiceAwareInterface ? $this->config->Details->toArray() : array(); } - + /** * Get Fedora Page Length. * @@ -135,54 +135,88 @@ class AbstractBase implements \VuFindHttp\HttpServiceAwareInterface if (empty($detailsList)) { throw new \Exception('Missing [Details] in VuDL.ini'); } + $details = array(); foreach ($detailsList as $key=>$title) { $keys = explode(',', $key); - foreach ($keys as $k) { - $fields[$k] = $title; - } - // Link up to top combined field - if (count($keys) > 1) { - $combinedFields[] = $keys; + $field = false; + for ($i=0;$i<count($keys);$i++) { + if (isset($record[$keys[$i]])) { + $field = $keys[$i]; + break; + } } - } - // Pool details - $details = array(); - foreach ($fields as $key=>$title) { - if (isset($record[$key])) { - $details[$key] = array('title' => $title, 'value' => $record[$key]); + if (false === $field) { + continue; } - } - // Rearrange combined fields - foreach ($combinedFields as $fields) { - $main = $fields[0]; - if (!isset($details[$main]['value']) - || !is_array($details[$main]['value']) - ) { - if (isset($details[$main]['value'])) { - $details[$main]['value'] = array($details[$main]['value']); - } else { - $details[$main]['value'] = array(); + if (count($keys) == 1) { + if (isset($record[$keys[0]])) { + $details[$field] = array( + 'title' => $title, + 'value' => $record[$keys[0]] + ); } - } - for ($i=1;$i<count($fields);$i++) { - if (isset($details[$fields[$i]])) { - if (!isset($details[$main]['title'])) { - $details[$main]['title'] = $details[$fields[$i]]['title']; - } - if (is_array($details[$main]['value'])) { - foreach ($details[$fields[$i]]['value'] as $value) { - $details[$main]['value'][] = $value; + } else { + $value = array(); + $field = false; + foreach ($keys as $k) { + if (isset($record[$k])) { + if (is_array($record[$k])) { + $value = array_merge($value, $record[$k]); + } else { + $value[] = $record[$k]; } - } else { - $details[$main]['value'][] = $details[$fields[$i]]['value']; } - unset($details[$fields[$i]]); } - } - if (empty($details[$main]['value'])) { - unset($details[$main]); + $details[$field] = array( + 'title' => $title, + 'value' => $record[$keys[0]] + ); } } return $details; } + + /** + * A method to search from the root id down to the current record + * creating multiple breadcrumb paths along the way + * + * @param array $tree Array of parents by id with title and array of children + * @param string $id Target id to stop at + * + * @return array Array of arrays with parents in order + */ + protected function traceParents($tree, $id) + { + // BFS from top (root id) to target $id + $queue = array( + array( + 'id' => $this->getRootId(), + 'path' => array() + ) + ); + $ret = array(); + while (!empty($queue)) { + $current = array_shift($queue); + $record = $tree[$current['id']]; + $path = $current['path']; + if ($current['id'] != $this->getRootId()) { + $path[$current['id']] = $record['title']; + } + foreach ($record['children'] as $cid) { + // At target + if ($cid == $id) { + array_push($ret, $path); + } else { // Add to queue for more + array_push( + $queue, + array( + 'id' => $cid, + 'path' => $path + ) + ); + } + } + } + return $ret; + } } \ No newline at end of file diff --git a/module/VuDL/src/VuDL/Connection/Fedora.php b/module/VuDL/src/VuDL/Connection/Fedora.php index 15a383ba455d88b287070cfceff16bb825d9359d..4fdabca5a63c631eeb78d2fc9ef2625bacdd8c12 100644 --- a/module/VuDL/src/VuDL/Connection/Fedora.php +++ b/module/VuDL/src/VuDL/Connection/Fedora.php @@ -58,7 +58,7 @@ class Fedora extends AbstractBase ? $this->config->Fedora->url_base : null; } - + /** * Returns an array of classes for this object * @@ -157,7 +157,7 @@ class Fedora extends AbstractBase } return $details; } - + /** * Get an HTTP client * @@ -172,7 +172,7 @@ class Fedora extends AbstractBase } return new \Zend\Http\Client($url); } - + /** * Get an item's label * @@ -210,7 +210,7 @@ class Fedora extends AbstractBase if (empty($list[$i])) { continue; } - list($id, $title) = explode(',', $list[$i], 2); + list($id,) = explode(',', $list[$i], 2); $items[] = $id; } return $items; @@ -235,7 +235,7 @@ class Fedora extends AbstractBase $list = explode("\n", $response->getBody()); return $list[1]; } - + /** * Returns file contents of the structmap, our most common call * @@ -316,6 +316,7 @@ class Fedora extends AbstractBase if (isset($this->parentLists[$id])) { return $this->parentLists[$id]; } + // Walk to get all parents to root $query = 'select $child $parent $parentTitle from <#ri> ' . 'where walk (' . '<info:fedora/' .$id. '> ' @@ -323,52 +324,27 @@ class Fedora extends AbstractBase . '$parent ' . 'and $child <fedora-rels-ext:isMemberOf> $parent) ' . 'and $parent <fedora-model:label> $parentTitle'; + // Parse out relationships $response = $this->query($query); - $list = explode("\n", $response->getBody()); + $list = explode("\n", trim($response->getBody(), "\n")); $tree = array(); - $items = array(); - $roots = array(); for ($i=1;$i<count($list);$i++) { - if (empty($list[$i])) { - continue; - } list($child, $parent, $title) = explode(',', substr($list[$i], 12), 3); $parent = substr($parent, 12); - if ($parent == $this->getRootId()) { - $roots[] = $child; - continue; - } - if ($child == $this->getRootId()) { - continue; - } - if (isset($tree[$parent])) { - $tree[$parent][] = $child; - } else { - $tree[$parent] = array($child); - } - $items[$parent] = str_replace('""', '"', trim($title, '" ')); - } - $ret = array(); - $queue = array(); - foreach ($roots as $root) { - $queue[] = array($root, array()); - } - while ($path = array_pop($queue)) { - $tid = $path[0]; - while ($tid != $id) { - $path[1][$tid] = $items[$tid]; - for ($i=1;$i<count($tree[$tid]);$i++) { - $queue[] = array($tree[$tid][$i], $path[1]); - } - $tid = $tree[$tid][0]; + if (!isset($tree[$parent])) { + $tree[$parent] = array( + 'children' => array(), + 'title' => $title + ); } - $ret[] = array_reverse($path[1]); + $tree[$parent]['children'][] = $child; } - //var_dump('---', $ret); + $ret = $this->traceParents($tree, $id); + // Store in cache $this->parentLists[$id] = $ret; return $ret; } - + /** * Get Fedora Query URL. * @@ -446,7 +422,32 @@ class Fedora extends AbstractBase } return array(); } - + + /** + * Get copyright URL and compare it to special cases from VuDL.ini + * + * @param array $setLicenses ids are urls, then abbrev + * parsed in details.phtml later + * + * @return array + */ + public function getCopyright($id, $setLicenses) + { + $check = $this->getDatastreamHeaders($id, 'LICENSE'); + if (!strpos($check[0], '404')) { + $xml = $this->getDatastreamContent($id, 'LICENSE'); + preg_match('/xlink:href="(.*?)"/', $xml, $license); + $license = $license[1]; + foreach ($setLicenses as $tell=>$value) { + if (strpos($license, $tell)) { + return array($license, $value); + } + } + return array($license, false); + } + return null; + } + /** * Consolidation of Zend Client calls * diff --git a/module/VuDL/src/VuDL/Connection/Solr.php b/module/VuDL/src/VuDL/Connection/Solr.php index 4b7486b6df955fedf47259682297ede371bfe59b..175bb3075e989f5a579f9984413fa784660833a6 100644 --- a/module/VuDL/src/VuDL/Connection/Solr.php +++ b/module/VuDL/src/VuDL/Connection/Solr.php @@ -89,7 +89,7 @@ class Solr extends AbstractBase } return null; } - + /** * Get details from Solr * @@ -116,7 +116,7 @@ class Solr extends AbstractBase } return null; } - + /** * Get an item's label * @@ -131,7 +131,7 @@ class Solr extends AbstractBase new ParamBag( array( 'q' => 'id:"'.$id.'"', - 'fl' => $labelField, + 'fl' => $labelField, ) ) ); @@ -142,7 +142,7 @@ class Solr extends AbstractBase } return null; } - + /** * Tuple call to return and parse a list of members... * @@ -203,7 +203,7 @@ class Solr extends AbstractBase } return null; } - + /** * Returns file contents of the structmap, our most common call * @@ -257,92 +257,75 @@ class Solr extends AbstractBase if (isset($this->parentLists[$id])) { return $this->parentLists[$id]; } - // Get info on our record - $origin = $this->search( - new ParamBag( - array( - 'q' => 'id:"'.$id.'"', - 'fl' => 'hierarchy_all_parents_str_mv,' - . 'hierarchy_top_id,' - . 'title_short,' - . 'hierarchy_parent_id,' - . 'hierarchy_parent_title', + $queue = array($id); + $tree = array(); + while (!empty($queue)) { + $current = array_shift($queue); + $response = $this->search( + new ParamBag( + array( + 'q' => 'id:"'.$current.'"', + 'fl' => 'hierarchy_parent_id,hierarchy_parent_title', + ) ) - ) - ); - $origin = json_decode($origin); - // These are our targets - $top = $origin->response->docs[0]->hierarchy_top_id; - // If we have results, find the structure - if ($origin->response->numFound > 0) { - // Immediate parents - $parents = array_unique( - $origin->response->docs[0]->hierarchy_all_parents_str_mv ); - if (empty($parents)) { + $data = json_decode($response); + if ($current == $id && $data->response->numFound == 0) { return null; } - $ret = array(); - $hierarchyParents = $origin->response->docs[0]->hierarchy_parent_id; - foreach ($hierarchyParents as $i=>$parent) { - $ret[] = array( - $origin->response->docs[0]->hierarchy_parent_id[$i] - => $origin->response->docs[0]->hierarchy_parent_title[$i] - ); - } - $current = 0; - $last = key($ret[0]); - $limit = 50; - while ($limit-- && $current < count($ret)) { - $path = $ret[$current]; - $partOf = $this->search( - new ParamBag( - array( - 'q' => 'id:"'.$last.'"', - 'fl' => 'hierarchy_top_id,' - . 'hierarchy_parent_id,' - . 'hierarchy_parent_title', - ) - ) - ); - $partOf = json_decode($partOf); - $parentIDs = $partOf->response->docs[0]->hierarchy_parent_id; - $parentTitles = $partOf->response->docs[0]->hierarchy_parent_title; - $topIDs = $partOf->response->docs[0]->hierarchy_top_id; - $count = 0; - foreach ($parentIDs as $i=>$pid) { - $ptitle = trim($parentTitles[$i]); - if (in_array($pid, $parents)) { - if ($count == 0) { - $ret[$current][$pid] = $ptitle; - if (in_array($pid, $top)) { - $current ++; - if ($current == count($ret)) { - break 2; - } - end($ret[$current]); - $last = key($ret[$current]); - } else { - foreach ($topIDs as $tid) { - if (!in_array($tid, $top)) { - $top[] = $tid; - } - } - $last = $pid; - } - } else { - $path2 = $path; - $path2[$pid] = $ptitle; - $ret[] = $path2; - } - $count ++; + // Get info on our record + $parents = $data->response->docs[0]; + if ($current != $this->getRootId()) { + foreach ($parents->hierarchy_parent_id as $i=>$cid) { + array_push($queue, $cid); + if (!isset($tree[$cid])) { + $tree[$cid] = array( + 'children' => array(), + 'title' => $parents->hierarchy_parent_title[$i] + ); } + $tree[$cid]['children'][] = $current; } } - $this->parentLists[$id] = $ret; - return $ret; } - return null; + $ret = $this->traceParents($tree, $id); + // Store in cache + $this->parentLists[$id] = $ret; + return $ret; + } + + /** + * Get copyright URL and compare it to special cases from VuDL.ini + * + * @param array $setLicenses ids are urls, then abbrev + * parsed in details.phtml later + * + * @return array + */ + public function getCopyright($id, $setLicenses) + { + $licenseField = 'license.mdRef'; + $response = $this->search( + new ParamBag( + array( + 'q' => 'id:"'.$id.'"', + 'fl' => $licenseField, + ) + ) + ); + $data = json_decode($response); + $docs = $data->response->docs[0]; + if ($data->response->numFound == 0 || !isset($docs->$licenseField)) { + return null; + } + $license = $docs->$licenseField; + $license = $license[0]; + foreach ($setLicenses as $tell=>$value) { + if (strpos($license, $tell)) { + return array($license, $value); + } + } + return array($license, false); } /** @@ -365,7 +348,7 @@ class Solr extends AbstractBase $response = $this->solr->search($paramBag); // Reapply the global filters $map->setParameters('select', 'appends', $params->getArrayCopy()); - + return $response; } } diff --git a/module/VuDL/src/VuDL/Controller/VudlController.php b/module/VuDL/src/VuDL/Controller/VudlController.php index 49f06b571d1850b96ad31511bced50a83a17ecbc..6b3a59587d1ab338c5eed43db8c141dc06dde9a2 100644 --- a/module/VuDL/src/VuDL/Controller/VudlController.php +++ b/module/VuDL/src/VuDL/Controller/VudlController.php @@ -62,7 +62,7 @@ class VudlController extends AbstractVuDL */ protected function getRoot($id) { - $parents = $this->getConnector()->getParentList($id); + $parents = array_reverse($this->getConnector()->getParentList($id)); foreach (array_keys($parents[0]) as $i) { if (in_array( 'ResourceCollection', @@ -263,20 +263,9 @@ class VudlController extends AbstractVuDL $fileDetails = $this->getConnector()->getDetails($root, true); // Copyright information - $check = $this->getConnector()->getDatastreamHeaders($root, 'LICENSE'); - if (!strpos($check[0], '404')) { - $xml = $this->getConnector()->getDatastreamContent($root, 'LICENSE'); - preg_match('/xlink:href="(.*?)"/', $xml, $license); - $fileDetails['license'] = $license[1]; - $fileDetails['special_license'] = false; - $licenseValues = $this->getLicenses(); - foreach ($licenseValues as $tell=>$value) { - if (strpos($fileDetails['license'], $tell)) { - $fileDetails['special_license'] = $value; - break; - } - } - } + list($fileDetails['license'], $fileDetails['special_license']) + = $this->getConnector()->getCopyright($root, $this->getLicenses()); + $view->details = $fileDetails; // Get ids for all files diff --git a/themes/bootstrap/templates/breadcrumbs/multi.phtml b/themes/bootstrap/templates/breadcrumbs/multi.phtml index 9819107c852a0fdbeb9edc8c26e054f94a4278da..e62fa479a44beaba1c65f17cfd91d24d8d60dd14 100644 --- a/themes/bootstrap/templates/breadcrumbs/multi.phtml +++ b/themes/bootstrap/templates/breadcrumbs/multi.phtml @@ -5,7 +5,7 @@ <ul class="dropdown-menu" role="menu"> <? foreach ($this->layout()->breadcrumbs as $trail): ?> <ul class="inline" style="margin:0 .5em;white-space:nowrap"> - <? foreach (array_reverse($trail) as $id=>$title): ?> + <? foreach ($trail as $id=>$title): ?> <li><span class="muted">></span> <a href="<?=$this->url('vudl-record', array('id'=>$id))?>"><?=$title ?></a></li> <? endforeach; ?> </ul> diff --git a/themes/bootstrap/templates/vudl/details.phtml b/themes/bootstrap/templates/vudl/details.phtml index bf72a8be084429aa54bef955ca1d45c55de06555..ef63a60fcb798c515527a5497933c3912d2e37de 100644 --- a/themes/bootstrap/templates/vudl/details.phtml +++ b/themes/bootstrap/templates/vudl/details.phtml @@ -24,6 +24,7 @@ <? // If we need exploding and backlinking ?> <? elseif($attr == 'topic' || $attr == 'series'): ?> + <? if(!is_array($val['value'])) $val['value'] = array($val['value']); ?> <? if(count($val['value']) > 1): ?><ul class="unstyled"><? endif ?> <? foreach($val['value'] as $v): ?> <? if(count($val['value']) > 1): ?><li><? endif ?> @@ -87,7 +88,7 @@ <a href="<?=$this->url('record', array('id'=>$this->id))?>"><i class="icon-link"></i> <?=$this->transEsc('More Details') ?></a><br/> <a href="<?=$this->url('vudl-record', array('id'=>$this->id))?>"><i class="icon-save"></i> <?=$this->transEsc('Permanent Link') ?></a><br/> <br/><br/> - <? if(isset($this->details['description'])): ?><p class="text-left"><?=html_entity_decode($this->details['description']['value'], ENT_COMPAT|ENT_HTML401, 'UTF-8') ?></p><? endif ?> + <? if(isset($this->details['description'])): ?><p class="text-left"><?=html_entity_decode($this->details['description']['value'], 2 /*ENT_COMPAT|ENT_HTML401*/, 'UTF-8') ?></p><? endif ?> </div> </div> </div> \ No newline at end of file