Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Augment search results with additional data #111

Merged
merged 5 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading