Skip to content

Commit

Permalink
Augment search results with additional data (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
demiankatz authored Jul 5, 2024
1 parent ef98998 commit 0b6c558
Show file tree
Hide file tree
Showing 12 changed files with 331 additions and 43 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 2.6.0 - 2024-07-05

### Added

- Ability to include additional details in search results.

### Changed

- Nothing.

### Removed

- Nothing.

### Fixed

- Nothing.

## 2.5.0 - 2024-03-21

### Added
Expand Down
29 changes: 29 additions & 0 deletions module/GeebyDeeby/config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@
// may be accessed by adding the group name as a subdirectory of the
// main /Links URL. (e.g. http://mysite.org/Links/MyGroupName).
],
'search_controls' => [
// You can add edition attribute IDs and labels here to make them
// available for display in search results:
'edition_attributes' => [
// 1234 => 'Show my example attribute',
],
],
],
'controller_plugins' => [
'aliases' => [
Expand Down Expand Up @@ -1204,6 +1211,28 @@
],
],
],
'search-creator-ajax' => [
'type' => 'Literal',
'options' => [
'route' => '/Search/CreatorAjax',
'defaults' => [
'__NAMESPACE__' => 'GeebyDeeby\Controller',
'controller' => 'Search',
'action' => 'creatorAjax',
],
],
],
'search-edition-attribute-ajax' => [
'type' => 'Literal',
'options' => [
'route' => '/Search/EditionAttributeAjax',
'defaults' => [
'__NAMESPACE__' => 'GeebyDeeby\Controller',
'controller' => 'Search',
'action' => 'editionAttributeAjax',
],
],
],
'series' => [
'type' => 'Segment',
'options' => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ protected function getDbTable($table)
}

/**
* Die with a JSON-encoded error message.
* Die with a JSON-encoded message.
*
* @param string $msg The message to send back.
* @param bool $success Success status
Expand Down
44 changes: 44 additions & 0 deletions module/GeebyDeeby/src/GeebyDeeby/Controller/SearchController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,50 @@ protected function tokenize($q)
return explode(' ', $q);
}

/**
* Retrieve creator details by AJAX.
*
* @return mixed
*/
public function creatorAjaxAction()
{
$nameHelper = $this->serviceLocator->get('ViewHelperManager')->get('showPerson');
$post = $this->params()->fromPost();
$ids = explode(',', $post['ids']);
$index = [];
foreach ($this->getDbTable('person')->getListForItemIds($ids) as $row) {
$index[$row['Item_ID']] ??= [];
$index[$row['Item_ID']][] = $row;
}
$formatPerson = function ($person) use ($nameHelper) {
return htmlspecialchars(($nameHelper)($person));
};
$response = [];
foreach ($index as $id => $data) {
$response[$id] = implode('; ', array_map($formatPerson, $data));
}
return $this->jsonDie($response, true);
}

/**
* Retrieve edition attribute details by AJAX.
*
* @return mixed
*/
public function editionAttributeAjaxAction()
{
$post = $this->params()->fromPost();
$attributeId = $post['attribute_id'];
$ids = explode(',', $post['ids']);
$result = [];
foreach ($this->getDbTable('editionsattributesvalues')->getAttributesForItem($ids, $attributeId) as $row) {
// We only want to display one value per item, so it doesn't matter if we overwrite existing data here:
$result[$row['Item_ID']] = '<b>' . htmlspecialchars($row['Editions_Attribute_Name']) . '</b>: '
. htmlspecialchars($row['Editions_Attribute_Value']);
}
return $this->jsonDie($result, true);
}

