Skip to content

Commit

Permalink
Shacl page: download feature (#210)
Browse files Browse the repository at this point in the history
* Disable git error messages in log file (#179)

* Remove extractGitVersion, use version.ini instead (#179)

* Omit timestamp in error logger

It's likely added by the operating system.

* Don't show timeline of no historicalDataDir

* Fix undefined variable

* Start Docker image (#192)

* Configuration without id is broken #194

* Configuration without id is broken #194

* Adding BnF - Bibliothèque nationale de France (French National Library)

* Read schema type from the analysis output #197

* Create Hungarian translation #198: initial version and make Hungarian selectable

* Create Hungarian translation #198: documentation

* BaseTab: logger must be initialized first

* Allow config to be a symlink

* Link to field documentation in completeness tab #119

* Replace error_log with logger to support log levels #193

* Replace error_log with logger to support log levels #193: general logs

* Change link to field documentation

From icon link to linking the field (see #119).

* Add schema type fallback

* Extend docker

* Update jQuery to 3.7.1 #205

* Update jQuery to 3.7.1 #205

* Update MARC schema with OGyK extension

* display-xxx does not pick catalogue #209: fix issue

* Shacl page: make the IDs of failed rules downloadable for #208

---------

Co-authored-by: Jakob Voss <[email protected]>
  • Loading branch information
pkiraly and nichtich authored Aug 19, 2024
1 parent 9212332 commit 05f0b19
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 31 deletions.
2 changes: 1 addition & 1 deletion classes/IssuesDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public function getRecordIdsByShaclCount($criterium, $typeId, $groupId = '') {
$stmt = $this->prepare(
'SELECT COUNT(distinct(id)) AS count
FROM shacl
WHERE "' . $criterium . '" = :typeId');
WHERE "' . $criterium . '" = :typeId' . $groupCriterium);
$stmt->bindValue(':typeId', $typeId, SQLITE3_TEXT);
if ($groupId !== '')
$stmt->bindValue(':groupId', $groupId, SQLITE3_TEXT);
Expand Down
65 changes: 60 additions & 5 deletions classes/Shacl.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,25 @@

class Shacl extends BaseTab {

public static String $paramsFile = 'shacl4bib.params.json';
protected string $action = 'list';
protected $parameterFile = 'shacl4bib.params.json';

public function prepareData(Smarty &$smarty) {
parent::prepareData($smarty);
$this->action = getOrDefault('action', 'list', ['list', 'download']);

if ($this->action == 'download') {
$this->processDownloadRequest();
} else {
$this->processListRequest($smarty);
}
}

public function getTemplate() {
return 'shacl/shacl.tpl';
}

private function processListRequest(&$smarty) {
$schemaFile = $this->analysisParameters->shaclConfigurationFile;
$schemaFile = substr($schemaFile, strrpos($schemaFile, '/') + 1);
$schemaFilePath = $this->getFilePath($schemaFile);
Expand All @@ -19,10 +34,6 @@ public function prepareData(Smarty &$smarty) {
$smarty->assign('index', $this->indexSchema($schema));
}

public function getTemplate() {
return 'shacl/shacl.tpl';
}

private function indexSchema($schema) {
$index = [];
foreach ($schema['fields'] as $field) {
Expand Down Expand Up @@ -65,4 +76,48 @@ public function showArray($name, $criterium) {

return $text;
}

public function queryUrl($id, $value) {
return sprintf('?tab=data&type=custom-rule&query=%s:%s', $id, $value);
}

public function downloadUrl($id, $value) {
$baseParams = [
'tab=shacl',
'action=download',
];
$params = array_merge($baseParams, $this->getGeneralParams());
$params[] = sprintf('ruleId=%s', $id);
$params[] = sprintf('value=%s', $value);
return '?' . join('&', $params);
}

private function processDownloadRequest() {
$ruleId = getOrDefault('ruleId', '');
$value = getOrDefault('value', '');
if ($ruleId != '') {
$this->output = 'none';
$this->download($ruleId, $value);
}
}

private function download($ruleId, $value) {
$groupId = '';
$attachment = sprintf('attachment; filename="shacl-issue-%s-is-%s-at-%s.csv"', $ruleId, $value, date("Y-m-d"));
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: ' . $attachment);

if ($ruleId != '') {
if ($this->sqliteExists()) {
$this->numFound = $this->issueDB()->getRecordIdsByShaclCount($ruleId, $value, $groupId)->fetchArray(SQLITE3_ASSOC)['count'];
$result = $this->issueDB()->getRecordIdsByShacl($ruleId, $value, $groupId);
while ($row = $result->fetchArray(SQLITE3_ASSOC))
echo $row['id'], "\n";
# } else {
# $recordIds = $this->getIdsFromCsv($errorId, $this->action);
# echo join("\n", $recordIds);
}
}
}

}
21 changes: 12 additions & 9 deletions classes/Utils/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,6 @@ public static function fromIniFile(string $file, array $defaults=[]) {
private function __construct(array $configuration) {
// global
$this->configuration = $configuration;

foreach ($configuration as $key => $value) {
if (str_starts_with($key, 'display-')) {
Configuration::expectBool($key, $value);
$this->display[substr($key,8)] = $value;
}
}

$this->id = $configuration["id"]; // REQUIRED

$this->dir = $this->getValue('dir', 'output');
Expand All @@ -98,12 +90,23 @@ private function __construct(array $configuration) {
$this->schema = $this->getValue('schema', null); // 'MARC21'
$this->linkTemplate = $this->getValue('linkTemplate', null);
$this->language = $this->getValue('language', null); // 'en'

foreach ($configuration as $key => $value) {
if (str_starts_with($key, 'display-')) {
$displayKey = substr($key,8);
if (is_array($value) && isset($value[$this->id])) {
$value = $value[$this->id];
}
Configuration::expectBool($key, $value);
$this->display[$displayKey] = $value;
}
}
}

private static function expectBool($key, $value) {
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if (!is_bool($value)) {
throw new Exception("$key must be boolean (1/0/true/false/on/off/yes/no)");
throw new Exception("$key must be boolean (1/0/true/false/on/off/yes/no). It is '$value' instead");
}
}

Expand Down
18 changes: 9 additions & 9 deletions common-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ function readCsv($csvFile, $id = '') {
return $records;
}

if (!function_exists('array_is_list')) {
function array_is_list(array $arr) {
if ($arr === [])
return true;
return array_keys($arr) === range(0, count($arr) - 1);
}
}

function setLanguage($language) {
global $languages;
$lang = isset($languages[$language]) ? $languages[$language] : $languages['en'];
Expand All @@ -82,14 +90,6 @@ function setLanguage($language) {
textdomain('messages');
}

if (!function_exists('array_is_list')) {
function array_is_list(array $arr) {
if ($arr === [])
return true;
return array_keys($arr) === range(0, count($arr) - 1);
}
}

/**
* Translate string with variables
* @return mixed|string The first argument should be the msgid, the rest should be the variables to inject
Expand All @@ -98,7 +98,7 @@ function _t() {
$args = func_get_args();
$args[0] = _($args[0]);

if(func_num_args() <= 1)
if (func_num_args() <= 1)
return $args[0];

return call_user_func_array('sprintf', $args);
Expand Down
50 changes: 43 additions & 7 deletions templates/shacl/shacl.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
<thead>
<tr>
<th colspan="3"></th>
<th colspan="3" class="text-center" style="padding: 0 10px 0 50px;">number of records</th>
<th colspan="6" class="text-center" style="padding: 0 10px 0 50px;">number of records</th>
</tr>
<tr>
<th class="text-center" style="padding-right: 10px;">path</th>
<th class="text-center" style="padding-right: 5px;">criteria</th>
<th></th>
<th class="text-center" style="padding: 0 10px 0 50px;">failed</th>
<th class="text-center" style="padding: 0 10px 0 10px;">passed</th>
<th class="text-center" style="padding: 0 10px 0 10px;">NA</th>
<th class="text-center" style="padding: 0 10px 0 50px;" colspan="2">failed</th>
<th class="text-center" style="padding: 0 10px 0 10px;" colspan="2">passed</th>
<th class="text-center" style="padding: 0 10px 0 10px;" colspan="2">NA</th>
</tr>
</thead>
<tbody>
Expand All @@ -48,9 +48,45 @@
<div style="float: left; background-color: #37ba00; width:{floor($row->{'1'} * 300 / $count)}px;">&nbsp;</div>
<div style="float: left; background-color: #cccccc; width:{floor($row->{'NA'} * 300 / $count)}px;">&nbsp;</div>
</td>
<td class="text-right">{if $row->{'0'} == 0}0{else}<a href="?tab=data&type=custom-rule&query={$id}:0">{number_format($row->{'0'})}</a>{/if}</td>
<td class="text-right">{if $row->{'1'} == 0}0{else}<a href="?tab=data&type=custom-rule&query={$id}:1">{number_format($row->{'1'})}</a>{/if}</td>
<td class="text-right">{if $row->{'NA'} == 0}0{else}<a href="?tab=data&type=custom-rule&query={$id}:NA">{number_format($row->{'NA'})}</a>{/if}</td>
<td class="text-right" style="min-width: 100px;">
{if $row->{'0'} == 0}
0
{else}
{number_format($row->{'0'})}
{/if}
</td>
<td style="min-width: 60px;">
{if $row->{'0'} > 0}
<a href="{$controller->queryUrl($id, 0)}" class="search"><i class="fa fa-search" aria-hidden="true"></i></a>
<a href="{$controller->downloadUrl($id, 0)}" class="list"><i class="fa fa-download" aria-hidden="true"></i></a>
{/if}
</td>
<td class="text-right">
{if $row->{'1'} == 0}
0
{else}
{number_format($row->{'1'})}
{/if}
</td>
<td style="min-width: 60px;">
{if $row->{'1'} > 0}
<a href="{$controller->queryUrl($id, 1)}" class="search"><i class="fa fa-search" aria-hidden="true"></i></a>
<a href="{$controller->downloadUrl($id, 1)}" class="list"><i class="fa fa-download" aria-hidden="true"></i></a>
{/if}
</td>
<td class="text-right">
{if $row->{'NA'} == 0}
0
{else}
{number_format($row->{'NA'})}</a>
{/if}
</td>
<td style="min-width: 60px;">
{if $row->{'NA'} > 0}
<a href="{$controller->queryUrl($id, 'NA')}" class="search"><i class="fa fa-search" aria-hidden="true"></i></a>
<a href="{$controller->downloadUrl($id, 'NA')}" class="list"><i class="fa fa-download" aria-hidden="true"></i></a>
{/if}
</td>
</tr>
{/foreach}
</tbody>
Expand Down

0 comments on commit 05f0b19

Please sign in to comment.