* @git GetBible * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace TrueChristianChurch\Joomla\GetBible\Watcher; use TrueChristianChurch\Joomla\GetBible\Database\Load; use TrueChristianChurch\Joomla\GetBible\Database\Insert; use TrueChristianChurch\Joomla\GetBible\Database\Update; use TrueChristianChurch\Joomla\GetBible\Api\Books; use TrueChristianChurch\Joomla\GetBible\Abstraction\Watcher; /** * The GetBible Book Watcher * * @since 2.0.1 */ final class Book extends Watcher { /** * The Books class * * @var Books * @since 2.0.1 */ protected Books $books; /** * Constructor * * @param Load $load The load object. * @param Insert $insert The insert object. * @param Update $update The update object. * @param Books $books The books API object. * * @since 2.0.1 */ public function __construct( Load $load, Insert $insert, Update $update, Books $books) { // load the parent constructor parent::__construct($load, $insert, $update); $this->books = $books; // set the table $this->table = 'book'; } /** * Update translations books * * @param array $translations The translations ids. * * @return bool True on success * @since 2.0.1 */ public function translations(array $translations): bool { foreach ($translations as $translation) { if (($abbreviation = $this->load->value(['id' => $translation], 'abbreviation', 'translation')) === null) { return false; } if (!$this->update($abbreviation)) { return false; } } return true; } /** * Sync the target being watched * * @param string $translation The translation. * @param int $book The book number. * * @return bool True on success * @since 2.0.1 */ public function sync(string $translation, int $book): bool { // load the target if not found if ($this->load($translation, $book)) { if ($this->isNew() || $this->hold()) { return true; } try { // get API hash value $hash = $this->books->sha($translation, $book); } catch (\Exception $e) { return false; } // confirm hash has not changed if (hash_equals($hash, $this->target->sha)) { return $this->bump(); } if ($this->update($translation)) { return true; } } return false; } /** * Load Book * * @param string $translation The translation. * @param int $book The book number. * * @return bool True if translation found * @since 2.0.1 */ private function load(string $translation, int $book): bool { // check local value if (($this->target = $this->load->item(['abbreviation' => $translation, 'nr' => $book], $this->table)) !== null) { return true; } try { // get all this translation books $books = $this->books->list($translation); } catch (\Exception $e) { return false; } // check return data if (!isset($books->{$book}) || !isset($books->{$book}->sha)) { return false; } // add them to the database $this->insert->items((array) $books, 'book'); if (($this->target = $this->load->item(['abbreviation' => $translation, 'nr' => $book], $this->table)) !== null) { $this->fresh = true; } return $this->fresh; } /** * Trigger the update of all books of this translation * * @param string $translation The translation. * * @return bool True if update was a success * @since 2.0.1 */ private function update(string $translation): bool { try { // get translations from the API if (($books = $this->books->list($translation)) === null) { return false; } } catch (\Exception $e) { return false; } // get the local books $local_books = $this->load->items(['abbreviation' => $translation], $this->table); $update = []; $insert = []; $match = ['key' => 'nr', 'value' => '']; // dynamic update all books foreach ($books as $book) { // check if the verse exist $match['value'] = (string) $book->nr; if ($local_books !== null && ($object = $this->getTarget($match, $local_books)) !== null) { $book->id = $object->id; $book->created = $this->today; $update[] = $book; } else { $insert[] = $book; } } // check if we have values to insert $inserted = false; if ($insert !== []) { $inserted = $this->insert->items($insert, $this->table); } // update the local values if ($update !== [] && $this->update->items($update, 'id', $this->table)) { return true; } return $inserted; } }