Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Richter committed Aug 31, 2023
0 parents commit 4f68996
Show file tree
Hide file tree
Showing 11 changed files with 600 additions and 0 deletions.
163 changes: 163 additions & 0 deletions Classes/Command/IndexCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Liszt Catalog Raisonne project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
*/

namespace Slub\LisztBibliography\Command;

use Elasticsearch\Client;
use Hedii\ZoteroApi\ZoteroApi;
use Illuminate\Support\Collection;
use Slub\LisztCommon\Common\ElasticClientBuilder;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class IndexCommand extends Command
{

protected ZoteroApi $bibApi;
protected Collection $bibliographyItems;
protected Client $client;
protected array $extConf;
protected SymfonyStyle $io;
protected ZoteroApi $localeApi;
protected array $locales;

protected function configure(): void
{
$this->setDescription('Create elasticsearch index from zotero bibliography');
}

protected function initialize(InputInterface $input, OutputInterface $output) {
$this->extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('liszt_bibliography');
$this->client = ElasticClientBuilder::getClient();
$this->bibApi = new ZoteroApi($this->extConf['zoteroApiKey']);
$this->localeApi = new ZoteroApi($this->extConf['zoteroApiKey']);
$this->io = new SymfonyStyle($input, $output);
$this->io->title($this->getDescription());
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->io->section('Fetching Bibliography Data');
$this->fetchBibliography();
$this->io->section('Committing Bibliography Data');
$this->commitBibliography();
$this->io->section('Committing Locale Data');
$this->commitLocales();
return 0;
}

protected function fetchBibliography(): void
{
// fetch locales
$response = $this->localeApi->
raw('https://api.zotero.org/schema?format=json')->
send();
$this->locales = $response->getBody()['locales'];

// get bulk size and total size
$bulkSize = (int) $this->extConf['zoteroBulkSize'];
$response = $this->bibApi->
group($this->extConf['zoteroGroupId'])->
items()->
top()->
limit(1)->
send();
$total = (int) $response->getHeaders()['Total-Results'][0];

// fetch bibliography items bulkwise
$this->io->progressStart($total);
$collection = new Collection($response->getBody());
$this->bibliographyItems = $collection->pluck('data');

$cursor = $bulkSize;
while ($cursor < $total) {
$this->io->progressAdvance($bulkSize);
$response = $this->bibApi->
group($this->extConf['zoteroGroupId'])->
items()->
top()->
start($cursor)->
limit($bulkSize)->
send();
$collection = new Collection($response->getBody());
$this->bibliographyItems = $this->bibliographyItems->
concat($collection->pluck('data'));
$cursor += $bulkSize;
}
$this->io->progressFinish();
}

protected function commitBibliography(): void
{
$index = $this->extConf['elasticIndexName'];
$this->io->text('Committing the ' . $index . ' index');

$this->io->progressStart(count($this->bibliographyItems));
if ($this->client->indices()->exists(['index' => $index])) {
$this->client->indices()->delete(['index' => $index]);
$this->client->indices()->create(['index' => $index]);
}

$params = [ 'body' => [] ];
$bulkCount = 0;
foreach ($this->bibliographyItems as $document) {
$this->io->progressAdvance();
$params['body'][] = [ 'index' =>
[
'_index' => $index,
'_id' => $document['key']
]
];
$params['body'][] = json_encode($document);

if (!(++$bulkCount % $this->extConf['elasticBulkSize'])) {
$this->client->bulk($params);
$params = [ 'body' => [] ];
}
}
$this->io->progressFinish();
$this->client->bulk($params);

$this->io->text('done');
}

protected function commitLocales(): void
{
$localeIndex = $this->extConf['elasticLocaleIndexName'];
$this->io->text('Committing the ' . $localeIndex . ' index');

if ($this->client->indices()->exists(['index' => $localeIndex])) {
$this->client->indices()->delete(['index' => $localeIndex]);
$this->client->indices()->create(['index' => $localeIndex]);
}

$params = [ 'body' => [] ];
foreach ($this->locales as $key => $locale) {
$params['body'][] = [ 'index' =>
[
'_index' => $localeIndex,
'_id' => $key
]
];
$params['body'][] = json_encode($locale);

}
$this->client->bulk($params);

$this->io->text('done');
}
}
93 changes: 93 additions & 0 deletions Classes/Controller/BibliographyController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Liszt Catalog Raisonne project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
*/

namespace Slub\LisztBibliography\Controller;

