Skip to content

Commit

Permalink
Merge pull request #99 from FriendsOfREDAXO/restful-api-sync-cronjob-…
Browse files Browse the repository at this point in the history
…update

Finalize Cronjob
  • Loading branch information
alxndr-w authored Sep 5, 2024
2 parents cb5dc7a + d75c80b commit bdc741c
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 88 deletions.
5 changes: 5 additions & 0 deletions lang/de_de.lang
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,8 @@ neues_entry_sync_cronjob = [📰 Neues] Beiträge, Kategorien und Autoren einer
neues_entry_sync_cronjob_url = URL der REDAXO-Installation
neues_entry_sync_cronjob_token = RESTful API-Token
neues_entry_sync_cronjob_status = Status-Wert
neues_entry_sync_cronjob_neues_category_id = Standard-Kategorie
neues_entry_sync_cronjob_neues_author_id = Standard-Autor
neues_entry_sync_cronjob_media_category_id = Import in Medienpool-Kategorie
neues_entry_sync_cronjob_x_per_page = Anzahl der letzten Beiträge
neues_entry_sync_cronjob_success = %s Beiträge wurden erfolgreich synchronisiert (Erstellt: %s, aktualisiert %s).
4 changes: 2 additions & 2 deletions lib/Api/Restful.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static function init(): void
'path' => '/neues/entry/5.0.0/',
'auth' => '\rex_yform_rest_auth_token::checkToken',
'type' => Entry::class,
'query' => Entry::query()->where('status', 1, ">="),
'query' => Entry::query()->where('status', 1, '>='),
'get' => [
'fields' => [
Entry::class => [
Expand Down Expand Up @@ -105,7 +105,7 @@ public static function init(): void
'path' => '/neues/category/5.0.0/',
'auth' => '\rex_yform_rest_auth_token::checkToken',
'type' => Category::class,
'query' => Category::query()->where('status', 1, ">="),
'query' => Category::query()->where('status', 1, '>='),
'get' => [
'fields' => [
Category::class => [
Expand Down
288 changes: 202 additions & 86 deletions lib/Cronjob/Sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,121 +5,202 @@
use FriendsOfRedaxo\Neues\Author;
use FriendsOfRedaxo\Neues\Category;
use FriendsOfRedaxo\Neues\Entry;
use rex;
use rex_cronjob;
use rex_i18n;
use rex_media;
use rex_media_service;
use rex_path;
use rex_socket;
use rex_sql;
use rex_string;

class Sync extends rex_cronjob
{
/** @var array<string,string> */
private $rest_urls = ['category' => '/rest/neues/category/5.0.0/',
'author' => '/rest/neues/author/5.0.0/',
'entry' => '/rest/neues/entry/5.0.0/'];
private const ENDPOINT = '/rest/neues/entry/5.0.0/';

private $counter = [
'category' => ['created' => 0, 'updated' => 0],
'author' => ['created' => 0, 'updated' => 0],
'entry' => ['created' => 0, 'updated' => 0],
];

/**
* @return bool
*/
public function execute()
{
$url = rtrim($this->getParam('url'), '/') . self::ENDPOINT;
$data = [];

$baseUrl = $this->getParam('url');
/* Query zusammenstellen */
$query = [];
if ((int) $this->getParam('x_per_page') > 0) {
$query[] = 'per_page=' . $this->getParam('x_per_page');
}
$query[] = 'order[updatedate]=desc';
$socket_url = $url . '?' . implode('&', $query);
$token = $this->getParam('token');
$status = $this->getParam('status');

foreach ($this->rest_urls as $type => $url) {
$url = $baseUrl . $url;
$socket = rex_socket::factoryUrl($url);
$socket->addHeader('token', $token);
$response = $socket->doGet();

if (!$response->isOk()) {
/**
* TODO: in 'neues_entry_sync_error' Platzhalter für den Code. einfügen.
* TODO: reicht auch $this->setMessage(rex_i18n::msg('neues_entry_sync_error') ??
*/
$this->setMessage(sprintf(rex_i18n::msg('neues_entry_sync_error'), $response->getStatusCode()));
return false;
}

$data[$type] = json_decode($response->getBody(), true);
/* Socket erstellen und Daten abrufen */
$socket = rex_socket::factoryUrl($socket_url);
$socket->addHeader('token', $token);
/** @var rex_socket_response $response */
$response = $socket->doGet();

if (!$response->isOk()) {
$this->setMessage(sprintf(rex_i18n::msg('neues_entry_sync_error'), $response->getStatusCode()));
return false;
}

if (isset($data['category']['data'])) {
foreach ($data['category']['data'] as $category) {
$category = $category['attributes'];
$data = json_decode($response->getBody(), true);

// Überprüfe, ob UUID bereits in der Datenbank vorhanden ist
$neues_category = Category::query()->where('uuid', $category['uuid'])->findOne();
if (null === $neues_category) {
$neues_category = Category::create();
}
$entries = $data['data'];

$neues_category->setValue('uuid', $category['uuid']);
$neues_category->setValue('name', $category['name']);
$neues_category->setValue('image', $category['image']);
$neues_category->setValue('status', $status);
$neues_category->setValue('createdate', $category['createdate']);
$neues_category->setValue('createuser', 'cronjob');
$neues_category->setValue('updatedate', $category['updatedate']);
$neues_category->setValue('updateuser', 'cronjob');
$neues_category->save();
}
foreach ($entries as $entry) {
$this->createEntry($entry);
}

$this->setMessage(sprintf(rex_i18n::msg('neues_entry_sync_cronjob_success'), $this->counter['entry']['created'] + $this->counter['entry']['updated'], $this->counter['entry']['created'], $this->counter['entry']['updated']));
return true;
}

public function createEntry(array $current)
{
$entry_data = $current['attributes'];

$entry = Entry::query()->where('uuid', $entry_data['uuid'])->findOne();
if (null === $entry) {
$entry = Entry::create();
$entry->setValue('uuid', $entry_data['uuid']);
++$this->counter['entry']['created'];
} else {
++$this->counter['entry']['updated'];
}

if (isset($data['author']['data'])) {
foreach ($data['author']['data'] as $author) {
$author = $author['attributes'];
/* Kategorien abrufen und speichern */
$target_category_ids = [];
if ($this->getParam('neues_category_id') > 0 && Category::get($this->getParam('neues_category_id'))) {
$target_category_ids[] = $this->getParam('neues_category_id');
} else {
$categories = $current['relationships']['category_ids']['data'];

// Überprüfe, ob UUID bereits in der Datenbank vorhanden ist
$neues_author = Author::query()->where('uuid', $author['uuid'])->findOne();
if (null === $neues_author) {
$neues_author = Author::create();
foreach ($categories as $category) {
$target_category = $this->createCategory($category['attributes']);
if ($target_category) {
$target_category_ids[] = $target_category->getId();
}
}
}
$entry->setValue('category_ids', implode(',', $target_category_ids));
/* / Kategorien abrufen und speichern */

$neues_author->setValue('uuid', $author['uuid']);
$neues_author->setValue('name', $author['name']);
$neues_author->setValue('nickname', $author['nickname']);
$neues_author->setValue('text', $author['text']);
$neues_author->save();
/* Autor abrufen und speichern */
$author = $current['relationships']['author']['data'];
if ($author) {
$target_author = $this->createAuthor($author['attributes']);
if ($target_author) {
$entry->setValue('author_id', $target_author->getId());
}
}
/* / Autor abrufen und speichern */

/* Titelbild abrufen und speichern */
$updated_image = '';
$targetname = $entry_data['uuid'] . '_' . $entry_data['image'];
if ($this->createMedia($entry_data['image'])) {
$updated_image = $targetname;
}
$entry->setValue('image', $updated_image);
/* / Titelbild abrufen und speichern */

foreach ($data['entry']['data'] as $entry) {
$entry = $entry['attributes'];
// Überprüfe, ob UUID bereits in der Datenbank vorhanden ist
$neues_entry = Entry::query()->where('uuid', $entry['uuid'])->findOne();
if (null === $neues_entry) {
$neues_entry = Entry::create();
/* Galerie-Bilder abrufen und speichern */
$images = array_filter(explode(',', $entry_data['images']));
$updated_images = [];
foreach ($images as $image) {
$targetname = $entry_data['uuid'] . '_' . $image;
if ($this->createMedia($image, $targetname)) {
$updated_images[] = $targetname;
}
}
$entry->setValue('images', implode(',', $updated_images));
/* / Galerie-Bilder abrufen und speichern */

$entry->setValue('name', $entry_data['name']);
$entry->setValue('teaser', $entry_data['teaser']);
$entry->setValue('description', $entry_data['description']);
$entry->setValue('url', $entry_data['url']);
// $entry->setValue('lang_id', $entry['lang_id']);
$entry->setValue('publishdate', $entry_data['publishdate']);
$entry->setValue('domain_ids', 0);
$entry->setValue('createuser', 'neues_sync_cronjob');
$entry->setValue('updateuser', 'neues_sync_cronjob');
$entry->setValue('createdate', $entry_data['createdate']);
$entry->setValue('updatedate', $entry_data['updatedate']);
$entry->save();
}

public function createCategory($current)
{
$category = Category::query()->where('uuid', $current['uuid'])->findOne();
if (null === $category) {
$category = Category::create();
$category->setValue('uuid', $current['uuid']);
++$this->counter['category']['created'];
} else {
++$this->counter['category']['updated'];
}

$category->setValue('name', $current['name']);
$category->setValue('image', $current['image']);
$category->setValue('status', $current['status']);
$category->setValue('createdate', $current['createdate']);
$category->setValue('createuser', 'neues_sync_cronjob');
$category->setValue('updatedate', $current['updatedate']);
$category->setValue('updateuser', 'neues_sync_cronjob');
$category->save();
return $category;
}

public function createAuthor(array $current)
{
// Überprüfe, ob UUID bereits in der Datenbank vorhanden ist
$author = Author::query()->where('uuid', $current['uuid'])->findOne();
if (null === $author) {
$author = Author::create();
}

$neues_entry->setValue('uuid', $entry['uuid']);
$neues_entry->setValue('name', $entry['name']);
$neues_entry->setValue('teaser', $entry['teaser']);
$neues_entry->setValue('description', $entry['description']);
$neues_entry->setValue('url', $entry['url']);
$neues_entry->setValue('image', $entry['image']);
$neues_entry->setValue('images', $entry['images']);
// $neues_entry->setValue('lang_id', $entry['lang_id']);
// $neues_entry->setValue('category_id', $entry['category_id']);
// $neues_entry->setValue('author_id', $entry['author_id']);
$neues_entry->setValue('status', $status);
$neues_entry->setValue('publishdate', $entry['publishdate']);
$neues_entry->setValue('domain_ids', 0);
$neues_entry->setValue('createuser', 'cronjob');
$neues_entry->setValue('updateuser', 'cronjob');
$neues_entry->setValue('createdate', $entry['createdate']);
$neues_entry->setValue('updatedate', $entry['updatedate']);
$neues_entry->save();
$author->setValue('uuid', $current['uuid']);
$author->setValue('name', $current['name']);
$author->setValue('nickname', $current['nickname']);
$author->setValue('text', $current['text']);
$author->save();
return $author;
}

public function createMedia(string $filename, ?string $prefix = null): bool
{
$targetname = rex_string::normalize($prefix) . $filename;
if ('' === $filename) {
return false;
}

/**
* REVIEW: Ist hier der letzte Status-Code wirklich erforderlich? Es wäre eh nur der der letzten Abfrage
* FIXME: Der Eintrag 'neues_entry_sync_success' kommt in den .lang-Dateien nicht vor.
* REXSTAN: Variable $response might not be defined.
* -> unwahrscheinlich, da es fix drei $data-Einträge gibt. Dennoch ....
*/
$this->setMessage(sprintf(rex_i18n::msg('neues_entry_sync_success'), $response->getStatusCode()));
if (rex_media::get($targetname)) {
return true;
}

$socket = rex_socket::factoryUrl($this->getParam('url') . '/media/' . $filename);
/** @var rex_socket_response $response */
$response = $socket->doGet();

if ($response->isOk()) {
$cache_filepath = rex_path::addonCache('neues', 'cronjob/' . $targetname);
$response->writeBodyTo($cache_filepath);
/* Überprüfe, ob die Datei auf dem Dateisystem vorhanden ist */
return rex_media_service::addMedia([
'category_id' => $this->getParam('media_category_id'),
'title' => $filename,
'createuser' => 'neues_sync_cronjob',
'file' => ['name' => $targetname,
'path' => $cache_filepath]]) ? true : false;
}
return true;
}

Expand All @@ -128,13 +209,28 @@ public function getTypeName()
return rex_i18n::msg('neues_entry_sync_cronjob');
}

/**
* @return list<array<string, mixed>>
*/
public function getParamFields()
{
$media_categories = rex_sql::factory()->getArray('SELECT id, name FROM ' . rex::getTable('media_category'));
$media_category_options = ['' => 'Root'];
foreach ($media_categories as $media_category) {
$media_category_options[$media_category['id']] = $media_category['name'];
}

$neues_categories = Category::getAll();
$neues_category_options = ['' => 'Original'];
foreach ($neues_categories as $neues_category) {
$neues_category_options[$neues_category->getId()] = '📁 ' . $neues_category->getName();
}
$fields = [
[
'name' => 'url',
'label' => rex_i18n::msg('neues_entry_sync_cronjob_url'),
'type' => 'text',
'attributes' => ['required' => 'required', 'type' => 'url'],
],
[
'name' => 'token',
Expand All @@ -144,7 +240,27 @@ public function getParamFields()
[
'name' => 'status',
'label' => rex_i18n::msg('neues_entry_sync_cronjob_status'),
'type' => 'select',
'options' => ['1' => '🟢 Veröffentlichen', '0' => '🟡 Entwurf'],
],
[
'name' => 'media_category_id',
'label' => rex_i18n::msg('neues_entry_sync_cronjob_media_category_id'),
'type' => 'select',
'options' => $media_category_options,
],
[
'name' => 'neues_category_id',
'label' => rex_i18n::msg('neues_entry_sync_cronjob_neues_category_id'),
'type' => 'select',
'options' => $neues_category_options,
],
[
/* Wie viele Einträge sollen abgerufen werden */
'name' => 'x_per_page',
'label' => rex_i18n::msg('neues_entry_sync_cronjob_x_per_page'),
'type' => 'text',
'attributes' => ['type' => 'number', 'min' => 1],
],
];

Expand Down

0 comments on commit bdc741c

Please sign in to comment.