*/ declare(strict_types = 1); /** * Class for keeping the places fulltext index in sync. */ final class NodaPlaceFulltextSync { /** @var MDMysqli */ private MDMysqli $_mysqli_noda; /** * Removes the obsolete entries. * * @return void */ public function removeObsolete():void { $result = $this->_mysqli_noda->do_read_query("SELECT 1 FROM `orte_fulltext` WHERE NOT EXISTS (SELECT 1 FROM `orte` WHERE `orte`.`ort_id` = `orte_fulltext`.`ort_id`) LIMIT 1"); if ($result->num_rows === 0) { $result->close(); $result = null; return; } $result->close(); $result = null; $this->_mysqli_noda->do_update_query_large("DELETE FROM `orte_fulltext` WHERE NOT EXISTS (SELECT 1 FROM `orte` WHERE `orte`.`ort_id` = `orte_fulltext`.`ort_id`)"); } /** * Gets the entries to update. * * @return array */ public function getNewEntries():array { $result = $this->_mysqli_noda->do_read_query("SELECT `ort_id`, `ort_name` FROM `orte` WHERE NOT EXISTS (SELECT 1 FROM `orte_fulltext` WHERE `orte`.`ort_id` = `orte_fulltext`.`ort_id` AND `orte`.`ort_erfasst_am` <= `orte_fulltext`.`update_timestamp`) LIMIT 10000"); if ($result->num_rows === 0) { $result->close(); $result = null; return []; } $toUpdate = []; while ($cur = $result->fetch_assoc()) { $ort_id = (int)$cur['ort_id']; unset($cur['ort_id']); $toUpdate[$ort_id] = $cur; } $result->close(); $result = null; $tlResult = $this->_mysqli_noda->do_read_query("SELECT `ort_translation`.`ort_id`, `trans_name` AS `name` FROM `ort_translation` WHERE `ort_translation`.`ort_id` IN (" . implode(', ', array_keys($toUpdate)) . ")"); $translations = []; while ($cur = $tlResult->fetch_assoc()) { $ort_id = (int)$cur['ort_id']; if (empty($translations[$ort_id])) { $translations[$ort_id] = [$cur['name']]; } else $translations[$ort_id][] = $cur['name']; } $tlResult->close(); $tlResult = null; $newEntries = []; foreach ($toUpdate as $ort_id => $values) { if (isset($translations[$ort_id])) $values = array_merge($values, $translations[$ort_id]); $newEntries[$ort_id] = implode(' ', array_unique($values)); } return $newEntries; } /** * Loads the list of entries to update. * * @return void */ public function update():void { if (empty($toUpdate = $this->getNewEntries())) { return; } if (count($toUpdate) > 1) { $this->_mysqli_noda->autocommit(false); } $updateStmt = $this->_mysqli_noda->do_prepare("INSERT INTO `orte_fulltext` (`ort_id`, `content`, `update_timestamp`) VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE `content` = ?, `update_timestamp` = NOW()"); foreach ($toUpdate as $key => $value) { $updateStmt->bind_param("iss", $key, $value, $value); $updateStmt->execute(); } $updateStmt->close(); $updateStmt = null; if (count($toUpdate) > 1) { $this->_mysqli_noda->commit(); $this->_mysqli_noda->autocommit(true); } } /** * Sync: Wrapper function glueing together the sync process. * * @return void */ public function sync():void { $this->removeObsolete(); $this->update(); } /** * Constructor. * * @param MDMysqli $mysqli_noda DB connection. * * @return void */ public function __construct(MDMysqli $mysqli_noda) { $this->_mysqli_noda = $mysqli_noda; } }