use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Slub\LisztCommon\Controller\ClientEnabledController;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class BibliographyController extends ClientEnabledController
{
/** id of list target **/
const MAIN_TARGET = 'bib-list';
const SIDE_TARGET = 'bib-list-side';
const SIZE = 20;

/** @var jsCall */
protected string $jsCall;

/** @var div */
protected string $div;

protected string $bibIndex;
protected string $localeIndex;

public function __construct(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory)
{
$this->responseFactory = $responseFactory;
$this->streamFactory = $streamFactory;
}

public function initializeAction(): void
{
$extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('liszt_bibliography');
$this->bibIndex = $extConf['elasticIndexName'];
$this->localeIndex = $extConf['elasticLocaleIndexName'];
}

public function indexAction(): ResponseInterface
{
$this->createJsCall();
$this->wrapTargetDiv();
$contentStream = $this->
streamFactory->
createStream(
$this->div .
$this->jsCall
);

return $this->
responseFactory->
createResponse()->
withBody($contentStream);
}

private function wrapTargetDiv(): void
{
$sideCol = '<div id="' .
self::SIDE_TARGET .
'" class="col-md-4 col-xl-3 order-md-2"><ul class="list-group"></ul></div>';
$mainCol = '<div id="' .
self::MAIN_TARGET .
'" class="col-md order-md-1"></div>';
$this->div = '<div class="container"><div class="row">' .
$sideCol . $mainCol . '</div>';
}

private function createJsCall(): void
{
$this->jsCall =
'<script>;document.addEventListener("DOMContentLoaded", _ => new BibliographyController({' .
'target:"' . self::MAIN_TARGET . '",' .
'sideTarget:"' . self::SIDE_TARGET . '",' .
'size:' . self::SIZE . ',' .
'bibIndex:"' . $this->bibIndex . '",' .
'localeIndex:"' . $this->localeIndex . '"' .
'}));</script>';
}
}
18 changes: 18 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
services:
_defaults:
autowire: true
autoconfigure: true
public: false
Slub\LisztBibliography\:
resource: '../Classes/*'
exclude: '../Classes/Domain/Model/*'
Slub\LisztBibliography\Classes\Controller\BibliographyController:
tags:
- backend.controller
Slub\LisztBibliography\Command\IndexCommand:
tags:
-
name: console.command
command: 'liszt-bibliography:index'
description: 'Create elasticsearch index from zotero bibliography'
schedulable: true
45 changes: 45 additions & 0 deletions Configuration/TCA/Overrides/tt_content.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;

defined('TYPO3') or die();

ExtensionUtility::registerPlugin(
'liszt_bibliography',
'BibliographyListing',
'Liszt Bibliography Listing'
);

ExtensionManagementUtility::addTcaSelectItem(
'tt_content',
'CType',
[
'LLL:EXT:liszt_bibliography/Resources/Private/Language/locallang.xlf:listing_title',
'lisztbibliography_listing',
'content-text'
]
);

$GLOBALS['TCA']['tt_content']['types']['lisztbibliography_listing'] = [
'showitem' => '
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general,
--palette--;;general,
header; Title,
bodytext;LLL:EXT:core/Resources/Private/Language/Form/locallang_ttc.xlf:bodytext_formlabel,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access,
--palette--;;hidden,
--palette--;;acces,
',
'columnsOverrides' => [
'bodytext' => [
'config' => [
'enableRichtext' => true,
'richtextConfiguration' => 'default'
]
]
]
];

28 changes: 28 additions & 0 deletions Configuration/TsConfig/Page/Mod/Wizards/Listing.tsconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
mod.wizards.newContentElement.wizardItems {
plugins {
elements {
lisztbibliography_bibliographylisting {
iconIdentifier = content-text
title = LLL:EXT:liszt_bibliography/Resources/Private/Language/locallang.xlf:listing_title
description = LLL:EXT:liszt_bibliography/Resources/Private/Language/locallang.xlf:listing_description
tt_content_defValues {
CType = list
list_type = lisztbibliography_bibliographylisting
}
}
}
}
common {
elements {
lisztbibliography_bibliographylisting {
iconIdentifier = content-text
title = LLL:EXT:liszt_bibliography/Resources/Private/Language/locallang.xlf:listing_title
description = LLL:EXT:liszt_bibliography/Resources/Private/Language/locallang.xlf:listing_description
tt_content_defValues {
CType = lisztbibliography_listing
}
}
}
show := addToList(lisztbibliography_listing)
}
}
25 changes: 25 additions & 0 deletions Configuration/TypoScript/setup.typoscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
######################
#### DEPENDENCIES ####
######################
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:liszt_common/Configuration/TypoScript/setup.typoscript">

lib.contentElement {
#layoutRootPaths {
#200 = EXT:liszt_bibliography:Resources/Private/Layouts
#}
#partialRootPaths {
#200 = EXT:liszt_bibliography:Resources/Private/Partial
#}
templateRootPaths {
200 = EXT:liszt_bibliography/Resources/Private/Templates
}
}

tt_content {
lisztbibliography_listing =< lib.contentElement
lisztbibliography_listing {
templateName = BibliographyListing
}
}

page.includeJSFooter.BibliographyController = EXT:liszt_bibliography/Resources/Public/JavaScript/Src/BibliographyController.js
14 changes: 14 additions & 0 deletions Resources/Private/Language/locallang.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<xliff version="1.0">
<file source-language="en" datatype="plaintext" original="EXT:publisher_db/Resources/Private/Language/locallang" date="2022-12-19T13:20:31Z" product-name="publisher_db">
<header/>
<body>
<trans-unit id="listing_title" resname="tx_publisherdb_domain_model_publishermikroitem">
<source>Bibliographie-Listing</source>
</trans-unit>
<trans-unit id="listing_description" resname="tx_publisherdb_domain_model_publishermikroitem">
<source>Eine Auflistung aller Einträge der Liszt-Bibliographie</source>
</trans-unit>
</body>
</file>
</xliff>
Loading

0 comments on commit 4f68996

Please sign in to comment.