From 2b47a39950d61e96b9182530418e05e18e3adbe2 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 24 Feb 2023 10:23:23 -0500 Subject: [PATCH] Add a new WireNumberTools core class. More will be added later, but this class starts with one method for unique number/ID generation. This is useful for generating unique IDs for things that may not already have them, and ensuring that the ID remains unique for the lifetime of the installation. --- wire/core/WireNumberTools.php | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 wire/core/WireNumberTools.php diff --git a/wire/core/WireNumberTools.php b/wire/core/WireNumberTools.php new file mode 100644 index 00000000..8016b00d --- /dev/null +++ b/wire/core/WireNumberTools.php @@ -0,0 +1,93 @@ + (is_string($options) ? $options : ''), + 'getLast' => false, + 'reset' => false, + ); + + $database = $this->wire()->database; + $config = $this->wire()->config; + $options = is_array($options) ? array_merge($defaults, $options) : $defaults; + $table = 'unique_num'; + + if($options['namespace']) { + $table .= '_' . $this->wire()->sanitizer->fieldName($options['namespace']); + } + + if($options['reset']) { + if(!$options['namespace']) throw new WireException('Namespace required for reset'); + if($database->tableExists($table)) $database->exec("DROP TABLE $table"); + return 0; + } + + if($options['getLast']) try { + $query = $database->query("SELECT MAX(id) FROM $table"); + $uniqueNum = (int) $query->fetchColumn(); + $query->closeCursor(); + return $uniqueNum; + } catch(\Exception $e) { + return 0; + } + + try { + $database->query("INSERT INTO $table SET id=null"); + $uniqueNum = (int) $database->lastInsertId(); + } catch(\Exception $e) { + $uniqueNum = 0; + } + + if(!$uniqueNum && !$database->tableExists($table) && empty($options['recursive'])) { + $idSchema = "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY"; + $database->exec("CREATE TABLE $table ($idSchema) ENGINE=$config->dbEngine"); + return $this->uniqueNumber(array_merge($options, array('recursive' => true))); + } + + if(!$uniqueNum) throw new WireException('Unable to generate unique number'); + + if(($uniqueNum % 10 === 0) && $uniqueNum >= 10) { + // maintain only 10 unique IDs in the DB table at a time + $query = $database->prepare("DELETE FROM $table WHERE id<:id"); + $query->bindValue(':id', $uniqueNum, \PDO::PARAM_INT); + $query->execute(); + } + + return $uniqueNum; + } + +}