4
0

update 2023-06-20 05:05:22

This commit is contained in:
Robot 2023-06-20 05:05:22 +02:00
parent 5fa40eb556
commit 32bc71fbff
Signed by: Robot
GPG Key ID: 14DECD44E7E1BB95
6 changed files with 927 additions and 35 deletions

View File

@ -99,7 +99,15 @@ class App implements ServiceProviderInterface
*/
public function getWatcher(Container $container): Watcher
{
return new Watcher();
return new Watcher(
$container->get('GetBible.Load'),
$container->get('GetBible.Insert'),
$container->get('GetBible.Update'),
$container->get('GetBible.Api.Translations'),
$container->get('GetBible.Api.Books'),
$container->get('GetBible.Api.Chapters'),
$container->get('GetBible.Api.Verses')
);
}
}

View File

@ -70,5 +70,13 @@
*/
public function getWatcher(Container $container): Watcher
{
return new Watcher();
return new Watcher(
$container->get('GetBible.Load'),
$container->get('GetBible.Insert'),
$container->get('GetBible.Update'),
$container->get('GetBible.Api.Translations'),
$container->get('GetBible.Api.Books'),
$container->get('GetBible.Api.Chapters'),
$container->get('GetBible.Api.Verses')
);
}

View File

@ -11,19 +11,120 @@
```uml
@startuml
class Watcher << (F,LightGreen) >> #Green {
+ get(int $chapter, int $book, ...) : ?object
# Load $load
# Insert $insert
# Update $update
# Translations $translations
# Books $books
# Chapters $chapters
# Verses $verses
# bool $fresh
+ __construct(Load $load, Insert $insert, ...)
+ api(string $translation, int $book, ...) : bool
- translation(string $translation) : ?string
- book(string $translation, int $book) : ?string
- chapter(string $translation, int $book, ...) : ?string
- verses(string $translation, int $book, ...) : bool
- update(string $translation, int $book, ...) : bool
- getVerse(int $number, array $verses) : ?object
- updateHash(string $translation, int $book, ...) : bool
}
note right of Watcher::get
Get the verses of chapter in a book in a translation
note right of Watcher::__construct
Constructor
since: 3.2.0
return: ?object
since: 2.0.1
arguments:
int $chapter
Load $load
Insert $insert
Update $update
Translations $translations
Books $books
Chapters $chapters
Verses $verses
end note
note left of Watcher::api
Watching that the local Database and API is in sync
since: 2.0.1
return: bool
arguments:
string $translation
int $book
string $translation = 'kjv'
int $chapter
end note
note right of Watcher::translation
Get Translation Hash Value
since: 2.0.1
return: ?string
end note
note left of Watcher::book
Get Book Hash Value
since: 2.0.1
return: ?string
end note
note right of Watcher::chapter
Get Chapter Hash Value
since: 2.0.1
return: ?string
arguments:
string $translation
int $book
int $chapter
end note
note left of Watcher::verses
Load verses if not in local database
since: 2.0.1
return: bool
arguments:
string $translation
int $book
int $chapter
end note
note right of Watcher::update
Trigger the update of the verses of a translation-book-chapter
since: 2.0.1
return: bool
arguments:
string $translation
int $book
int $chapter
end note
note left of Watcher::getVerse
Get a verse text from the API array of verses
since: 2.0.1
return: ?object
end note
note right of Watcher::updateHash
Trigger the update of a chapter hash value
since: 2.0.1
return: bool
arguments:
string $translation
int $book
int $chapter
string $hash
end note
@enduml

View File

@ -12,33 +12,409 @@
namespace VDM\Joomla\GetBible;
use VDM\Joomla\GetBible\Abstraction\Api;
use VDM\Joomla\GetBible\Database\Load;
use VDM\Joomla\GetBible\Database\Insert;
use VDM\Joomla\GetBible\Database\Update;
use VDM\Joomla\GetBible\Api\Translations;
use VDM\Joomla\GetBible\Api\Books;
use VDM\Joomla\GetBible\Api\Chapters;
use VDM\Joomla\GetBible\Api\Verses;
/**
* The GetBible Watcher
*
* @since 3.2.0
* @since 2.0.1
*/
final class Watcher extends Api
final class Watcher
{
/**
* Get the verses of chapter in a book in a translation
* The Load class
*
* @param int $chapter The chapter number.
* @var Load
* @since 2.0.1
*/
protected Load $load;
/**
* The Insert class
*
* @var Insert
* @since 2.0.1
*/
protected Insert $insert;
/**
* The Update class
*
* @var Update
* @since 2.0.1
*/
protected Update $update;
/**
* The Translations class
*
* @var Translations
* @since 2.0.1
*/
protected Translations $translations;
/**
* The Books class
*
* @var Books
* @since 2.0.1
*/
protected Books $books;
/**
* The Chapters class
*
* @var Chapters
* @since 2.0.1
*/
protected Chapters $chapters;
/**
* The Verses class
*
* @var Verses
* @since 2.0.1
*/
protected Verses $verses;
/**
* The fresh load switch
*
* @var bool
* @since 2.0.1
*/
protected bool $fresh = false;
/**
* Constructor
*
* @param Load $load The load object.
* @param Insert $insert The insert object.
* @param Update $update The update object.
* @param Translations $translations The translations API object.
* @param Books $books The books API object.
* @param Chapters $chapters The chapters API object.
* @param Verses $verses The verses API object.
*
* @since 2.0.1
*/
public function __construct(
Load $load,
Insert $insert,
Update $update,
Translations $translations,
Books $books,
Chapters $chapters,
Verses $verses)
{
$this->load = $load;
$this->insert = $insert;
$this->update = $update;
$this->translations = $translations;
$this->books = $books;
$this->chapters = $chapters;
$this->verses = $verses;
}
/**
* Watching that the local Database and API is in sync
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return bool True on success
* @since 2.0.1
*/
public function api(string $translation, int $book, int $chapter): bool
{
// does the translation exist
if ($this->translation($translation) === null)
{
return false;
}
// does the book exist
if ($this->book($translation, $book) === null)
{
return false;
}
// does the chapter exist, and get hash value
if (($hash = $this->chapter($translation, $book, $chapter)) === null)
{
return false;
}
// load the verses if not found
if ($this->verses($translation, $book, $chapter))
{
if ($this->fresh)
{
return true;
}
// get API chapter hash value
$api_hash = $this->chapters->sha($translation, $book, $chapter);
// confirm chapter hash has not changed
if (hash_equals($hash, $api_hash))
{
return true;
}
if ($this->update($translation, $book, $chapter))
{
// now update the hash of this chapter
return $this->updateHash($translation, $book, $chapter, $api_hash);
}
}
return false;
}
/**
* Get Translation Hash Value
*
* @param string $translation The translation.
*
* @return object|null The response object or null if an error occurs.
* @since 3.2.0
* @return string|null The sha of the translation
* @since 2.0.1
*/
public function get(int $chapter, int $book, string $translation = 'kjv'): ?object
private function translation(string $translation): ?string
{
return $this->response->get(
$this->http->get(
$this->uri->get($translation . '/' . $book . '/' . $chapter . '.json')
)
);
// check local value
if (($translation_sha = $this->load->value(['abbreviation' => $translation], 'sha', 'translation')) !== null)
{
return $translation_sha;
}
// get all the translations
$translations = $this->translations->list();
// check return data
if (!isset($translations->{$translation}) || !isset($translations->{$translation}->sha))
{
return null;
}
// add them to the database
$this->insert->items((array) $translations, 'translation');
return $translations->{$translation}->sha;
}
/**
* Get Book Hash Value
*
* @param string $translation The translation.
* @param int $book The book number.
*
* @return string|null The sha of the book
* @since 2.0.1
*/
private function book(string $translation, int $book): ?string
{
// check local value
if (($book_sha = $this->load->value(['abbreviation' => $translation, 'nr' => $book], 'sha', 'book')) !== null)
{
return $book_sha;
}
// get all the books
$books = $this->books->list($translation);
// check return data
if (!isset($books->{$book}) || !isset($books->{$book}->sha))
{
return null;
}
// add them to the database
$this->insert->items((array) $books, 'book');
return $books->{$book}->sha;
}
/**
* Get Chapter Hash Value
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return string|null The sha of the chapter
* @since 2.0.1
*/
private function chapter(string $translation, int $book, int $chapter): ?string
{
// check local value
if (($chapter_sha = $this->load->value(
['abbreviation' => $translation, 'nr' => $book, 'chapter' => $chapter],
'sha', 'chapter'
)) !== null)
{
return $chapter_sha;
}
// get all the books
$chapters = $this->chapters->list($translation, $book);
// check return data
if (!isset($chapters->{$chapter}) || !isset($chapters->{$chapter}->sha))
{
return null;
}
// add them to the database
$this->insert->items((array) $chapters, 'chapter');
return $chapters->{$chapter}->sha;
}
/**
* Load verses if not in local database
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return bool True if in local database
* @since 2.0.1
*/
private function verses(string $translation, int $book, int $chapter): bool
{
// check local value
if (($name = $this->load->value(
['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter, 'verse' => 1],
'name', 'verse'
)) !== null)
{
return true;
}
// get all the verses
if (($verses = $this->verses->get($translation, $book, $chapter)) === null)
{
return false;
}
// dynamic update all verse objects
$insert = ['book_nr' => $book, 'abbreviation' => $translation];
array_walk($verses->verses, function ($item, $key) use ($insert) {
foreach ($insert as $k => $v) { $item->$k = $v; }
});
$this->fresh = true;
// add them to the database
return $this->insert->items((array) $verses->verses, 'verse');
}
/**
* Trigger the update of the verses of a translation-book-chapter
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return bool True if update was a success
* @since 2.0.1
*/
private function update(string $translation, int $book, int $chapter): bool
{
// load all the verses from the local database
if (($verses = $this->load->items(
['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter],
'verse'
)) !== null)
{
// get verses from the API
if (($api = $this->verses->get($translation, $book, $chapter)) === null)
{
return false;
}
$api_verses = (array) $api->verses;
$update = [];
// dynamic update all verse objects
foreach ($verses as $verse)
{
if (($object = $this->getVerse((int) $verse->verse, $api_verses)) !== null)
{
$object->id = $verse->id;
$update[] = $object;
}
}
// update the local verses
if ($update !== [] && $this->update->items($update, 'id', 'verse'))
{
return true;
}
}
return false;
}
/**
* Get a verse text from the API array of verses
*
* @param int $number The verse number.
* @param array $verses The api verses
*
* @return object|null The verse string
* @since 2.0.1
*/
private function getVerse(int $number, array &$verses): ?object
{
foreach ($verses as $verse)
{
if ($verse->verse === $number)
{
return $verse;
}
}
return null;
}
/**
* Trigger the update of a chapter hash value
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
* @param string $hash The API chapter hash value.
*
* @return bool True if update was a success
* @since 2.0.1
*/
private function updateHash(string $translation, int $book, int $chapter, string $hash): bool
{
// load the chapter
if (($chapter = $this->load->value(
['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter],
'id', 'chapter'
)) !== null)
{
$update = [];
$update['id'] = $chapter;
$update['sha'] = $hash;
// update the local verses
return $this->update->row($update, 'id', 'chapter');
}
return false;
}
}

View File

@ -1,18 +1,388 @@
/**
* Get the verses of chapter in a book in a translation
* The Load class
*
* @param int $chapter The chapter number.
* @var Load
* @since 2.0.1
*/
protected Load $load;
/**
* The Insert class
*
* @var Insert
* @since 2.0.1
*/
protected Insert $insert;
/**
* The Update class
*
* @var Update
* @since 2.0.1
*/
protected Update $update;
/**
* The Translations class
*
* @var Translations
* @since 2.0.1
*/
protected Translations $translations;
/**
* The Books class
*
* @var Books
* @since 2.0.1
*/
protected Books $books;
/**
* The Chapters class
*
* @var Chapters
* @since 2.0.1
*/
protected Chapters $chapters;
/**
* The Verses class
*
* @var Verses
* @since 2.0.1
*/
protected Verses $verses;
/**
* The fresh load switch
*
* @var bool
* @since 2.0.1
*/
protected bool $fresh = false;
/**
* Constructor
*
* @param Load $load The load object.
* @param Insert $insert The insert object.
* @param Update $update The update object.
* @param Translations $translations The translations API object.
* @param Books $books The books API object.
* @param Chapters $chapters The chapters API object.
* @param Verses $verses The verses API object.
*
* @since 2.0.1
*/
public function __construct(
Load $load,
Insert $insert,
Update $update,
Translations $translations,
Books $books,
Chapters $chapters,
Verses $verses)
{
$this->load = $load;
$this->insert = $insert;
$this->update = $update;
$this->translations = $translations;
$this->books = $books;
$this->chapters = $chapters;
$this->verses = $verses;
}
/**
* Watching that the local Database and API is in sync
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return bool True on success
* @since 2.0.1
*/
public function api(string $translation, int $book, int $chapter): bool
{
// does the translation exist
if ($this->translation($translation) === null)
{
return false;
}
// does the book exist
if ($this->book($translation, $book) === null)
{
return false;
}
// does the chapter exist, and get hash value
if (($hash = $this->chapter($translation, $book, $chapter)) === null)
{
return false;
}
// load the verses if not found
if ($this->verses($translation, $book, $chapter))
{
if ($this->fresh)
{
return true;
}
// get API chapter hash value
$api_hash = $this->chapters->sha($translation, $book, $chapter);
// confirm chapter hash has not changed
if (hash_equals($hash, $api_hash))
{
return true;
}
if ($this->update($translation, $book, $chapter))
{
// now update the hash of this chapter
return $this->updateHash($translation, $book, $chapter, $api_hash);
}
}
return false;
}
/**
* Get Translation Hash Value
*
* @param string $translation The translation.
*
* @return object|null The response object or null if an error occurs.
* @since 3.2.0
* @return string|null The sha of the translation
* @since 2.0.1
*/
public function get(int $chapter, int $book, string $translation = 'kjv'): ?object
private function translation(string $translation): ?string
{
return $this->response->get(
$this->http->get(
$this->uri->get($translation . '/' . $book . '/' . $chapter . '.json')
)
);
// check local value
if (($translation_sha = $this->load->value(['abbreviation' => $translation], 'sha', 'translation')) !== null)
{
return $translation_sha;
}
// get all the translations
$translations = $this->translations->list();
// check return data
if (!isset($translations->{$translation}) || !isset($translations->{$translation}->sha))
{
return null;
}
// add them to the database
$this->insert->items((array) $translations, 'translation');
return $translations->{$translation}->sha;
}
/**
* Get Book Hash Value
*
* @param string $translation The translation.
* @param int $book The book number.
*
* @return string|null The sha of the book
* @since 2.0.1
*/
private function book(string $translation, int $book): ?string
{
// check local value
if (($book_sha = $this->load->value(['abbreviation' => $translation, 'nr' => $book], 'sha', 'book')) !== null)
{
return $book_sha;
}
// get all the books
$books = $this->books->list($translation);
// check return data
if (!isset($books->{$book}) || !isset($books->{$book}->sha))
{
return null;
}
// add them to the database
$this->insert->items((array) $books, 'book');
return $books->{$book}->sha;
}
/**
* Get Chapter Hash Value
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return string|null The sha of the chapter
* @since 2.0.1
*/
private function chapter(string $translation, int $book, int $chapter): ?string
{
// check local value
if (($chapter_sha = $this->load->value(
['abbreviation' => $translation, 'nr' => $book, 'chapter' => $chapter],
'sha', 'chapter'
)) !== null)
{
return $chapter_sha;
}
// get all the books
$chapters = $this->chapters->list($translation, $book);
// check return data
if (!isset($chapters->{$chapter}) || !isset($chapters->{$chapter}->sha))
{
return null;
}
// add them to the database
$this->insert->items((array) $chapters, 'chapter');
return $chapters->{$chapter}->sha;
}
/**
* Load verses if not in local database
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return bool True if in local database
* @since 2.0.1
*/
private function verses(string $translation, int $book, int $chapter): bool
{
// check local value
if (($name = $this->load->value(
['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter, 'verse' => 1],
'name', 'verse'
)) !== null)
{
return true;
}
// get all the verses
if (($verses = $this->verses->get($translation, $book, $chapter)) === null)
{
return false;
}
// dynamic update all verse objects
$insert = ['book_nr' => $book, 'abbreviation' => $translation];
array_walk($verses->verses, function ($item, $key) use ($insert) {
foreach ($insert as $k => $v) { $item->$k = $v; }
});
$this->fresh = true;
// add them to the database
return $this->insert->items((array) $verses->verses, 'verse');
}
/**
* Trigger the update of the verses of a translation-book-chapter
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
*
* @return bool True if update was a success
* @since 2.0.1
*/
private function update(string $translation, int $book, int $chapter): bool
{
// load all the verses from the local database
if (($verses = $this->load->items(
['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter],
'verse'
)) !== null)
{
// get verses from the API
if (($api = $this->verses->get($translation, $book, $chapter)) === null)
{
return false;
}
$api_verses = (array) $api->verses;
$update = [];
// dynamic update all verse objects
foreach ($verses as $verse)
{
if (($object = $this->getVerse((int) $verse->verse, $api_verses)) !== null)
{
$object->id = $verse->id;
$update[] = $object;
}
}
// update the local verses
if ($update !== [] && $this->update->items($update, 'id', 'verse'))
{
return true;
}
}
return false;
}
/**
* Get a verse text from the API array of verses
*
* @param int $number The verse number.
* @param array $verses The api verses
*
* @return object|null The verse string
* @since 2.0.1
*/
private function getVerse(int $number, array &$verses): ?object
{
foreach ($verses as $verse)
{
if ($verse->verse === $number)
{
return $verse;
}
}
return null;
}
/**
* Trigger the update of a chapter hash value
*
* @param string $translation The translation.
* @param int $book The book number.
* @param int $chapter The chapter number.
* @param string $hash The API chapter hash value.
*
* @return bool True if update was a success
* @since 2.0.1
*/
private function updateHash(string $translation, int $book, int $chapter, string $hash): bool
{
// load the chapter
if (($chapter = $this->load->value(
['abbreviation' => $translation, 'book_nr' => $book, 'chapter' => $chapter],
'id', 'chapter'
)) !== null)
{
$update = [];
$update['id'] = $chapter;
$update['sha'] = $hash;
// update the local verses
return $this->update->row($update, 'id', 'chapter');
}
return false;
}

View File

@ -1,7 +1,7 @@
{
"add_head": "0",
"add_licensing_template": "2",
"extends": "7b490e63-8d1f-46de-a0c4-154272fd5d7f",
"extends": "0",
"guid": "f815fb33-f721-48a5-a84e-53f1986e8881",
"implements": null,
"load_selection": null,
@ -9,9 +9,38 @@
"power_version": "1.0.0",
"system_name": "Joomla.GetBible.Watcher",
"type": "final class",
"use_selection": null,
"use_selection": {
"use_selection0": {
"use": "c03b9c61-17d3-4774-a335-783903719f83",
"as": "default"
},
"use_selection1": {
"use": "a07d90f6-6ff2-40a1-99c1-0f2cf33c9adf",
"as": "default"
},
"use_selection2": {
"use": "d7a5f0c6-de60-4d31-b3e4-5d668a8f7d2e",
"as": "default"
},
"use_selection3": {
"use": "be0cae8b-4b78-4f59-b97b-9e31ee6f52e0",
"as": "default"
},
"use_selection4": {
"use": "491c91ce-6355-40d3-bbbd-622473c6c026",
"as": "default"
},
"use_selection5": {
"use": "a752e4b2-9b5e-4188-8d33-3799c46d5119",
"as": "default"
},
"use_selection6": {
"use": "afa508bf-78f8-4616-97cc-f2809584c086",
"as": "default"
}
},
"namespace": "VDM\\Joomla\\GetBible\\Watcher",
"description": "The GetBible Watcher\r\n\r\n@since 3.2.0",
"description": "The GetBible Watcher\r\n\r\n@since 2.0.1",
"licensing_template": "\/**\r\n * @package GetBible\r\n *\r\n * @created 30th May, 2023\r\n * @author Llewellyn van der Merwe <https:\/\/dev.vdm.io>\r\n * @git GetBible <https:\/\/git.vdm.dev\/getBible>\r\n * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.\r\n * @license GNU General Public License version 2 or later; see LICENSE.txt\r\n *\/\r\n",
"head": "",
"composer": ""