From a9c506497ce2bedaff5202a8a19d929fbdcd4088 Mon Sep 17 00:00:00 2001 From: Joshua Ramon Enslin Date: Thu, 10 Oct 2024 09:51:28 +0200 Subject: [PATCH] Respect diacritics when looking up tag, actor, .. IDs --- src/NodaIDGetter.php | 325 ++++++++++++++++------------ tests/NodaIDGetterTest.php | 433 +++++++++++++++++++++++++++++++++++++ tests/bootstrap.php | 12 +- 3 files changed, 628 insertions(+), 142 deletions(-) create mode 100644 tests/NodaIDGetterTest.php diff --git a/src/NodaIDGetter.php b/src/NodaIDGetter.php index 6742a59..a826be4 100644 --- a/src/NodaIDGetter.php +++ b/src/NodaIDGetter.php @@ -10,6 +10,30 @@ declare(strict_types = 1); * Contains static functions for getting IDs for noda entries by various means. */ final class NodaIDGetter { + /** + * Comparison operation that allows for equality but also returns true + * if capitalization differs. If diacritics are available in one case + * and not in the other, there will be no match. + * This is needed to identify sufficiently exact matches despite a table + * collation of *_ci in MySQL. + * + * @param string $string_one First string in comparison. + * @param string $string_two Second string in comparison. + * + * @return boolean + */ + private static function _stri_matches(string $string_one, string $string_two):bool { + + if ($string_one === $string_two) { + return true; + } + if (\strtolower($string_one) === \strtolower($string_two)) { + return true; + } + + return false; + + } // // Actors @@ -80,21 +104,22 @@ final class NodaIDGetter { if (empty($name)) return 0; - $persinstRewriteResult = $mysqli_noda->query_by_stmt(" - SELECT `persinst_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `persinst_id`, `input_name` FROM `persinst_rewriting` WHERE `language` = ? AND `input_name` = ? LIMIT 1", "ss", $lang, $name); - if ($persinstRewriteData = $persinstRewriteResult->fetch_row()) { - $output = $persinstRewriteData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $persinstRewriteResult->close(); - - return $output; + return 0; } @@ -111,21 +136,22 @@ final class NodaIDGetter { if (empty($name)) return 0; - $persinstByTLNameResult = $mysqli_noda->query_by_stmt(" - SELECT `persinst_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `persinst_id`, `trans_name` FROM `persinst_translation` WHERE `trans_name` = ? AND `trans_language` = ? LIMIT 2", "ss", $name, $lang); - if ($persinstByTlData = $persinstByTLNameResult->fetch_row()) { - $output = $persinstByTlData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $persinstByTLNameResult->close(); - - return $output; + return 0; } @@ -145,8 +171,8 @@ final class NodaIDGetter { if (empty($name)) return 0; - $persinstByTLNameResult = $mysqli_noda->query_by_stmt(" - SELECT `persinst_translation`.`persinst_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `persinst_translation`.`persinst_id`, `trans_name` FROM `persinst_translation`, `persinst` WHERE `persinst_translation`.`persinst_id` = `persinst`.`persinst_id` AND `trans_name` = ? @@ -155,14 +181,15 @@ final class NodaIDGetter { AND `persinst_sterbejahr` = ? LIMIT 2", "ssss", $name, $lang, $birth, $death); - if ($persinstByTlData = $persinstByTLNameResult->fetch_row()) { - $output = $persinstByTlData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $persinstByTLNameResult->close(); - - return $output; + return 0; } @@ -178,22 +205,23 @@ final class NodaIDGetter { if (empty($name)) return 0; - $persinstByBaseNameResult = $mysqli_noda->query_by_stmt(" - SELECT `persinst_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `persinst_id`, `persinst_anzeigename`, `persinst_name`, CONCAT(`persinst_name`, ' (', `persinst_geburtsjahr`, '-', `persinst_sterbejahr`, ')') FROM `persinst` WHERE `persinst_anzeigename` = ? OR `persinst_name` = ? OR CONCAT(`persinst_name`, ' (', `persinst_geburtsjahr`, '-', `persinst_sterbejahr`, ')') = ? LIMIT 2", "sss", $name, $name, $name); - if ($persinstByBaseData = $persinstByBaseNameResult->fetch_row()) { - $output = $persinstByBaseData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name) || self::_stri_matches($cur[2], $name) || self::_stri_matches($cur[3], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $persinstByBaseNameResult->close(); - - return $output; + return 0; } @@ -211,8 +239,8 @@ final class NodaIDGetter { if (empty($name)) return 0; - $persinstByBaseNameResult = $mysqli_noda->query_by_stmt(" - SELECT `persinst_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `persinst_id`, `persinst_anzeigename`, `persinst_name`, CONCAT(`persinst_name`, ' (', `persinst_geburtsjahr`, '-', `persinst_sterbejahr`, ')') FROM `persinst` WHERE ( `persinst_anzeigename` = ? @@ -223,14 +251,15 @@ final class NodaIDGetter { AND `persinst_sterbejahr` = ? LIMIT 2", "sssss", $name, $name, $name, $birth, $death); - if ($persinstByBaseData = $persinstByBaseNameResult->fetch_row()) { - $output = $persinstByBaseData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name) || self::_stri_matches($cur[2], $name) || self::_stri_matches($cur[3], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $persinstByBaseNameResult->close(); - - return $output; + return 0; } @@ -284,22 +313,23 @@ final class NodaIDGetter { if (empty($name)) return 0; $lookUpName = $name . $birthYear . $deathYear; - $persinstByImportLogResult = $mysqli_noda->query_by_stmt(" - SELECT `persinst_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `persinst_id`, `input_string` FROM `persinst_logged_imports` WHERE `instance` = ? AND `institution_id` = ? AND `input_string` = ? LIMIT 2", "sis", $instance, $institution_id, $lookUpName); - if ($persinstByImportLogData = $persinstByImportLogResult->fetch_row()) { - $output = $persinstByImportLogData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $lookUpName)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $persinstByImportLogResult->close(); - - return $output; + return 0; } @@ -345,21 +375,22 @@ final class NodaIDGetter { if (empty($name)) return 0; - $placeRewriteResult = $mysqli_noda->query_by_stmt(" - SELECT `ort_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `ort_id`, `input_name` FROM `ort_rewriting` WHERE `language` = ? AND `input_name` = ? LIMIT 1", "ss", $lang, $name); - if ($placeRewriteData = $placeRewriteResult->fetch_row()) { - $output = $placeRewriteData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $placeRewriteResult->close(); - - return $output; + return 0; } @@ -375,20 +406,21 @@ final class NodaIDGetter { if (empty($name)) return 0; - $placeByBaseNameResult = $mysqli_noda->query_by_stmt(" - SELECT `ort_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `ort_id`, `ort_name` FROM `orte` WHERE `ort_name` = ? LIMIT 2", "s", $name); - if ($placeByBaseData = $placeByBaseNameResult->fetch_row()) { - $output = $placeByBaseData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $placeByBaseNameResult->close(); - - return $output; + return 0; } @@ -405,21 +437,22 @@ final class NodaIDGetter { if (empty($name)) return 0; - $placeByTLNameResult = $mysqli_noda->query_by_stmt(" - SELECT `ort_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `ort_id`, `trans_name` FROM `ort_translation` WHERE `trans_name` = ? AND `trans_language` = ? LIMIT 2", "ss", $name, $lang); - if ($placeByTlData = $placeByTLNameResult->fetch_row()) { - $output = $placeByTlData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $placeByTLNameResult->close(); - - return $output; + return 0; } @@ -470,22 +503,23 @@ final class NodaIDGetter { if (empty($name)) return 0; - $placeByImportLogResult = $mysqli_noda->query_by_stmt(" - SELECT `ort_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `ort_id`, `input_string` FROM `orte_logged_imports` WHERE `instance` = ? AND `institution_id` = ? AND `input_string` = ? LIMIT 2", "sis", $instance, $institution_id, $name); - if ($placeByImportLogData = $placeByImportLogResult->fetch_row()) { - $output = $placeByImportLogData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($cur[1], $name)) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $placeByImportLogResult->close(); - - return $output; + return 0; } @@ -533,17 +567,19 @@ final class NodaIDGetter { $output = []; - $tagRewriteResult = $mysqli_noda->query_by_stmt(" - SELECT `tag_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `tag_id`, `input_name` FROM `tag_rewriting` WHERE `tag_language` = ? AND `input_name` = ?", "ss", $lang, $name); - while ($tagRewriteData = $tagRewriteResult->fetch_row()) { - $output[] = $tagRewriteData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $output[] = $cur[0]; + } } - $tagRewriteResult->close(); + $result->close(); return $output; @@ -561,20 +597,21 @@ final class NodaIDGetter { if (empty($name)) return 0; - $tagByBaseNameResult = $mysqli_noda->query_by_stmt(" - SELECT `tag_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `tag_id`, `tag_name` FROM `tag` WHERE `tag_name` = ? LIMIT 2", "s", $name); - if ($tagByBaseData = $tagByBaseNameResult->fetch_row()) { - $output = $tagByBaseData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $tagByBaseNameResult->close(); - - return $output; + return 0; } @@ -591,21 +628,22 @@ final class NodaIDGetter { if (empty($name)) return 0; - $tagByTLNameResult = $mysqli_noda->query_by_stmt(" - SELECT `tag_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `tag_id`, `trans_name` FROM `tag_translation` WHERE `trans_name` = ? AND `trans_language` = ? LIMIT 2", "ss", $name, $lang); - if ($tagByTlData = $tagByTLNameResult->fetch_row()) { - $output = $tagByTlData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $tagByTLNameResult->close(); - - return $output; + return 0; } @@ -656,22 +694,23 @@ final class NodaIDGetter { if (empty($name)) return 0; - $tagByImportLogResult = $mysqli_noda->query_by_stmt(" - SELECT `tag_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `tag_id`, `input_string` FROM `tag_logged_imports` WHERE `instance` = ? AND `institution_id` = ? AND `input_string` = ? LIMIT 2", "sis", $instance, $institution_id, $name); - if ($tagByImportLogData = $tagByImportLogResult->fetch_row()) { - $output = $tagByImportLogData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $tagByImportLogResult->close(); - - return $output; + return 0; } @@ -719,20 +758,21 @@ final class NodaIDGetter { $output = []; - $timeRewriteResult = $mysqli_noda->query_by_stmt(" - SELECT `zeit_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `zeit_id`, `input_name` FROM `zeit_rewriting` WHERE `language` = ? AND `input_name` = ?", "ss", $lang, $name); - if ($timeRewriteData = $timeRewriteResult->fetch_row()) { - $output = (int)$timeRewriteData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $timeRewriteResult->close(); - - return $output; + return 0; } @@ -748,20 +788,21 @@ final class NodaIDGetter { if (empty($name)) return 0; - $timeByBaseNameResult = $mysqli_noda->query_by_stmt(" - SELECT `zeit_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `zeit_id`, `zeit_name` FROM `zeiten` WHERE `zeit_name` = ? LIMIT 2", "s", $name); - if ($timeByBaseData = $timeByBaseNameResult->fetch_row()) { - $output = $timeByBaseData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $timeByBaseNameResult->close(); - - return $output; + return 0; } @@ -778,21 +819,22 @@ final class NodaIDGetter { if (empty($name)) return 0; - $timeByTLNameResult = $mysqli_noda->query_by_stmt(" - SELECT `zeit_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `zeit_id`, `trans_name` FROM `zeit_translation` WHERE `trans_name` = ? AND `trans_language` = ? LIMIT 2", "ss", $name, $lang); - if ($timeByTlData = $timeByTLNameResult->fetch_row()) { - $output = $timeByTlData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $timeByTLNameResult->close(); - - return $output; + return 0; } @@ -810,22 +852,23 @@ final class NodaIDGetter { if (empty($name)) return 0; - $timeByImportLogResult = $mysqli_noda->query_by_stmt(" - SELECT `zeit_id` + $result = $mysqli_noda->query_by_stmt(" + SELECT `zeit_id`, `input_string` FROM `zeiten_logged_imports` WHERE `instance` = ? AND `institution_id` = ? AND `input_string` = ? LIMIT 2", "sis", $instance, $institution_id, $name); - if ($timeByImportLogData = $timeByImportLogResult->fetch_row()) { - $output = $timeByImportLogData[0]; + while ($cur = $result->fetch_row()) { + if (self::_stri_matches($name, $cur[1])) { + $result->close(); + return (int)$cur[0]; + } } - else $output = 0; + $result->close(); - $timeByImportLogResult->close(); - - return $output; + return 0; } diff --git a/tests/NodaIDGetterTest.php b/tests/NodaIDGetterTest.php new file mode 100644 index 0000000..2a3e974 --- /dev/null +++ b/tests/NodaIDGetterTest.php @@ -0,0 +1,433 @@ + + */ +declare(strict_types = 1); + +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Medium; + +require_once __DIR__ . '/../../MDMysqli/test_connections.conf.php'; + +/** + * Test for functions for looking up entry IDs by their (exact) names. + */ +#[Medium] +#[CoversClass(\NodaIDGetter::class)] +final class NodaIDGetterTest extends TestCase { + + private MDMysqli $_mysqli; + + /** + * Quasi-constructor connects to DB. + * + * @return void + */ + protected function setUp():void { + + $this->_mysqli = md_noda_mysqli_connect(); + + } + + /** + * Gets string and integer value from a mysql query. + * + * @param MDMysqli $mysqli DB connection. + * @param string $query DB query. + * + * @return array{0: string, 1: integer} + */ + private static function _getNameAndIdFromDbQuery(MDMysqli $mysqli, string $query):array { + + $result = $mysqli->do_read_query($query . " + LIMIT 1"); + + if (!($cur = $result->fetch_row())) { + throw new Exception("Failed to get result for query: " . $query); + } + $result->close(); + + return [ + (string)$cur[0], + (int)$cur[1], + ]; + + } + + /** + * Replaces vowels in string with variants with diacritics for testing + * exact matching. + * + * @param string $input Input string. + * + * @return string + */ + public static function _replaceVowelsWithDiacriticVariants(string $input):string { + + return strtr($input, [ + 'a' => 'ä', + 'o' => 'ö', + 'u' => 'ü', + 'i' => 'ï', + 'e' => 'è', + ]); + + } + + /** + * Runs regular tests on the term: + * - Matching by exact same name works. + * - Matching by same name with different capitalization works. + * - Matching by same name with diacritics replacing non-diacritic vowels fails + * (counter to MySQL's _ci-type notations rules). + * + * @param string $function NodaIDGetter's callback function for identification. + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + private function runRegularComparisonTests(string $function, string $name, int $expected_id):void { + + self::assertEquals($expected_id, + NodaIDGetter::$function($this->_mysqli, "de", $name), + "Entry " . $name . " is not matched in exact lookup. Expected ID: " . $expected_id); + + // Ensure that different capitalization does not influence the results + self::assertEquals($expected_id, + NodaIDGetter::$function($this->_mysqli, "de", strtoupper($name))); + self::assertEquals($expected_id, + NodaIDGetter::$function($this->_mysqli, "de", strtolower($name))); + + // Ensure that diacritics will stop the entry from matching + $nameReplaced = self::_replaceVowelsWithDiacriticVariants($name); + self::assertNotEquals($expected_id, + NodaIDGetter::$function($this->_mysqli, "de", $nameReplaced)); + + } + + // PersinstIDByName + + /** + * Returns a test actor name. + * + * @return array + */ + public static function persinstByNameProvider():array { + + $mysqli = md_main_mysqli_connect(); + $persinstByNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `persinst_name`, `persinst_id` + FROM `" . DATABASENAME_NODA . "`.`persinst` + WHERE INSTR(`persinst_name`, 'i')"); + $persinstByDisplayNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `persinst_anzeigename`, `persinst_id` + FROM `" . DATABASENAME_NODA . "`.`persinst` + WHERE INSTR(`persinst_anzeigename`, 'i') + AND `persinst_sterbejahr` != ''"); + $persinstByDisplayNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `trans_name`, `persinst_id` + FROM `" . DATABASENAME_NODA . "`.`persinst_translation` + WHERE INSTR(`trans_name`, 'i') + AND `trans_language` = 'de'"); + $mysqli->close(); + + return [ + 'Persinst ID by name: ' . $persinstByNameSimple[0] => $persinstByNameSimple, + 'Persinst ID by display name: ' . $persinstByDisplayNameSimple[0] => $persinstByDisplayNameSimple, + 'Persinst ID by translated name: ' . $persinstByDisplayNameSimple[0] => $persinstByDisplayNameSimple, + ]; + + } + + /** + * Test getting persinst by name works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('persinstByNameProvider')] + public function testGetPersinstIdByNameWorks(string $name, int $expected_id):void { + + $this->runRegularComparisonTests("getPersinstIDByName", $name, $expected_id); + + } + + // PersinstIDByRewrite + + /** + * Returns a test actor name. + * + * @return array + */ + public static function persinstByRewriteProvider():array { + + $mysqli = md_main_mysqli_connect(); + $persinstByRewriteSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `input_name`, `persinst_id` + FROM `" . DATABASENAME_NODA . "`.`persinst_rewriting` + WHERE INSTR(`input_name`, 'i')"); + $mysqli->close(); + + return [ + 'Persinst ID by rewrite: ' . $persinstByRewriteSimple[0] => $persinstByRewriteSimple, + ]; + + } + + /** + * Test getting persinst by rewrite works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('persinstByRewriteProvider')] + public function testGetPersinstIdByRewriteWorks(string $name, int $expected_id):void { + + $this->runRegularComparisonTests("getPersinstIDByRewrite", $name, $expected_id); + + } + + // PlaceIDByName + + /** + * Returns a test place name. + * + * @return array + */ + public static function placeByNameProvider():array { + + $mysqli = md_main_mysqli_connect(); + $placeByNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `ort_name`, `ort_id` + FROM `" . DATABASENAME_NODA . "`.`orte` + WHERE INSTR(`ort_name`, 'i')"); + $placeByDisplayNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `trans_name`, `ort_id` + FROM `" . DATABASENAME_NODA . "`.`ort_translation` + WHERE INSTR(`trans_name`, 'i') + AND `trans_language` = 'de'"); + $mysqli->close(); + + return [ + 'Place ID by name: ' . $placeByNameSimple[0] => $placeByNameSimple, + 'Place ID by translated name: ' . $placeByDisplayNameSimple[0] => $placeByDisplayNameSimple, + ]; + + } + + /** + * Test getting persinst by name works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('placeByNameProvider')] + public function testGetPlaceIdByNameWorks(string $name, int $expected_id):void { + + $this->runRegularComparisonTests("getPlaceIDByName", $name, $expected_id); + + } + + // PlaceIDByRewrite + + /** + * Returns a test place name registered for rewriting. + * + * @return array + */ + public static function placeByRewriteProvider():array { + + $mysqli = md_main_mysqli_connect(); + $placeByRewriteSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `input_name`, `ort_id` + FROM `" . DATABASENAME_NODA . "`.`ort_rewriting` + WHERE INSTR(`input_name`, 'i')"); + $mysqli->close(); + + return [ + 'Place ID by rewrite: ' . $placeByRewriteSimple[0] => $placeByRewriteSimple, + ]; + + } + + /** + * Test getting places by rewrite works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('placeByRewriteProvider')] + public function testGetPlaceIdByRewriteWorks(string $name, int $expected_id):void { + + $this->runRegularComparisonTests("getPlaceIDByRewrite", $name, $expected_id); + + } + + // TagIDByName + + /** + * Returns a test tag name. + * + * @return array + */ + public static function tagByNameProvider():array { + + $mysqli = md_main_mysqli_connect(); + $tagByNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `tag_name`, `tag_id` + FROM `" . DATABASENAME_NODA . "`.`tag` + WHERE INSTR(`tag_name`, 'i')"); + $tagByDisplayNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `trans_name`, `tag_id` + FROM `" . DATABASENAME_NODA . "`.`tag_translation` + WHERE INSTR(`trans_name`, 'i') + AND `trans_language` = 'de'"); + $mysqli->close(); + + return [ + 'Tag ID by name: ' . $tagByNameSimple[0] => $tagByNameSimple, + 'Tag ID by translated name: ' . $tagByDisplayNameSimple[0] => $tagByDisplayNameSimple, + ]; + + } + + /** + * Test getting tags by name works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('tagByNameProvider')] + public function testGetTagIdByNameWorks(string $name, int $expected_id):void { + + $this->runRegularComparisonTests("getTagIDByName", $name, $expected_id); + + } + + // TagIDByRewrite + + /** + * Returns a test tag name registered for rewriting. + * + * @return array + */ + public static function tagByRewriteProvider():array { + + $mysqli = md_main_mysqli_connect(); + $tagByRewriteSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `input_name`, `tag_id` + FROM `" . DATABASENAME_NODA . "`.`tag_rewriting` + WHERE INSTR(`input_name`, 'i')"); + $mysqli->close(); + + return [ + 'Tag ID by rewrite: ' . $tagByRewriteSimple[0] => $tagByRewriteSimple, + ]; + + } + + /** + * Test getting tags by rewrite works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('tagByRewriteProvider')] + public function testGetTagIdByRewriteWorks(string $name, int $expected_id):void { + + self::assertContains($expected_id, NodaIDGetter::getTagIDByRewrite($this->_mysqli, "de", $name)); + + // Ensure that different capitalization does not influence the results + self::assertContains($expected_id, NodaIDGetter::getTagIDByRewrite($this->_mysqli, "de", strtoupper($name))); + self::assertContains($expected_id, NodaIDGetter::getTagIDByRewrite($this->_mysqli, "de", strtolower($name))); + + // Ensure that diacritics will stop the entry from matching + $nameReplaced = self::_replaceVowelsWithDiacriticVariants($name); + self::assertFalse(in_array($expected_id, NodaIDGetter::getTagIDByRewrite($this->_mysqli, "de", $nameReplaced), true)); + + } + + // TimeIDByName + + /** + * Returns a test time name. + * + * @return array + */ + public static function timeByNameProvider():array { + + $mysqli = md_main_mysqli_connect(); + $timeByNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `zeit_name`, `zeit_id` + FROM `" . DATABASENAME_NODA . "`.`zeiten` + WHERE INSTR(`zeit_name`, 'i')"); + $timeByDisplayNameSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `trans_name`, `zeit_id` + FROM `" . DATABASENAME_NODA . "`.`zeit_translation` + WHERE INSTR(`trans_name`, 'i') + AND `trans_language` = 'de'"); + $mysqli->close(); + + return [ + 'Time ID by name: ' . $timeByNameSimple[0] => $timeByNameSimple, + 'Time ID by translated name: ' . $timeByDisplayNameSimple[0] => $timeByDisplayNameSimple, + ]; + + } + + /** + * Test getting persinst by name works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('timeByNameProvider')] + public function testGetTimeIdByNameWorks(string $name, int $expected_id):void { + + $this->runRegularComparisonTests("getTimeIDByName", $name, $expected_id); + + } + + // timeIDByRewrite + + /** + * Returns a test time name registered for rewriting. + * + * @return array + */ + public static function timeByRewriteProvider():array { + + $mysqli = md_main_mysqli_connect(); + $timeByRewriteSimple = self::_getNameAndIdFromDbQuery($mysqli, "SELECT `input_name`, `zeit_id` + FROM `" . DATABASENAME_NODA . "`.`zeit_rewriting` + WHERE INSTR(`input_name`, 'i')"); + $mysqli->close(); + + return [ + 'Time ID by rewrite: ' . $timeByRewriteSimple[0] => $timeByRewriteSimple, + ]; + + } + + /** + * Test getting times by rewrite works. + * + * @param string $name Name of the entry. + * @param integer $expected_id Expected target ID. + * + * @return void + */ + #[DataProvider('timeByRewriteProvider')] + public function testGetTimeIdByRewriteWorks(string $name, int $expected_id):void { + + $this->runRegularComparisonTests("getTimeIDByRewrite", $name, $expected_id); + + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b1d499e..d27cbb9 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,7 +12,17 @@ declare(strict_types = 1); // Try using class map as defined through /scripts/buildClassMap.php - foreach (array_merge([__DIR__ . '/../tests', __DIR__ . '/../src', __DIR__ . '/../src/enums', __DIR__ . '/../../MD_STD/src', __DIR__ . '/../../MDErrorReporter', __DIR__ . '/../../MDErrorReporter/exceptions', __DIR__ . '/../../MDErrorReporter/exceptions/generic', __DIR__ . '/../../MDErrorReporter/exceptions/updates']) as $classDir) { + foreach (array_merge([__DIR__ . '/../tests', + __DIR__ . '/../src', + __DIR__ . '/../src/enums', + __DIR__ . '/../../MD_STD/src', + __DIR__ . '/../../MDErrorReporter', + __DIR__ . '/../../MDErrorReporter/exceptions', + __DIR__ . '/../../MDErrorReporter/exceptions/generic', + __DIR__ . '/../../MDErrorReporter/exceptions/updates', + __DIR__ . '/../../MDMysqli/src', + __DIR__ . '/../../MDMysqli/exceptions', + ]) as $classDir) { if (\file_exists("$classDir/$className.php")) { include "$classDir/$className.php";