/**
* Keyword results
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
use Laminas\Db\Adapter\Adapter;
use Laminas\Db\RowGateway\RowGateway;

use function is_array;

/**
* Table Definition for Editions_Attributes_Values
*
Expand Down Expand Up @@ -82,13 +84,14 @@ public function getAttributesForEdition($editionID)
/**
* Get a list of attributes for the specified item.
*
* @param int $itemID Item ID
* @param int|int[] $itemID Item ID (or array of IDs)
* @param ?int $attributeID Attribute ID filter (null for all attributes)
*
* @return mixed
*/
public function getAttributesForItem($itemID)
public function getAttributesForItem($itemID, $attributeID = null)
{
$callback = function ($select) use ($itemID) {
$callback = function ($select) use ($itemID, $attributeID) {
$select->join(
['e' => 'Editions'],
'e.Edition_ID = Editions_Attributes_Values.Edition_ID'
Expand All @@ -103,7 +106,14 @@ public function getAttributesForItem($itemID)
. 'Editions_Attributes_Values.Editions_Attribute_ID'
);
$select->order(['ea.Display_Priority', 'ea.Editions_Attribute_Name']);
$select->where->equalTo('i.Item_ID', $itemID);
if (is_array($itemID)) {
$select->where->in('i.Item_ID', $itemID);
} else {
$select->where->equalTo('i.Item_ID', $itemID);
}
if ($attributeID) {
$select->where->equalTo('ea.Editions_Attribute_ID', $attributeID);
}
};
return $this->select($callback);
}
Expand Down
29 changes: 28 additions & 1 deletion module/GeebyDeeby/src/GeebyDeeby/Db/Table/Person.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function __construct(
}

/**
* Get a list of categories.
* Get a list of people.
*
* @param bool $biosOnly Should we filter to only people with biographies?
*
Expand All @@ -79,6 +79,33 @@ public function getList($biosOnly = false)
return $this->select($callback);
}

/**
* Get people for item IDs.
*
* @param array $itemIds Item IDs to match.
*
* @return mixed
*/
public function getListForItemIds($itemIds)
{
$callback = function ($select) use ($itemIds) {
$select->quantifier('DISTINCT');
$select->join(
['ec' => 'Editions_Credits'],
'ec.Person_ID = People.Person_ID',
[]
);
$select->join(
['e' => 'Editions'],
'ec.Edition_ID = e.Edition_ID',
['Item_ID']
);
$select->where->in('Item_ID', $itemIds);
$select->order(['Last_Name', 'First_Name']);
};
return $this->select($callback);
}

/**
* Get autocomplete suggestions.
*
Expand Down
9 changes: 9 additions & 0 deletions module/GeebyDeeby/view/geeby-deeby/search/controls.phtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php $config = $this->config('search_controls') ?? []; ?>
<div class="results row">
<ul class="search-controls hidden">
<li><label><input class="creator-toggle" type="checkbox" /> Show credits</label></li>
<?php foreach ($config['edition_attributes'] ?? [] as $id => $label): ?>
<li><label><input class="edition-attribute-toggle" data-edition-attribute-id="<?=$id?>" type="checkbox" /> <?=$this->escapeHtml($label)?></label></li>
<?php endforeach; ?>
</ul>
</div>
107 changes: 70 additions & 37 deletions module/GeebyDeeby/view/geeby-deeby/search/keyword.phtml
Original file line number Diff line number Diff line change
@@ -1,76 +1,109 @@
<?php
$this->layout()->title = 'Search Results - Keyword';
$empty = true;
$this->layout()->title = 'Search Results - Keyword';
$this->scriptManager()->add(['search']);
$empty = true;
$config = $this->config('search_controls') ?? [];
?>
<?=$this->render('geeby-deeby/search/controls.phtml')?>
<?php if (count($series) > 0): $empty = false; ?>
<h2>Series</h2>
<p>
<ol>
<?php foreach ($series as $current): ?>
<a href="<?=$this->url('series', ['id' => $current['Series_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Series_Name']))?>
</a><br />
<li>
<a href="<?=$this->url('series', ['id' => $current['Series_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Series_Name']))?>
</a>
</li>
<?php endforeach; ?>
</p>
</ol>
<?php endif; ?>
<?php if (count($seriesAltTitles) > 0): $empty = false; ?>
<h2>Series Alternate Titles</h2>
<p>
<ol>
<?php foreach ($seriesAltTitles as $current): ?>
<a href="<?=$this->url('series', ['id' => $current['Series_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Series_AltName']))?>
</a><br />
<li>
<a href="<?=$this->url('series', ['id' => $current['Series_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Series_AltName']))?>
</a>
</li>
<?php endforeach; ?>
</p>
</ol>
<?php endif; ?>
<?php if (count($items) > 0): $empty = false; ?>
<h2>Items</h2>
<p>
<ol>
<?php foreach ($items as $current): ?>
<a href="<?=$this->url('item', ['id' => $current['Item_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Item_Name']))?>
</a><br />
<li>
<a href="<?=$this->url('item', ['id' => $current['Item_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Item_Name']))?>
</a>
<span class="hidden creators" data-loaded="0" data-item-id="<?=$current['Item_ID']?>">
/ <span class="values"></span>
</span>
<?php foreach (array_keys($config['edition_attributes'] ?? []) as $id): ?>
<span class="hidden edition-attributes" data-loaded="0" data-edition-attribute-id="<?=$id?>" data-item-id="<?=$current['Item_ID']?>">
<br /><span class="values"></span>
</span>
<?php endforeach; ?>
</li>
<?php endforeach; ?>
</p>
</ol>
<?php endif; ?>
<?php if (count($itemsAltTitles) > 0): $empty = false; ?>
<h2>Item Alternate Titles</h2>
<p>
<ol>
<?php foreach ($itemsAltTitles as $current): ?>
<a href="<?=$this->url('item', ['id' => $current['Item_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Item_AltName']))?>
</a><br />
<li>
<a href="<?=$this->url('item', ['id' => $current['Item_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Item_AltName']))?>
</a>
<span class="hidden creators" data-loaded="0" data-item-id="<?=$current['Item_ID']?>">
/ <span class="values"></span>
</span>
<?php foreach (array_keys($config['edition_attributes'] ?? []) as $id): ?>
<span class="hidden edition-attributes" data-loaded="0" data-edition-attribute-id="<?=$id?>" data-item-id="<?=$current['Item_ID']?>">
<br /><span class="values"></span>
</span>
<?php endforeach; ?>
</li>
<?php endforeach; ?>
</p>
</ol>
<?php endif; ?>
<?php if (count($categories) > 0): $empty = false; ?>
<h2>Categories</h2>
<p>
<ol>
<?php foreach ($categories as $current): ?>
<a href="<?=$this->url('category', ['id' => $current['Category_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Category']))?>
</a><br />
<li>
<a href="<?=$this->url('category', ['id' => $current['Category_ID']])?>">
<?=$this->escapeHtml($this->fixtitle($current['Category']))?>
</a>
</li>
<?php endforeach; ?>
</p>
</ol>
<?php endif; ?>
<?php if (count($people) > 0): $empty = false; ?>
<h2>People</h2>
<p>
<ol>
<?php foreach ($people as $current): ?>
<a href="<?=$this->url('person', ['id' => $current['Person_ID']])?>">
<?=$this->escapeHtml($this->showperson($current))?>
</a><br />
<li>
<a href="<?=$this->url('person', ['id' => $current['Person_ID']])?>">
<?=$this->escapeHtml($this->showperson($current))?>
</a>
</li>
<?php endforeach; ?>
</p>
</ol>
<?php endif; ?>
<?php if (count($tags) > 0): $empty = false; ?>
<h2>Subjects/Tags</h2>
<p>
<ol>
<?php foreach ($tags as $current): ?>
<a href="<?=$this->url('tag', ['id' => $current['Tag_ID']])?>">
<?=$this->escapeHtml($current['Tag'])?>
</a><br />
<li>
<a href="<?=$this->url('tag', ['id' => $current['Tag_ID']])?>">
<?=$this->escapeHtml($current['Tag'])?>
</a>
</li>
<?php endforeach; ?>
</p>
</ol>
<?php endif; ?>
<?php if ($empty): ?>
<p>No results found for <?=$this->escapeHtml($this->layout()->query)?>.</p>
Expand Down
13 changes: 13 additions & 0 deletions module/GeebyDeeby/view/geeby-deeby/search/list.phtml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<?php $config = $this->config('search_controls') ?? []; ?>
<div class="col-md-3">
<h2><?=$this->title ?></h2>
<?php foreach ($this->items as $i => $current): ?>
Expand All @@ -7,5 +8,17 @@
<?=$this->escapeHtml($this->fixtitle($current[$this->prefix . '_Name'] ?? $current[$this->prefix . '_AltName']))?>
</a>
</div>
<?php if ($this->prefix === 'Item'): ?>
<div class="result row hidden creators" data-loaded="0" data-item-id="<?=$current[$this->prefix . '_ID']?>">
<span class="col-md-1">&nbsp;</span>
<span class="col-md-10 values"></span>
</div>
<?php endif; ?>
<?php foreach (array_keys($config['edition_attributes'] ?? []) as $id): ?>
<div class="result row hidden edition-attributes" data-loaded="0" data-edition-attribute-id="<?=$id?>" data-item-id="<?=$current[$this->prefix . '_ID']?>">
<span class="col-md-1">&nbsp;</span>
<span class="col-md-10 values"></span>
</div>
<?php endforeach; ?>
<?php endforeach; ?>
</div>
Loading

0 comments on commit 0b6c558

Please sign in to comment.