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

Finalize Cronjob #99

Merged
merged 9 commits into from
Sep 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
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()
alxndr-w marked this conversation as resolved.
Show resolved Hide resolved
{
$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
Loading