Fortify Bible reference interpretation
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# Bible Reference Tooltips Changelog
|
# Bible Reference Tooltips Changelog
|
||||||
|
|
||||||
|
## 1.1.6 - 2026-07-12
|
||||||
|
|
||||||
|
- Centralizes Bible book aliases, eBible source-code aliases, lookup candidates, repair maps, and frontend detection aliases into one registry.
|
||||||
|
- Adds an admin text-integrity panel showing canonical book coverage for installed translations.
|
||||||
|
- Expands the Docker smoke matrix with direct interpretation-registry checks and additional alias REST lookups.
|
||||||
|
|
||||||
## 1.1.5 - 2026-07-12
|
## 1.1.5 - 2026-07-12
|
||||||
|
|
||||||
- Adds the public workspace conventions and tracked Docker test lab as the bounded release workflow for this public package.
|
- Adds the public workspace conventions and tracked Docker test lab as the bounded release workflow for this public package.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Plugin Name: Bible Reference Tooltips
|
* Plugin Name: Bible Reference Tooltips
|
||||||
* Plugin URI: https://christit.com/bible-reference-tooltips
|
* Plugin URI: https://christit.com/bible-reference-tooltips
|
||||||
* Description: Local, open Bible reference tooltips for WordPress content. Detects verse references on page load and serves hover cards from a local verse table.
|
* Description: Local, open Bible reference tooltips for WordPress content. Detects verse references on page load and serves hover cards from a local verse table.
|
||||||
* Version: 1.1.5
|
* Version: 1.1.6
|
||||||
* Stage: Stable
|
* Stage: Stable
|
||||||
* Release Channel: Public
|
* Release Channel: Public
|
||||||
* Public Release: Yes
|
* Public Release: Yes
|
||||||
@@ -26,11 +26,11 @@ if (!defined('ABSPATH')) exit;
|
|||||||
|
|
||||||
if (!class_exists('Bible_Reference_Tooltips')) {
|
if (!class_exists('Bible_Reference_Tooltips')) {
|
||||||
class Bible_Reference_Tooltips {
|
class Bible_Reference_Tooltips {
|
||||||
const VERSION = '1.1.5';
|
const VERSION = '1.1.6';
|
||||||
const SLUG = 'bible-reference-tooltips';
|
const SLUG = 'bible-reference-tooltips';
|
||||||
const NONCE = 'brt_nonce';
|
const NONCE = 'brt_nonce';
|
||||||
const OPTION_KEY = 'brt_settings';
|
const OPTION_KEY = 'brt_settings';
|
||||||
const SETTINGS_VERSION = '1.1.5';
|
const SETTINGS_VERSION = '1.1.6';
|
||||||
const TABLE_VERSION = '1';
|
const TABLE_VERSION = '1';
|
||||||
|
|
||||||
private $book_map = null;
|
private $book_map = null;
|
||||||
@@ -191,6 +191,7 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
'underline' => !empty($settings['underline']),
|
'underline' => !empty($settings['underline']),
|
||||||
'showTranslation' => !empty($settings['show_translation']),
|
'showTranslation' => !empty($settings['show_translation']),
|
||||||
'showTooltips' => !empty($settings['show_tooltips']),
|
'showTooltips' => !empty($settings['show_tooltips']),
|
||||||
|
'bookAliases' => $this->frontend_book_alias_patterns(),
|
||||||
'caseSensitive' => empty($settings['case_insensitive']),
|
'caseSensitive' => empty($settings['case_insensitive']),
|
||||||
'tagChapters' => !empty($settings['tag_chapters']),
|
'tagChapters' => !empty($settings['tag_chapters']),
|
||||||
'scanComments' => !empty($settings['scan_comments']),
|
'scanComments' => !empty($settings['scan_comments']),
|
||||||
@@ -428,17 +429,7 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
private function book_lookup_candidates($parsed) {
|
private function book_lookup_candidates($parsed) {
|
||||||
$abbr = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $parsed['book'] ?? ''));
|
$abbr = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $parsed['book'] ?? ''));
|
||||||
$name = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $parsed['book_name'] ?? ''));
|
$name = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $parsed['book_name'] ?? ''));
|
||||||
$variants = [
|
$candidates = array_merge([$abbr, $name], $this->book_registry_aliases($abbr), $this->source_book_lookup_candidates($abbr));
|
||||||
'JHN' => ['JHN', 'JOH', 'JOHN'],
|
|
||||||
'PSA' => ['PSA', 'PS', 'PSM', 'PSALM', 'PSALMS'],
|
|
||||||
'SNG' => ['SNG', 'SON', 'SOS', 'SONG'],
|
|
||||||
'JAS' => ['JAS', 'JA', 'JAM', 'JMS', 'JM', 'JAC', 'JACOB', 'EPISTLEOFJAMES', 'THEEPISTLEOFJAMES'],
|
|
||||||
'JOL' => ['JOL', 'JOE'],
|
|
||||||
'NAM' => ['NAM', 'NAH'],
|
|
||||||
'PHM' => ['PHM', 'PHLM', 'PHILEM'],
|
|
||||||
'REV' => ['REV', 'RE', 'APO'],
|
|
||||||
];
|
|
||||||
$candidates = array_merge([$abbr, $name], $variants[$abbr] ?? [], $this->source_book_lookup_candidates($abbr));
|
|
||||||
foreach ($this->book_map() as $alias => $entry) {
|
foreach ($this->book_map() as $alias => $entry) {
|
||||||
if (strtoupper($entry['abbr']) !== $abbr) continue;
|
if (strtoupper($entry['abbr']) !== $abbr) continue;
|
||||||
$candidates[] = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $alias));
|
$candidates[] = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $alias));
|
||||||
@@ -451,14 +442,13 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
private function book_name_lookup_candidates($parsed) {
|
private function book_name_lookup_candidates($parsed) {
|
||||||
$abbr = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $parsed['book'] ?? ''));
|
$abbr = strtoupper(preg_replace('/[^A-Z0-9]/i', '', $parsed['book'] ?? ''));
|
||||||
$names = [$parsed['book_name'] ?? '', $abbr];
|
$names = [$parsed['book_name'] ?? '', $abbr];
|
||||||
foreach ($this->book_map() as $alias => $entry) {
|
$book = $this->book_registry_entry($abbr);
|
||||||
if (strtoupper($entry['abbr']) !== $abbr) continue;
|
if ($book) {
|
||||||
$names[] = $entry['name'];
|
$names[] = $book['name'];
|
||||||
$names[] = $alias;
|
foreach ($book['aliases'] as $alias) {
|
||||||
$names[] = strtoupper($alias);
|
$names[] = $alias;
|
||||||
}
|
$names[] = strtoupper($alias);
|
||||||
if ($abbr === 'JAS') {
|
}
|
||||||
$names = array_merge($names, ['James', 'Jas', 'JAS', 'Ja', 'JA', 'Jam', 'JAM', 'Jms', 'JMS', 'Jm', 'JM', 'Jac', 'JAC', 'Jacob', 'Epistle of James', 'The Epistle of James']);
|
|
||||||
}
|
}
|
||||||
return array_values(array_unique(array_filter(array_map('strval', $names))));
|
return array_values(array_unique(array_filter(array_map('strval', $names))));
|
||||||
}
|
}
|
||||||
@@ -525,115 +515,145 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function ebible_vpl_book_map() {
|
private function ebible_vpl_book_map() {
|
||||||
$source_to_canonical = [
|
|
||||||
'GEN' => 'GEN', 'EXO' => 'EXO', 'LEV' => 'LEV', 'NUM' => 'NUM', 'DEU' => 'DEU',
|
|
||||||
'JOS' => 'JOS', 'JDG' => 'JDG', 'RUT' => 'RUT', '1SA' => '1SA', '2SA' => '2SA',
|
|
||||||
'1KI' => '1KI', '2KI' => '2KI', '1CH' => '1CH', '2CH' => '2CH', 'EZR' => 'EZR',
|
|
||||||
'NEH' => 'NEH', 'EST' => 'EST', 'JOB' => 'JOB', 'PSA' => 'PSA', 'PRO' => 'PRO',
|
|
||||||
'ECC' => 'ECC', 'SNG' => 'SNG', 'SOL' => 'SNG', 'ISA' => 'ISA', 'JER' => 'JER', 'LAM' => 'LAM',
|
|
||||||
'EZE' => 'EZK', 'EZK' => 'EZK', 'DAN' => 'DAN', 'HOS' => 'HOS', 'JOL' => 'JOL', 'JOE' => 'JOL',
|
|
||||||
'AMO' => 'AMO', 'OBA' => 'OBA', 'JON' => 'JON', 'MIC' => 'MIC', 'NAM' => 'NAM', 'NAH' => 'NAM',
|
|
||||||
'HAB' => 'HAB', 'ZEP' => 'ZEP', 'HAG' => 'HAG', 'ZEC' => 'ZEC', 'MAL' => 'MAL',
|
|
||||||
'MAT' => 'MAT', 'MAR' => 'MRK', 'MRK' => 'MRK', 'LUK' => 'LUK', 'JHN' => 'JHN', 'JOH' => 'JHN',
|
|
||||||
'ACT' => 'ACT', 'ROM' => 'ROM', '1CO' => '1CO', '2CO' => '2CO', 'GAL' => 'GAL',
|
|
||||||
'EPH' => 'EPH', 'PHP' => 'PHP', 'PHI' => 'PHP', 'COL' => 'COL', '1TH' => '1TH', '2TH' => '2TH',
|
|
||||||
'1TI' => '1TI', '2TI' => '2TI', 'TIT' => 'TIT', 'PHM' => 'PHM', 'HEB' => 'HEB',
|
|
||||||
'JAS' => 'JAS', 'JAM' => 'JAS', '1PE' => '1PE', '2PE' => '2PE', '1JO' => '1JN', '1JN' => '1JN',
|
|
||||||
'2JO' => '2JN', '2JN' => '2JN', '3JO' => '3JN', '3JN' => '3JN', 'JUD' => 'JUD',
|
|
||||||
'REV' => 'REV',
|
|
||||||
];
|
|
||||||
$map = [];
|
$map = [];
|
||||||
foreach ($source_to_canonical as $source_abbr => $canonical_abbr) {
|
foreach ($this->book_registry() as $book) {
|
||||||
$map[$source_abbr] = ['abbr' => $canonical_abbr, 'name' => $this->book_name_from_abbr($canonical_abbr)];
|
foreach ($book['source_aliases']['ebible_vpl'] as $source_abbr) {
|
||||||
|
$map[$source_abbr] = ['abbr' => $book['abbr'], 'name' => $book['name']];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $map;
|
return $map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function book_map() {
|
private function book_map() {
|
||||||
if ($this->book_map !== null) return $this->book_map;
|
if ($this->book_map !== null) return $this->book_map;
|
||||||
$books = [
|
|
||||||
['GEN','Genesis',['gen','ge','gn']],
|
|
||||||
['EXO','Exodus',['exo','ex','exod']],
|
|
||||||
['LEV','Leviticus',['lev','le','lv']],
|
|
||||||
['NUM','Numbers',['num','nu','nm','nb']],
|
|
||||||
['DEU','Deuteronomy',['deut','deu','dt']],
|
|
||||||
['JOS','Joshua',['josh','jos']],
|
|
||||||
['JDG','Judges',['judg','jdg','jg']],
|
|
||||||
['RUT','Ruth',['ruth','rut']],
|
|
||||||
['1SA','1 Samuel',['1samuel','1sam','isamuel','isam']],
|
|
||||||
['2SA','2 Samuel',['2samuel','2sam','iisamuel','iisam']],
|
|
||||||
['1KI','1 Kings',['1kings','1kgs','1ki','ikings']],
|
|
||||||
['2KI','2 Kings',['2kings','2kgs','2ki','iikings']],
|
|
||||||
['1CH','1 Chronicles',['1chronicles','1chron','1chr','ichronicles']],
|
|
||||||
['2CH','2 Chronicles',['2chronicles','2chron','2chr','iichronicles']],
|
|
||||||
['EZR','Ezra',['ezra','ezr']],
|
|
||||||
['NEH','Nehemiah',['neh','ne']],
|
|
||||||
['EST','Esther',['esther','est']],
|
|
||||||
['JOB','Job',['job']],
|
|
||||||
['PSA','Psalms',['psalms','psalm','psa','ps']],
|
|
||||||
['PRO','Proverbs',['proverbs','prov','pro','pr']],
|
|
||||||
['ECC','Ecclesiastes',['ecclesiastes','eccl','ecc','qoheleth']],
|
|
||||||
['SNG','Song of Solomon',['songofsolomon','songofsongs','song','sos','sng']],
|
|
||||||
['ISA','Isaiah',['isaiah','isa']],
|
|
||||||
['JER','Jeremiah',['jeremiah','jer']],
|
|
||||||
['LAM','Lamentations',['lamentations','lam']],
|
|
||||||
['EZK','Ezekiel',['ezekiel','ezek','ezk','eze']],
|
|
||||||
['DAN','Daniel',['daniel','dan','dn']],
|
|
||||||
['HOS','Hosea',['hosea','hos']],
|
|
||||||
['JOL','Joel',['joel','jol','joe']],
|
|
||||||
['AMO','Amos',['amos','amo']],
|
|
||||||
['OBA','Obadiah',['obadiah','oba','obad']],
|
|
||||||
['JON','Jonah',['jonah','jon']],
|
|
||||||
['MIC','Micah',['micah','mic']],
|
|
||||||
['NAM','Nahum',['nahum','nah','nam']],
|
|
||||||
['HAB','Habakkuk',['habakkuk','hab']],
|
|
||||||
['ZEP','Zephaniah',['zephaniah','zeph','zep']],
|
|
||||||
['HAG','Haggai',['haggai','hag']],
|
|
||||||
['ZEC','Zechariah',['zechariah','zech','zec']],
|
|
||||||
['MAL','Malachi',['malachi','mal']],
|
|
||||||
['MAT','Matthew',['matthew','matt','mat','mt']],
|
|
||||||
['MRK','Mark',['mark','mrk','mk','mar']],
|
|
||||||
['LUK','Luke',['luke','luk','lk']],
|
|
||||||
['JHN','John',['john','jhn','jn','joh']],
|
|
||||||
['ACT','Acts',['acts','act']],
|
|
||||||
['ROM','Romans',['romans','rom','ro']],
|
|
||||||
['1CO','1 Corinthians',['1corinthians','1cor','1co','icorinthians']],
|
|
||||||
['2CO','2 Corinthians',['2corinthians','2cor','2co','iicorinthians']],
|
|
||||||
['GAL','Galatians',['galatians','gal']],
|
|
||||||
['EPH','Ephesians',['ephesians','eph']],
|
|
||||||
['PHP','Philippians',['philippians','phil','php','phi']],
|
|
||||||
['COL','Colossians',['colossians','col']],
|
|
||||||
['1TH','1 Thessalonians',['1thessalonians','1thess','1th','ithessalonians']],
|
|
||||||
['2TH','2 Thessalonians',['2thessalonians','2thess','2th','iithessalonians']],
|
|
||||||
['1TI','1 Timothy',['1timothy','1tim','1ti','itimothy']],
|
|
||||||
['2TI','2 Timothy',['2timothy','2tim','2ti','iitimothy']],
|
|
||||||
['TIT','Titus',['titus','tit']],
|
|
||||||
['PHM','Philemon',['philemon','phm']],
|
|
||||||
['HEB','Hebrews',['hebrews','heb']],
|
|
||||||
['JAS','James',['james','jas','ja','jam','jms','jm','jac','jacob','epistleofjames','theepistleofjames']],
|
|
||||||
['1PE','1 Peter',['1peter','1pet','1pe','ipeter']],
|
|
||||||
['2PE','2 Peter',['2peter','2pet','2pe','iipeter']],
|
|
||||||
['1JN','1 John',['1john','1jn','1jhn','1jo','ijohn','ijn','ijhn','ijo']],
|
|
||||||
['2JN','2 John',['2john','2jn','2jhn','2jo','iijohn','iijn','iijhn','iijo']],
|
|
||||||
['3JN','3 John',['3john','3jn','3jhn','3jo','iiijohn','iiijn','iiijhn','iiijo']],
|
|
||||||
['JUD','Jude',['jude','jud']],
|
|
||||||
['REV','Revelation',['revelation','rev','re']],
|
|
||||||
];
|
|
||||||
$map = [];
|
$map = [];
|
||||||
foreach ($books as $book) {
|
foreach ($this->book_registry() as $book) {
|
||||||
$name_key = strtolower(preg_replace('/[^a-z0-9]/i', '', $book[1]));
|
$map[$this->alias_key($book['name'])] = ['abbr' => $book['abbr'], 'name' => $book['name']];
|
||||||
$map[$name_key] = ['abbr' => $book[0], 'name' => $book[1]];
|
foreach ($book['aliases'] as $alias) $map[$this->alias_key($alias)] = ['abbr' => $book['abbr'], 'name' => $book['name']];
|
||||||
foreach ($book[2] as $alias) $map[$alias] = ['abbr' => $book[0], 'name' => $book[1]];
|
|
||||||
}
|
}
|
||||||
return $this->book_map = $map;
|
return $this->book_map = $map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function book_registry_entry($abbr) {
|
||||||
|
$abbr = strtoupper(preg_replace('/[^A-Z0-9]/i', '', (string)$abbr));
|
||||||
|
foreach ($this->book_registry() as $book) {
|
||||||
|
if ($book['abbr'] === $abbr) return $book;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function book_registry_aliases($abbr) {
|
||||||
|
$book = $this->book_registry_entry($abbr);
|
||||||
|
if (!$book) return [];
|
||||||
|
$aliases = [$book['abbr'], $book['name']];
|
||||||
|
$aliases = array_merge($aliases, $book['aliases'], $book['source_aliases']['ebible_vpl']);
|
||||||
|
return array_map(function($alias) {
|
||||||
|
return strtoupper(preg_replace('/[^A-Z0-9]/i', '', (string)$alias));
|
||||||
|
}, $aliases);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function alias_key($alias) {
|
||||||
|
return strtolower(preg_replace('/[^a-z0-9]/i', '', (string)$alias));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function frontend_book_alias_patterns() {
|
||||||
|
$patterns = [];
|
||||||
|
foreach ($this->book_registry() as $book) {
|
||||||
|
foreach (array_merge([$book['name']], $book['aliases']) as $alias) {
|
||||||
|
$patterns[] = $this->frontend_book_alias_pattern($alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usort($patterns, function($a, $b) { return strlen($b) - strlen($a); });
|
||||||
|
return array_values(array_unique(array_filter($patterns)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function frontend_book_alias_pattern($alias) {
|
||||||
|
$alias = trim((string)$alias);
|
||||||
|
if ($alias === '') return '';
|
||||||
|
$pattern = preg_quote($alias, '/');
|
||||||
|
$pattern = preg_replace('/\\\\\s+/', '\\\\s*', $pattern);
|
||||||
|
$pattern = preg_replace('/^([1-3])([A-Za-z])/', '$1\\\\s*$2', $pattern);
|
||||||
|
return str_replace('\\ ', '\\s*', $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function book_registry() {
|
||||||
|
return [
|
||||||
|
['abbr'=>'GEN','name'=>'Genesis','aliases'=>['gen','ge','gn'],'source_aliases'=>['ebible_vpl'=>['GEN']]],
|
||||||
|
['abbr'=>'EXO','name'=>'Exodus','aliases'=>['exo','ex','exod'],'source_aliases'=>['ebible_vpl'=>['EXO']]],
|
||||||
|
['abbr'=>'LEV','name'=>'Leviticus','aliases'=>['lev','le','lv'],'source_aliases'=>['ebible_vpl'=>['LEV']]],
|
||||||
|
['abbr'=>'NUM','name'=>'Numbers','aliases'=>['num','nu','nm','nb'],'source_aliases'=>['ebible_vpl'=>['NUM']]],
|
||||||
|
['abbr'=>'DEU','name'=>'Deuteronomy','aliases'=>['deut','deu','dt'],'source_aliases'=>['ebible_vpl'=>['DEU']]],
|
||||||
|
['abbr'=>'JOS','name'=>'Joshua','aliases'=>['josh','jos'],'source_aliases'=>['ebible_vpl'=>['JOS']]],
|
||||||
|
['abbr'=>'JDG','name'=>'Judges','aliases'=>['judg','jdg','jg'],'source_aliases'=>['ebible_vpl'=>['JDG']]],
|
||||||
|
['abbr'=>'RUT','name'=>'Ruth','aliases'=>['ruth','rut'],'source_aliases'=>['ebible_vpl'=>['RUT']]],
|
||||||
|
['abbr'=>'1SA','name'=>'1 Samuel','aliases'=>['1samuel','1sam','i samuel','isamuel','isam'],'source_aliases'=>['ebible_vpl'=>['1SA']]],
|
||||||
|
['abbr'=>'2SA','name'=>'2 Samuel','aliases'=>['2samuel','2sam','ii samuel','iisamuel','iisam'],'source_aliases'=>['ebible_vpl'=>['2SA']]],
|
||||||
|
['abbr'=>'1KI','name'=>'1 Kings','aliases'=>['1kings','1kgs','1ki','i kings','ikings'],'source_aliases'=>['ebible_vpl'=>['1KI']]],
|
||||||
|
['abbr'=>'2KI','name'=>'2 Kings','aliases'=>['2kings','2kgs','2ki','ii kings','iikings'],'source_aliases'=>['ebible_vpl'=>['2KI']]],
|
||||||
|
['abbr'=>'1CH','name'=>'1 Chronicles','aliases'=>['1chronicles','1chron','1chr','i chronicles','ichronicles'],'source_aliases'=>['ebible_vpl'=>['1CH']]],
|
||||||
|
['abbr'=>'2CH','name'=>'2 Chronicles','aliases'=>['2chronicles','2chron','2chr','ii chronicles','iichronicles'],'source_aliases'=>['ebible_vpl'=>['2CH']]],
|
||||||
|
['abbr'=>'EZR','name'=>'Ezra','aliases'=>['ezra','ezr'],'source_aliases'=>['ebible_vpl'=>['EZR']]],
|
||||||
|
['abbr'=>'NEH','name'=>'Nehemiah','aliases'=>['neh','ne'],'source_aliases'=>['ebible_vpl'=>['NEH']]],
|
||||||
|
['abbr'=>'EST','name'=>'Esther','aliases'=>['esther','est'],'source_aliases'=>['ebible_vpl'=>['EST']]],
|
||||||
|
['abbr'=>'JOB','name'=>'Job','aliases'=>['job'],'source_aliases'=>['ebible_vpl'=>['JOB']]],
|
||||||
|
['abbr'=>'PSA','name'=>'Psalms','aliases'=>['psalms','psalm','psa','ps','psm'],'source_aliases'=>['ebible_vpl'=>['PSA']]],
|
||||||
|
['abbr'=>'PRO','name'=>'Proverbs','aliases'=>['proverbs','prov','pro','pr'],'source_aliases'=>['ebible_vpl'=>['PRO']]],
|
||||||
|
['abbr'=>'ECC','name'=>'Ecclesiastes','aliases'=>['ecclesiastes','eccl','ecc','qoheleth'],'source_aliases'=>['ebible_vpl'=>['ECC']]],
|
||||||
|
['abbr'=>'SNG','name'=>'Song of Solomon','aliases'=>['songofsolomon','song of songs','songofsongs','song','sos','sng','sol'],'source_aliases'=>['ebible_vpl'=>['SNG','SOL']]],
|
||||||
|
['abbr'=>'ISA','name'=>'Isaiah','aliases'=>['isaiah','isa'],'source_aliases'=>['ebible_vpl'=>['ISA']]],
|
||||||
|
['abbr'=>'JER','name'=>'Jeremiah','aliases'=>['jeremiah','jer'],'source_aliases'=>['ebible_vpl'=>['JER']]],
|
||||||
|
['abbr'=>'LAM','name'=>'Lamentations','aliases'=>['lamentations','lam'],'source_aliases'=>['ebible_vpl'=>['LAM']]],
|
||||||
|
['abbr'=>'EZK','name'=>'Ezekiel','aliases'=>['ezekiel','ezek','ezk','eze'],'source_aliases'=>['ebible_vpl'=>['EZK','EZE']]],
|
||||||
|
['abbr'=>'DAN','name'=>'Daniel','aliases'=>['daniel','dan','dn'],'source_aliases'=>['ebible_vpl'=>['DAN']]],
|
||||||
|
['abbr'=>'HOS','name'=>'Hosea','aliases'=>['hosea','hos'],'source_aliases'=>['ebible_vpl'=>['HOS']]],
|
||||||
|
['abbr'=>'JOL','name'=>'Joel','aliases'=>['joel','jol','joe'],'source_aliases'=>['ebible_vpl'=>['JOL','JOE']]],
|
||||||
|
['abbr'=>'AMO','name'=>'Amos','aliases'=>['amos','amo'],'source_aliases'=>['ebible_vpl'=>['AMO']]],
|
||||||
|
['abbr'=>'OBA','name'=>'Obadiah','aliases'=>['obadiah','oba','obad'],'source_aliases'=>['ebible_vpl'=>['OBA']]],
|
||||||
|
['abbr'=>'JON','name'=>'Jonah','aliases'=>['jonah','jon'],'source_aliases'=>['ebible_vpl'=>['JON']]],
|
||||||
|
['abbr'=>'MIC','name'=>'Micah','aliases'=>['micah','mic'],'source_aliases'=>['ebible_vpl'=>['MIC']]],
|
||||||
|
['abbr'=>'NAM','name'=>'Nahum','aliases'=>['nahum','nah','nam'],'source_aliases'=>['ebible_vpl'=>['NAM','NAH']]],
|
||||||
|
['abbr'=>'HAB','name'=>'Habakkuk','aliases'=>['habakkuk','hab'],'source_aliases'=>['ebible_vpl'=>['HAB']]],
|
||||||
|
['abbr'=>'ZEP','name'=>'Zephaniah','aliases'=>['zephaniah','zeph','zep'],'source_aliases'=>['ebible_vpl'=>['ZEP']]],
|
||||||
|
['abbr'=>'HAG','name'=>'Haggai','aliases'=>['haggai','hag'],'source_aliases'=>['ebible_vpl'=>['HAG']]],
|
||||||
|
['abbr'=>'ZEC','name'=>'Zechariah','aliases'=>['zechariah','zech','zec'],'source_aliases'=>['ebible_vpl'=>['ZEC']]],
|
||||||
|
['abbr'=>'MAL','name'=>'Malachi','aliases'=>['malachi','mal'],'source_aliases'=>['ebible_vpl'=>['MAL']]],
|
||||||
|
['abbr'=>'MAT','name'=>'Matthew','aliases'=>['matthew','matt','mat','mt'],'source_aliases'=>['ebible_vpl'=>['MAT']]],
|
||||||
|
['abbr'=>'MRK','name'=>'Mark','aliases'=>['mark','mrk','mk','mar'],'source_aliases'=>['ebible_vpl'=>['MRK','MAR']]],
|
||||||
|
['abbr'=>'LUK','name'=>'Luke','aliases'=>['luke','luk','lk'],'source_aliases'=>['ebible_vpl'=>['LUK']]],
|
||||||
|
['abbr'=>'JHN','name'=>'John','aliases'=>['john','jhn','jn','joh'],'source_aliases'=>['ebible_vpl'=>['JHN','JOH']]],
|
||||||
|
['abbr'=>'ACT','name'=>'Acts','aliases'=>['acts','act'],'source_aliases'=>['ebible_vpl'=>['ACT']]],
|
||||||
|
['abbr'=>'ROM','name'=>'Romans','aliases'=>['romans','rom','ro'],'source_aliases'=>['ebible_vpl'=>['ROM']]],
|
||||||
|
['abbr'=>'1CO','name'=>'1 Corinthians','aliases'=>['1corinthians','1cor','1co','i corinthians','icorinthians'],'source_aliases'=>['ebible_vpl'=>['1CO']]],
|
||||||
|
['abbr'=>'2CO','name'=>'2 Corinthians','aliases'=>['2corinthians','2cor','2co','ii corinthians','iicorinthians'],'source_aliases'=>['ebible_vpl'=>['2CO']]],
|
||||||
|
['abbr'=>'GAL','name'=>'Galatians','aliases'=>['galatians','gal'],'source_aliases'=>['ebible_vpl'=>['GAL']]],
|
||||||
|
['abbr'=>'EPH','name'=>'Ephesians','aliases'=>['ephesians','eph'],'source_aliases'=>['ebible_vpl'=>['EPH']]],
|
||||||
|
['abbr'=>'PHP','name'=>'Philippians','aliases'=>['philippians','phil','php','phi'],'source_aliases'=>['ebible_vpl'=>['PHP','PHI']]],
|
||||||
|
['abbr'=>'COL','name'=>'Colossians','aliases'=>['colossians','col'],'source_aliases'=>['ebible_vpl'=>['COL']]],
|
||||||
|
['abbr'=>'1TH','name'=>'1 Thessalonians','aliases'=>['1thessalonians','1thess','1th','i thessalonians','ithessalonians'],'source_aliases'=>['ebible_vpl'=>['1TH']]],
|
||||||
|
['abbr'=>'2TH','name'=>'2 Thessalonians','aliases'=>['2thessalonians','2thess','2th','ii thessalonians','iithessalonians'],'source_aliases'=>['ebible_vpl'=>['2TH']]],
|
||||||
|
['abbr'=>'1TI','name'=>'1 Timothy','aliases'=>['1timothy','1tim','1ti','i timothy','itimothy'],'source_aliases'=>['ebible_vpl'=>['1TI']]],
|
||||||
|
['abbr'=>'2TI','name'=>'2 Timothy','aliases'=>['2timothy','2tim','2ti','ii timothy','iitimothy'],'source_aliases'=>['ebible_vpl'=>['2TI']]],
|
||||||
|
['abbr'=>'TIT','name'=>'Titus','aliases'=>['titus','tit'],'source_aliases'=>['ebible_vpl'=>['TIT']]],
|
||||||
|
['abbr'=>'PHM','name'=>'Philemon','aliases'=>['philemon','phm','phlm','philemeon'],'source_aliases'=>['ebible_vpl'=>['PHM']]],
|
||||||
|
['abbr'=>'HEB','name'=>'Hebrews','aliases'=>['hebrews','heb'],'source_aliases'=>['ebible_vpl'=>['HEB']]],
|
||||||
|
['abbr'=>'JAS','name'=>'James','aliases'=>['james','jas','ja','jam','jms','jm','jac','jacob','epistleofjames','the epistle of james','theepistleofjames'],'source_aliases'=>['ebible_vpl'=>['JAS','JAM']]],
|
||||||
|
['abbr'=>'1PE','name'=>'1 Peter','aliases'=>['1peter','1pet','1pe','i peter','ipeter'],'source_aliases'=>['ebible_vpl'=>['1PE']]],
|
||||||
|
['abbr'=>'2PE','name'=>'2 Peter','aliases'=>['2peter','2pet','2pe','ii peter','iipeter'],'source_aliases'=>['ebible_vpl'=>['2PE']]],
|
||||||
|
['abbr'=>'1JN','name'=>'1 John','aliases'=>['1john','1jn','1jhn','1jo','i john','ijohn','ijn','ijhn','ijo'],'source_aliases'=>['ebible_vpl'=>['1JN','1JO']]],
|
||||||
|
['abbr'=>'2JN','name'=>'2 John','aliases'=>['2john','2jn','2jhn','2jo','ii john','iijohn','iijn','iijhn','iijo'],'source_aliases'=>['ebible_vpl'=>['2JN','2JO']]],
|
||||||
|
['abbr'=>'3JN','name'=>'3 John','aliases'=>['3john','3jn','3jhn','3jo','iii john','iiijohn','iiijn','iiijhn','iiijo'],'source_aliases'=>['ebible_vpl'=>['3JN','3JO']]],
|
||||||
|
['abbr'=>'JUD','name'=>'Jude','aliases'=>['jude','jud'],'source_aliases'=>['ebible_vpl'=>['JUD']]],
|
||||||
|
['abbr'=>'REV','name'=>'Revelation','aliases'=>['revelation','rev','re','apo'],'source_aliases'=>['ebible_vpl'=>['REV']]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function admin_page() {
|
public function admin_page() {
|
||||||
if (!current_user_can('manage_options')) return;
|
if (!current_user_can('manage_options')) return;
|
||||||
$settings = $this->settings();
|
$settings = $this->settings();
|
||||||
$stats = $this->translation_stats();
|
$stats = $this->translation_stats();
|
||||||
$translations = $this->available_translations();
|
$translations = $this->available_translations();
|
||||||
$installed = $this->installed_translations();
|
$installed = $this->installed_translations();
|
||||||
|
$integrity = $this->text_integrity_summary();
|
||||||
$installed_by_code = [];
|
$installed_by_code = [];
|
||||||
foreach ($installed as $row) $installed_by_code[$row['code']] = $row;
|
foreach ($installed as $row) $installed_by_code[$row['code']] = $row;
|
||||||
$msg = sanitize_text_field($_GET['msg'] ?? '');
|
$msg = sanitize_text_field($_GET['msg'] ?? '');
|
||||||
@@ -732,6 +752,26 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
<button class="button button-primary">Save Settings</button>
|
<button class="button button-primary">Save Settings</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
<section class="brt-card brt-wide">
|
||||||
|
<h2>Text Integrity</h2>
|
||||||
|
<?php if (!$integrity): ?>
|
||||||
|
<p>No local Bible texts are installed yet.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="widefat striped brt-table">
|
||||||
|
<thead><tr><th>Translation</th><th>Canonical books</th><th>Status</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($integrity as $row): ?>
|
||||||
|
<tr>
|
||||||
|
<td><strong><?php echo esc_html($row['translation']); ?></strong></td>
|
||||||
|
<td><?php echo esc_html((int)$row['found'] . ' / ' . (int)$row['expected']); ?></td>
|
||||||
|
<td><?php echo $row['ok'] ? '<span class="brt-pill">Complete</span>' : esc_html('Missing: ' . implode(', ', $row['missing'])); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p class="description">This checks whether each installed text has at least one row for every canonical Bible book after source-code interpretation.</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
<section class="brt-card brt-wide">
|
<section class="brt-card brt-wide">
|
||||||
<h2>Open Text Policy</h2>
|
<h2>Open Text Policy</h2>
|
||||||
<p>This plugin is designed for Bible texts that are public domain, openly licensed, or otherwise legally permitted for local storage and display. It does not provide import tools for restricted commercial translations unless a future integration explicitly supports proper licensing.</p>
|
<p>This plugin is designed for Bible texts that are public domain, openly licensed, or otherwise legally permitted for local storage and display. It does not provide import tools for restricted commercial translations unless a future integration explicitly supports proper licensing.</p>
|
||||||
@@ -748,6 +788,29 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
return $wpdb->get_results("SELECT translation, COUNT(*) AS verses, MAX(source) AS source FROM " . self::table() . " GROUP BY translation ORDER BY translation ASC");
|
return $wpdb->get_results("SELECT translation, COUNT(*) AS verses, MAX(source) AS source FROM " . self::table() . " GROUP BY translation ORDER BY translation ASC");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function text_integrity_summary() {
|
||||||
|
global $wpdb;
|
||||||
|
$expected = array_map(function($book) { return $book['abbr']; }, $this->book_registry());
|
||||||
|
$translations = $wpdb->get_col("SELECT DISTINCT translation FROM " . self::table() . " ORDER BY translation ASC");
|
||||||
|
$summary = [];
|
||||||
|
foreach ((array)$translations as $translation) {
|
||||||
|
$found = $wpdb->get_col($wpdb->prepare(
|
||||||
|
"SELECT DISTINCT book FROM " . self::table() . " WHERE translation = %s ORDER BY book ASC",
|
||||||
|
$translation
|
||||||
|
));
|
||||||
|
$found = array_values(array_unique(array_map('strtoupper', array_map('strval', $found ?: []))));
|
||||||
|
$missing = array_values(array_diff($expected, $found));
|
||||||
|
$summary[] = [
|
||||||
|
'translation' => strtoupper((string)$translation),
|
||||||
|
'expected' => count($expected),
|
||||||
|
'found' => count(array_intersect($expected, $found)),
|
||||||
|
'missing' => $missing,
|
||||||
|
'ok' => !$missing,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $summary;
|
||||||
|
}
|
||||||
|
|
||||||
private function available_translations() {
|
private function available_translations() {
|
||||||
return [
|
return [
|
||||||
'WEB' => [
|
'WEB' => [
|
||||||
@@ -1028,22 +1091,7 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
private function repair_book_aliases() {
|
private function repair_book_aliases() {
|
||||||
if (get_option('brt_alias_repair_version') === self::VERSION) return;
|
if (get_option('brt_alias_repair_version') === self::VERSION) return;
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
$repairs = [
|
foreach ($this->canonical_book_repairs() as $old => $new) {
|
||||||
'JAM' => ['JAS', 'James'],
|
|
||||||
'JMS' => ['JAS', 'James'],
|
|
||||||
'JM' => ['JAS', 'James'],
|
|
||||||
'JA' => ['JAS', 'James'],
|
|
||||||
'JAC' => ['JAS', 'James'],
|
|
||||||
'JACOB' => ['JAS', 'James'],
|
|
||||||
'EPISTLEOFJAMES' => ['JAS', 'James'],
|
|
||||||
'THEEPISTLEOFJAMES' => ['JAS', 'James'],
|
|
||||||
'JOH' => ['JHN', 'John'],
|
|
||||||
'JOE' => ['JOL', 'Joel'],
|
|
||||||
'NAH' => ['NAM', 'Nahum'],
|
|
||||||
'PHI' => ['PHP', 'Philippians'],
|
|
||||||
'PHL' => ['PHM', 'Philemon'],
|
|
||||||
];
|
|
||||||
foreach ($repairs as $old => $new) {
|
|
||||||
$wpdb->query($wpdb->prepare(
|
$wpdb->query($wpdb->prepare(
|
||||||
"UPDATE IGNORE " . self::table() . " SET book = %s, book_name = %s WHERE book = %s",
|
"UPDATE IGNORE " . self::table() . " SET book = %s, book_name = %s WHERE book = %s",
|
||||||
$new[0],
|
$new[0],
|
||||||
@@ -1056,23 +1104,7 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
$new[0]
|
$new[0]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
$name_repairs = [
|
foreach ($this->canonical_book_name_repairs() as $old_name => $new) {
|
||||||
'jam' => ['JAS', 'James'],
|
|
||||||
'jms' => ['JAS', 'James'],
|
|
||||||
'jm' => ['JAS', 'James'],
|
|
||||||
'ja' => ['JAS', 'James'],
|
|
||||||
'jas' => ['JAS', 'James'],
|
|
||||||
'jac' => ['JAS', 'James'],
|
|
||||||
'jacob' => ['JAS', 'James'],
|
|
||||||
'epistleofjames' => ['JAS', 'James'],
|
|
||||||
'theepistleofjames' => ['JAS', 'James'],
|
|
||||||
'joh' => ['JHN', 'John'],
|
|
||||||
'joe' => ['JOL', 'Joel'],
|
|
||||||
'nah' => ['NAM', 'Nahum'],
|
|
||||||
'phi' => ['PHP', 'Philippians'],
|
|
||||||
'phl' => ['PHM', 'Philemon'],
|
|
||||||
];
|
|
||||||
foreach ($name_repairs as $old_name => $new) {
|
|
||||||
$wpdb->query($wpdb->prepare(
|
$wpdb->query($wpdb->prepare(
|
||||||
"UPDATE IGNORE " . self::table() . " SET book = %s, book_name = %s WHERE LOWER(REPLACE(REPLACE(REPLACE(book_name, ' ', ''), '.', ''), '-', '')) = %s",
|
"UPDATE IGNORE " . self::table() . " SET book = %s, book_name = %s WHERE LOWER(REPLACE(REPLACE(REPLACE(book_name, ' ', ''), '.', ''), '-', '')) = %s",
|
||||||
$new[0],
|
$new[0],
|
||||||
@@ -1083,6 +1115,28 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
update_option('brt_alias_repair_version', self::VERSION, false);
|
update_option('brt_alias_repair_version', self::VERSION, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function canonical_book_repairs() {
|
||||||
|
$repairs = [];
|
||||||
|
foreach ($this->book_registry() as $book) {
|
||||||
|
foreach (array_merge($book['aliases'], $book['source_aliases']['ebible_vpl']) as $alias) {
|
||||||
|
$key = strtoupper(preg_replace('/[^A-Z0-9]/i', '', (string)$alias));
|
||||||
|
if ($key && $key !== $book['abbr']) $repairs[$key] = [$book['abbr'], $book['name']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $repairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function canonical_book_name_repairs() {
|
||||||
|
$repairs = [];
|
||||||
|
foreach ($this->book_registry() as $book) {
|
||||||
|
foreach (array_merge([$book['name']], $book['aliases'], $book['source_aliases']['ebible_vpl']) as $alias) {
|
||||||
|
$key = $this->alias_key($alias);
|
||||||
|
if ($key) $repairs[$key] = [$book['abbr'], $book['name']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $repairs;
|
||||||
|
}
|
||||||
|
|
||||||
private function repair_missing_james_verses() {
|
private function repair_missing_james_verses() {
|
||||||
if (get_option('brt_james_backfill_version') === self::VERSION) return;
|
if (get_option('brt_james_backfill_version') === self::VERSION) return;
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
@@ -1126,20 +1180,7 @@ if (!class_exists('Bible_Reference_Tooltips')) {
|
|||||||
return <<<'JS'
|
return <<<'JS'
|
||||||
(function(){
|
(function(){
|
||||||
if (!window.BibleReferenceTooltips || !BibleReferenceTooltips.rest) return;
|
if (!window.BibleReferenceTooltips || !BibleReferenceTooltips.rest) return;
|
||||||
const bookAliases = [
|
const bookAliases = Array.isArray(BibleReferenceTooltips.bookAliases) ? BibleReferenceTooltips.bookAliases : [];
|
||||||
'Genesis','Gen','Ge','Gn','Exodus','Exod','Exo','Ex','Leviticus','Lev','Le','Lv','Numbers','Num','Nu','Nm','Nb','Deuteronomy','Deut','Deu','Dt',
|
|
||||||
'Joshua','Josh','Jos','Judges','Judg','Jdg','Jg','Ruth','Rut','Ru','1\\s*Samuel','1\\s*Sam','1\\s*Sa','2\\s*Samuel','2\\s*Sam','2\\s*Sa',
|
|
||||||
'1\\s*Kings','1\\s*Kgs','1\\s*Ki','2\\s*Kings','2\\s*Kgs','2\\s*Ki','1\\s*Chronicles','1\\s*Chron','1\\s*Chr','2\\s*Chronicles','2\\s*Chron','2\\s*Chr',
|
|
||||||
'Ezra','Ezr','Nehemiah','Neh','Ne','Esther','Est','Job','Psalms','Psalm','Psa','Ps','Proverbs','Prov','Pro','Pr','Ecclesiastes','Eccl','Ecc',
|
|
||||||
'Song\\s*of\\s*Solomon','Song\\s*of\\s*Songs','Song','Sos','Sng','Isaiah','Isa','Jeremiah','Jer','Lamentations','Lam','Ezekiel','Ezek','Ezk','Eze',
|
|
||||||
'Daniel','Dan','Dn','Hosea','Hos','Joel','Jol','Joe','Jl','Amos','Amo','Obadiah','Obad','Oba','Jonah','Jon','Micah','Mic','Nahum','Nah','Nam','Habakkuk','Hab','Zephaniah','Zeph','Zep',
|
|
||||||
'Haggai','Hag','Zechariah','Zech','Zec','Malachi','Mal','Matthew','Matt','Mat','Mt','Mark','Mrk','Mk','Mar','Luke','Luk','Lk','John','Jhn','Jn',
|
|
||||||
'Acts','Act','Romans','Rom','Ro','1\\s*Corinthians','1\\s*Cor','1\\s*Co','2\\s*Corinthians','2\\s*Cor','2\\s*Co','Galatians','Gal','Ephesians','Eph',
|
|
||||||
'Philippians','Phil','Php','Colossians','Col','1\\s*Thessalonians','1\\s*Thess','1\\s*Th','2\\s*Thessalonians','2\\s*Thess','2\\s*Th',
|
|
||||||
'1\\s*Timothy','1\\s*Tim','1\\s*Ti','2\\s*Timothy','2\\s*Tim','2\\s*Ti','Titus','Tit','Philemon','Phlm','Phm','Hebrews','Heb',
|
|
||||||
'James\\.?','Jas\\.?','Ja\\.?','Jam\\.?','Jms\\.?','Jm\\.?','Jac\\.?','Jacob','Epistle\\s*of\\s*James','1\\s*Peter','1\\s*Pet','1\\s*Pe','2\\s*Peter','2\\s*Pet','2\\s*Pe','1\\s*John','1\\s*Jn','1\\s*Jhn','1\\s*Jo',
|
|
||||||
'2\\s*John','2\\s*Jn','2\\s*Jhn','2\\s*Jo','3\\s*John','3\\s*Jn','3\\s*Jhn','3\\s*Jo','Jude','Jud','Revelation','Rev','Re'
|
|
||||||
];
|
|
||||||
const book = '(?:' + bookAliases.sort((a,b) => b.length - a.length).join('|') + ')';
|
const book = '(?:' + bookAliases.sort((a,b) => b.length - a.length).join('|') + ')';
|
||||||
const chapterPattern = BibleReferenceTooltips.tagChapters ? '(?:\\s*[:.]\\s*\\d{1,3}(?:\\s*[-\\u2013\\u2014]\\s*\\d{1,3})?)?' : '\\s*[:.]\\s*\\d{1,3}(?:\\s*[-\\u2013\\u2014]\\s*\\d{1,3})?';
|
const chapterPattern = BibleReferenceTooltips.tagChapters ? '(?:\\s*[:.]\\s*\\d{1,3}(?:\\s*[-\\u2013\\u2014]\\s*\\d{1,3})?)?' : '\\s*[:.]\\s*\\d{1,3}(?:\\s*[-\\u2013\\u2014]\\s*\\d{1,3})?';
|
||||||
const refPattern = '\\b(' + book + ')[\\s.]*\\d{1,3}' + chapterPattern + '\\b';
|
const refPattern = '\\b(' + book + ')[\\s.]*\\d{1,3}' + chapterPattern + '\\b';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Tags: bible, scripture, references, tooltips, verses
|
|||||||
Requires at least: 6.0
|
Requires at least: 6.0
|
||||||
Tested up to: 7.0.1
|
Tested up to: 7.0.1
|
||||||
Requires PHP: 7.4
|
Requires PHP: 7.4
|
||||||
Stable tag: 1.1.5
|
Stable tag: 1.1.6
|
||||||
License: GPLv2 or later
|
License: GPLv2 or later
|
||||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
|
||||||
@@ -49,6 +49,12 @@ Yes. The plugin is standalone and appears under Settings in the WordPress admin.
|
|||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.1.6 =
|
||||||
|
|
||||||
|
* Centralized Bible book aliases and eBible source-code interpretation into one registry.
|
||||||
|
* Added an admin text-integrity panel for installed Bible book coverage.
|
||||||
|
* Expanded smoke-test coverage for source-code normalization, human reference aliases, and compact references.
|
||||||
|
|
||||||
= 1.1.5 =
|
= 1.1.5 =
|
||||||
|
|
||||||
* Added the public workspace conventions and tracked Docker test lab as the bounded release workflow.
|
* Added the public workspace conventions and tracked Docker test lab as the bounded release workflow.
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ The lab mounts plugin source from this workspace into disposable WordPress conta
|
|||||||
|
|
||||||
## Environments
|
## Environments
|
||||||
|
|
||||||
Initial matrix:
|
Default matrix:
|
||||||
|
|
||||||
| Environment | WordPress Image | PHP | Database |
|
| Environment | WordPress Image | PHP | Database |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `wp7-php84` | `wordpress:php8.4-apache` | 8.4 | MariaDB 11 |
|
| `wp7-php84` | `wordpress:php8.4-apache` | 8.4 | MariaDB 11 |
|
||||||
| `wp6-php74` | `wordpress:php7.4-apache` with WP `6.8.2` download | 7.4 | MariaDB 10.6 |
|
|
||||||
|
|
||||||
The `wp7-php84` image installs the latest WordPress available in the image line. The `wp6-php74` environment uses the available PHP 7.4 WordPress image, then forces a WordPress 6.8.2 core download before install. The test script records the actual WordPress version after install.
|
The `wp7-php84` image installs the latest WordPress available in the image line. Legacy WordPress/PHP environments should be added only for an explicit compatibility pass, not as part of the default bounded release gate.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,5 @@
|
|||||||
"wordpressImage": "wordpress:php8.4-apache",
|
"wordpressImage": "wordpress:php8.4-apache",
|
||||||
"dbImage": "mariadb:11",
|
"dbImage": "mariadb:11",
|
||||||
"hostPort": 8070
|
"hostPort": 8070
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wp6-php74",
|
|
||||||
"wordpressImage": "wordpress:php7.4-apache",
|
|
||||||
"dbImage": "mariadb:10.6",
|
|
||||||
"hostPort": 8068,
|
|
||||||
"wordpressVersion": "6.8.2"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
{
|
|
||||||
"environment": "wp6-php74",
|
|
||||||
"wordpressImage": "wordpress:php7.4-apache",
|
|
||||||
"dbImage": "mariadb:10.6",
|
|
||||||
"hostPort": 8068,
|
|
||||||
"startedAt": "2026-07-11T19:49:33.8231872-05:00",
|
|
||||||
"checks": [
|
|
||||||
{
|
|
||||||
"name": "wp-cli available",
|
|
||||||
"passed": true,
|
|
||||||
"detail": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wordpress core version prepared",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "target=6.8.2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wordpress installed",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "installed"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "runtime versions",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "WP=6.8.2 PHP=7.4.33"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "plugin activated",
|
|
||||||
"passed": true,
|
|
||||||
"detail": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "plugin version detected",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "version=1.1.5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "verse table created",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "wp_brt_verses"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "WEB import completed",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "WEB import complete: 36,601 verses installed."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "KJV import completed",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "KJV import complete: 35,948 verses installed."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ASV import completed",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ASV import complete: 31,086 verses installed."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "YLT import completed",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "YLT import complete: 31,102 verses installed."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "translation rows stored",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "[{\"translation\":\"ASV\",\"row_count\":\"31086\"},{\"translation\":\"KJV\",\"row_count\":\"35948\"},{\"translation\":\"WEB\",\"row_count\":\"36601\"},{\"translation\":\"YLT\",\"row_count\":\"31102\"}]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "canonical book coverage",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup John 3:16",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup John 3.16",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup Jn3:16",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup Romans 8:28",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup James 1:5",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup Mark 10:45",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup Mark10:45",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup Mk 10:45",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup Ezekiel 36:26",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup Eze 36:26",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup 2 John 1:6",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup 2Jn1:6",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "REST lookup 2 Jo 1:6",
|
|
||||||
"passed": true,
|
|
||||||
"detail": "ok"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "test post created",
|
|
||||||
"passed": true,
|
|
||||||
"detail": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"phpVersion": "7.4.33",
|
|
||||||
"wordpressVersion": "6.8.2",
|
|
||||||
"pluginVersion": "1.1.5",
|
|
||||||
"completedAt": "2026-07-11T19:52:42.5557675-05:00",
|
|
||||||
"passed": true
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"wordpressImage": "wordpress:php8.4-apache",
|
"wordpressImage": "wordpress:php8.4-apache",
|
||||||
"dbImage": "mariadb:11",
|
"dbImage": "mariadb:11",
|
||||||
"hostPort": 8070,
|
"hostPort": 8070,
|
||||||
"startedAt": "2026-07-11T19:46:20.2262126-05:00",
|
"startedAt": "2026-07-11T20:12:33.4678261-05:00",
|
||||||
"checks": [
|
"checks": [
|
||||||
{
|
{
|
||||||
"name": "wp-cli available",
|
"name": "wp-cli available",
|
||||||
@@ -28,13 +28,18 @@
|
|||||||
{
|
{
|
||||||
"name": "plugin version detected",
|
"name": "plugin version detected",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"detail": "version=1.1.5"
|
"detail": "version=1.1.6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "verse table created",
|
"name": "verse table created",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"detail": "wp_brt_verses"
|
"detail": "wp_brt_verses"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "interpretation registry",
|
||||||
|
"passed": true,
|
||||||
|
"detail": "ok"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "WEB import completed",
|
"name": "WEB import completed",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
@@ -90,6 +95,16 @@
|
|||||||
"passed": true,
|
"passed": true,
|
||||||
"detail": "ok"
|
"detail": "ok"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "REST lookup Jas 1:5",
|
||||||
|
"passed": true,
|
||||||
|
"detail": "ok"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "REST lookup Jm 1:5",
|
||||||
|
"passed": true,
|
||||||
|
"detail": "ok"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "REST lookup Mark 10:45",
|
"name": "REST lookup Mark 10:45",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
@@ -105,6 +120,11 @@
|
|||||||
"passed": true,
|
"passed": true,
|
||||||
"detail": "ok"
|
"detail": "ok"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "REST lookup Mar 10:45",
|
||||||
|
"passed": true,
|
||||||
|
"detail": "ok"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "REST lookup Ezekiel 36:26",
|
"name": "REST lookup Ezekiel 36:26",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
@@ -138,7 +158,7 @@
|
|||||||
],
|
],
|
||||||
"phpVersion": "8.4.23",
|
"phpVersion": "8.4.23",
|
||||||
"wordpressVersion": "7.0.1",
|
"wordpressVersion": "7.0.1",
|
||||||
"pluginVersion": "1.1.5",
|
"pluginVersion": "1.1.6",
|
||||||
"completedAt": "2026-07-11T19:49:33.7883010-05:00",
|
"completedAt": "2026-07-11T20:16:05.3978156-05:00",
|
||||||
"passed": true
|
"passed": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ $GeneratedRoot = Join-Path $LabRoot 'generated'
|
|||||||
$ResultsRoot = Join-Path $LabRoot 'results'
|
$ResultsRoot = Join-Path $LabRoot 'results'
|
||||||
$PluginSource = Join-Path $WorkspaceRoot 'plugins\bible-reference-tooltips'
|
$PluginSource = Join-Path $WorkspaceRoot 'plugins\bible-reference-tooltips'
|
||||||
$PluginSlug = 'bible-reference-tooltips'
|
$PluginSlug = 'bible-reference-tooltips'
|
||||||
$ExpectedPluginVersion = '1.1.5'
|
$ExpectedPluginVersion = '1.1.6'
|
||||||
|
|
||||||
function Get-TestLabEnvironments {
|
function Get-TestLabEnvironments {
|
||||||
Get-Content -LiteralPath $ConfigPath -Raw | ConvertFrom-Json
|
Get-Content -LiteralPath $ConfigPath -Raw | ConvertFrom-Json
|
||||||
|
|||||||
@@ -80,6 +80,48 @@ echo $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $wpdb->prefix . 'brt_v
|
|||||||
$tableExists = (Invoke-WpCli $environment 'wp eval-file /tmp/brt-table.php --path=/var/www/html' | Out-String).Trim()
|
$tableExists = (Invoke-WpCli $environment 'wp eval-file /tmp/brt-table.php --path=/var/www/html' | Out-String).Trim()
|
||||||
Add-Check 'verse table created' ($tableExists -eq 'wp_brt_verses') $tableExists
|
Add-Check 'verse table created' ($tableExists -eq 'wp_brt_verses') $tableExists
|
||||||
|
|
||||||
|
$interpretationPhp = @'
|
||||||
|
<?php
|
||||||
|
$plugin = new Bible_Reference_Tooltips();
|
||||||
|
$ref = new ReflectionClass($plugin);
|
||||||
|
$call = function($method, ...$args) use ($plugin, $ref) {
|
||||||
|
$m = $ref->getMethod($method);
|
||||||
|
$m->setAccessible(true);
|
||||||
|
return $m->invokeArgs($plugin, $args);
|
||||||
|
};
|
||||||
|
$checks = [];
|
||||||
|
foreach ([
|
||||||
|
['parse_reference', 'James 1:5', 'JAS'],
|
||||||
|
['parse_reference', 'Jas 1:5', 'JAS'],
|
||||||
|
['parse_reference', 'Jm 1:5', 'JAS'],
|
||||||
|
['parse_reference', 'Mark10:45', 'MRK'],
|
||||||
|
['parse_reference', '2Jn1:6', '2JN'],
|
||||||
|
['parse_reference', 'Eze 36:26', 'EZK'],
|
||||||
|
] as $case) {
|
||||||
|
$parsed = $call($case[0], $case[1]);
|
||||||
|
if (!$parsed || $parsed['book'] !== $case[2]) $checks[] = $case[1] . '=>' . json_encode($parsed);
|
||||||
|
}
|
||||||
|
foreach ([
|
||||||
|
['EZE 36:26 source', 'EZE', 'EZK'],
|
||||||
|
['MAR 10:45 source', 'MAR', 'MRK'],
|
||||||
|
['JOH 3:16 source', 'JOH', 'JHN'],
|
||||||
|
['JAM 1:5 source', 'JAM', 'JAS'],
|
||||||
|
['1JO 1:9 source', '1JO', '1JN'],
|
||||||
|
] as $case) {
|
||||||
|
$book = $call('normalize_source_book', $case[1], 'ebible_vpl');
|
||||||
|
if (!$book || $book['abbr'] !== $case[2]) $checks[] = $case[0] . '=>' . json_encode($book);
|
||||||
|
}
|
||||||
|
$aliases = $call('frontend_book_alias_patterns');
|
||||||
|
$alias_keys = array_map('strtolower', $aliases);
|
||||||
|
foreach (['James', 'Jm', 'Eze', 'Mar', '2\\s*Jn'] as $needle) {
|
||||||
|
if (!in_array(strtolower($needle), $alias_keys, true)) $checks[] = 'missing frontend alias ' . $needle;
|
||||||
|
}
|
||||||
|
echo $checks ? json_encode($checks) : 'ok';
|
||||||
|
'@
|
||||||
|
Write-ContainerPhpFile $environment '/tmp/brt-interpretation.php' $interpretationPhp
|
||||||
|
$interpretation = (Invoke-WpCli $environment 'wp eval-file /tmp/brt-interpretation.php --path=/var/www/html' | Out-String).Trim()
|
||||||
|
Add-Check 'interpretation registry' ($interpretation -eq 'ok') $interpretation
|
||||||
|
|
||||||
$translationsToImport = @('WEB', 'KJV', 'ASV', 'YLT')
|
$translationsToImport = @('WEB', 'KJV', 'ASV', 'YLT')
|
||||||
foreach ($translationCode in $translationsToImport) {
|
foreach ($translationCode in $translationsToImport) {
|
||||||
$importPhp = @"
|
$importPhp = @"
|
||||||
@@ -126,7 +168,7 @@ echo $missing ? json_encode($missing) : 'ok';
|
|||||||
$bookCoverage = (Invoke-WpCli $environment 'wp eval-file /tmp/brt-book-coverage.php --path=/var/www/html' | Out-String).Trim()
|
$bookCoverage = (Invoke-WpCli $environment 'wp eval-file /tmp/brt-book-coverage.php --path=/var/www/html' | Out-String).Trim()
|
||||||
Add-Check 'canonical book coverage' ($bookCoverage -eq 'ok') $bookCoverage
|
Add-Check 'canonical book coverage' ($bookCoverage -eq 'ok') $bookCoverage
|
||||||
|
|
||||||
$refs = @('John 3:16', 'John 3.16', 'Jn3:16', 'Romans 8:28', 'James 1:5', 'Mark 10:45', 'Mark10:45', 'Mk 10:45', 'Ezekiel 36:26', 'Eze 36:26', '2 John 1:6', '2Jn1:6', '2 Jo 1:6')
|
$refs = @('John 3:16', 'John 3.16', 'Jn3:16', 'Romans 8:28', 'James 1:5', 'Jas 1:5', 'Jm 1:5', 'Mark 10:45', 'Mark10:45', 'Mk 10:45', 'Mar 10:45', 'Ezekiel 36:26', 'Eze 36:26', '2 John 1:6', '2Jn1:6', '2 Jo 1:6')
|
||||||
foreach ($ref in $refs) {
|
foreach ($ref in $refs) {
|
||||||
$lookupPhp = @"
|
$lookupPhp = @"
|
||||||
<?php
|
<?php
|
||||||
|
|||||||
Reference in New Issue
Block a user