X-Git-Url: https://git.mxchange.org/?p=shipsimu.git;a=blobdiff_plain;f=inc%2Fclasses%2Fmain%2Fdatabase%2Fdatabases%2Fclass_LocalFileDatabase.php;h=29e2e5e0f397f3dab498d8dc80ce70565a1598ce;hp=b3ee46ecb7b2b22851e2337439289394b4797417;hb=7def3a8992918dd9fe5f55d14d89c9cad4db0cbd;hpb=4c35e8280767c1e33832097060e39a32b80ffd01 diff --git a/inc/classes/main/database/databases/class_LocalFileDatabase.php b/inc/classes/main/database/databases/class_LocalFileDatabase.php index b3ee46e..29e2e5e 100644 --- a/inc/classes/main/database/databases/class_LocalFileDatabase.php +++ b/inc/classes/main/database/databases/class_LocalFileDatabase.php @@ -6,7 +6,7 @@ * * @author Roland Haeder * @version 0.0.0 - * @copyright Copyright(c) 2007, 2008 Roland Haeder, this is free software + * @copyright Copyright (c) 2007, 2008 Roland Haeder, this is free software * @license GNU GPL 3.0 or any newer version * @link http://www.ship-simu.org * @@ -26,9 +26,9 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontendInterface { // Constants for MySQL backward-compatiblity (PLEASE FIX THEM!) - const DB_CODE_TABLE_MISSING = 0x010; - const DB_CODE_TABLE_UNWRITEABLE = 0x011; - const DB_CODE_DATA_FILE_CORRUPT = 0x012; + const DB_CODE_TABLE_MISSING = 0x100; + const DB_CODE_TABLE_UNWRITEABLE = 0x101; + const DB_CODE_DATA_FILE_CORRUPT = 0x102; /** * Save path for "file database" @@ -65,6 +65,16 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend */ private $lastException = null; + /** + * Table information array + */ + private $tableInfo = array(); + + /** + * Element for index + */ + private $indexKey = "__idx"; + /** * The protected constructor. Do never instance from outside! You need to * set a local file path. The class will then validate it. @@ -75,13 +85,8 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend // Call parent constructor parent::__construct(__CLASS__); - // Set description - $this->setObjectDescription("Class for local file databases"); - - // Create unique ID - $this->generateUniqueId(); - // Clean up a little + $this->removeNumberFormaters(); $this->removeSystemArray(); } @@ -150,105 +155,15 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend return $this->lastException; } - /** - * Analyses if a unique ID has already been used or not by search in the - * local database folder. - * - * @param $uniqueID A unique ID number which shall be checked - * before it will be used - * @param $inConstructor If we got called in a de/con-structor or - * from somewhere else - * @return $isUnused true = The unique ID was not found in the database, - * false = It is already in use by an other object - * @throws NoArrayCreatedException If explode() fails to create an array - * @throws InvalidArrayCountException If the array contains less or - * more than two elements - */ - public function isUniqueIdUsed ($uniqueID, $inConstructor = false) { - // Currently not used... ;-) - $isUsed = false; - - // Split the unique ID up in path and file name - $pathFile = explode("@", $uniqueID); - - // Are there two elements? Index 0 is the path, 1 the file name + global extension - if (!is_array($pathFile)) { - // No array found - if ($inConstructor) { - return false; - } else { - throw new NoArrayCreatedException(array($this, "pathFile"), self::EXCEPTION_ARRAY_EXPECTED); - } - } elseif (count($pathFile) != 2) { - // Invalid ID returned! - if ($inConstructor) { - return false; - } else { - throw new InvalidArrayCountException(array($this, "pathFile", count($pathFile), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT); - } - } - - // Create full path name - $pathName = $this->getSavePath() . $pathFile[0]; - - // Check if the file is there with a file handler - if ($inConstructor) { - // No exceptions in constructors and destructors! - $dirInstance = FrameworkDirectoryPointer::createFrameworkDirectoryPointer($pathName, true); - - // Has an object being created? - if (!is_object($dirInstance)) return false; - } else { - // Outside a constructor - try { - $dirInstance = FrameworkDirectoryPointer::createFrameworkDirectoryPointer($pathName); - } catch (PathIsNoDirectoryException $e) { - // Okay, path not found - return false; - } - } - - // Initialize the search loop - $isValid = false; - while ($dataFile = $dirInstance->readDirectoryExcept(array(".", "..", ".htaccess", ".svn"))) { - // Generate FQFN for testing - $fqfn = sprintf("%s/%s", $pathName, $dataFile); - $this->setLastFile($fqfn); - - // Get instance for file handler - $inputHandler = $this->getFileIoInstance(); - - // Try to read from it. This makes it sure that the file is - // readable and a valid database file - $this->setLastFileContents($inputHandler->loadFileContents($fqfn)); - - // Extract filename (= unique ID) from it - $ID = substr(basename($fqfn), 0, -(strlen($this->getFileExtension()) + 1)); - - // Is this the required unique ID? - if ($ID == $pathFile[1]) { - // Okay, already in use! - $isUsed = true; - } - } - - // Close the directory handler - $dirInstance->closeDirectory(); - - // Now the same for the file... - return $isUsed; - } - /** * Setter for the last read file * - * @param $fqfn The FQFN of the last read file + * @param $fqfn The FQFN of the last read file * @return void */ private final function setLastFile ($fqfn) { - // Cast string - $fqfn = (string) $fqfn; - $this->lastFile = $fqfn; + // Cast string and set it + $this->lastFile = (string) $fqfn; } /** @@ -277,9 +192,8 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend * @param $contents An array with header and data elements * @return void */ - private final function setLastFileContents ($contents) { - // Cast array - $contents = (array) $contents; + private final function setLastFileContents (array $contents) { + // Set array $this->lastContents = $contents; } @@ -301,6 +215,15 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend return $this->fileExtension; } + /** + * Getter for index key + * + * @return $indexKey Index key + */ + public final function getIndexKey () { + return $this->indexKey; + } + /** * Reads a local data file and returns it's contents in an array * @@ -349,6 +272,74 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend $fileInstance->closeFile(); } + /** + * Getter for table information file contents or an empty if the info file was not created + * + * @param $dataSetInstance An instance of a database set class + * @return $infoArray An array with all table informations + */ + private function getContentsFromTableInfoFile (StoreableCriteria $dataSetInstance) { + // Default content is no data + $infoArray = array(); + + // Create FQFN for getting the table information file + $fqfn = $this->getSavePath() . $dataSetInstance->getTableName() . '/info.' . $this->getFileExtension(); + + // Get the file contents + try { + $infoArray = $this->getDataArrayFromFile($fqfn); + } catch (FileNotFoundException $e) { + // Not found, so ignore it here + } + + // ... and return it + return $infoArray; + } + + /** + * Creates the table info file from given dataset instance + * + * @param $dataSetInstance An instance of a database set class + * @return void + */ + private function createTableInfoFile (StoreableCriteria $dataSetInstance) { + // Create FQFN for creating the table information file + $fqfn = $this->getSavePath() . $dataSetInstance->getTableName() . '/info.' . $this->getFileExtension(); + + // Get the data out from dataset in a local array + $this->tableInfo[$dataSetInstance->getTableName()] = array( + 'primary' => $dataSetInstance->getPrimaryKey(), + 'created' => time(), + 'last_updated' => time() + ); + + // Write the data to the file + $this->writeDataArrayToFqfn($fqfn, $this->tableInfo[$dataSetInstance->getTableName()]); + } + + /** + * Updates the primary key information or creates the table info file if not found + * + * @param $dataSetInstance An instance of a database set class + * @return void + */ + private function updatePrimaryKey (StoreableCriteria $dataSetInstance) { + // Get the information array from lower method + $infoArray = $this->getContentsFromTableInfoFile($dataSetInstance); + + // Is the primary key there? + if (!isset($this->tableInfo['primary'])) { + // Then create the info file + $this->createTableInfoFile($dataSetInstance); + } elseif (($this->getConfigInstance()->readConfig('db_update_primary_forced') === "Y") && ($dataSetInstance->getPrimaryKey() != $this->tableInfo['primary'])) { + // Set the array element + $this->tableInfo[$dataSetInstance->getTableName()]['primary'] = $dataSetInstance->getPrimaryKey(); + + // Update the entry + $this->updateTableInfoFile($dataSetInstance); + } + } + /** * Makes sure that the database connection is alive * @@ -389,17 +380,25 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend ); // Initialize limit/skip - $limitFound = 0; $skipFound = 0; + $limitFound = 0; + $skipFound = 0; + $idx = 1; // Read the directory with some exceptions - while (($dataFile = $directoryInstance->readDirectoryExcept(array(".", "..", ".htaccess", ".svn"))) && ($limitFound < $criteriaInstance->getLimit())) { + while (($dataFile = $directoryInstance->readDirectoryExcept(array(".", "..", ".htaccess", ".svn", "info." . $this->getFileExtension()))) && ($limitFound < $criteriaInstance->getLimit())) { + // Does the extension match? + if (substr($dataFile, -(strlen($this->getFileExtension()))) !== $this->getFileExtension()) { + // Skip this file! + continue; + } // END - if + // Read the file $dataArray = $this->getDataArrayFromFile($pathName . $dataFile); // Is this an array? if (is_array($dataArray)) { // Search in the criteria with FMFW (First Matches, First Wins) - foreach ($dataArray as $key=>$value) { + foreach ($dataArray as $key => $value) { // Get criteria element $criteria = $criteriaInstance->getCriteriaElemnent($key); @@ -416,16 +415,24 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend } // END - if } // END - if + // Set id number + $dataArray[$this->getIndexKey()] = $idx; + // Entry found! $resultData['rows'][] = $dataArray; + + // Count found entries up $limitFound++; break; } // END - if } // END - foreach } else { // Throw an exception here - throw new SqlException(sprintf("File '%s' contains invalid data.", $dataFile), self::DB_CODE_DATA_FILE_CORRUPT); + throw new SqlException(array($this, sprintf("File '%s' contains invalid data.", $dataFile), self::DB_CODE_DATA_FILE_CORRUPT), self::EXCEPTION_SQL_QUERY); } + + // Count entry up + $idx++; } // END - while // Close directory and throw the instance away @@ -472,6 +479,9 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend // Write the data away $this->writeDataArrayToFqfn($fqfn, $dataSetInstance->getCriteriaArray()); + // Update the primary key + $this->updatePrimaryKey($dataSetInstance); + // Reset last error message and exception $this->resetLastError(); } catch (FrameworkException $e) { @@ -501,7 +511,8 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend $directoryInstance = FrameworkDirectoryPointer::createFrameworkDirectoryPointer($pathName); // Initialize limit/skip - $limitFound = 0; $skipFound = 0; + $limitFound = 0; + $skipFound = 0; // Get the criteria array from the dataset $criteriaArray = $dataSetInstance->getCriteriaArray(); @@ -510,14 +521,20 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend $searchInstance = $dataSetInstance->getSearchInstance(); // Read the directory with some exceptions - while (($dataFile = $directoryInstance->readDirectoryExcept(array(".", "..", ".htaccess", ".svn"))) && ($limitFound < $searchInstance->getLimit())) { + while (($dataFile = $directoryInstance->readDirectoryExcept(array(".", "..", ".htaccess", ".svn", "info." . $this->getFileExtension()))) && ($limitFound < $searchInstance->getLimit())) { + // Does the extension match? + if (substr($dataFile, -(strlen($this->getFileExtension()))) !== $this->getFileExtension()) { + // Skip this file! + continue; + } + // Open this file for reading $dataArray = $this->getDataArrayFromFile($pathName . $dataFile); // Is this an array? if (is_array($dataArray)) { // Search in the criteria with FMFW (First Matches, First Wins) - foreach ($dataArray as $key=>$value) { + foreach ($dataArray as $key => $value) { // Get criteria element $criteria = $searchInstance->getCriteriaElemnent($key); @@ -535,7 +552,7 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend } // END - if // Entry found, so update it - foreach ($criteriaArray as $criteriaKey=>$criteriaValue) { + foreach ($criteriaArray as $criteriaKey => $criteriaValue) { $dataArray[$criteriaKey] = $criteriaValue; } // END - foreach @@ -553,6 +570,9 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend // Close the file pointer $directoryInstance->closeDirectory(); + // Update the primary key + $this->updatePrimaryKey($dataSetInstance); + // Reset last error message and exception $this->resetLastError(); } catch (FrameworkException $e) { @@ -561,9 +581,30 @@ class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontend $this->lastError = $e->getMessage(); // Throw an SQL exception - throw new SqlException (array($this, sprintf("Cannot write data to table '%s'", $tableName), self::DB_CODE_TABLE_UNWRITEABLE), self::EXCEPTION_SQL_QUERY); + throw new SqlException (array($this, sprintf("Cannot write data to table '%s'", $dataSetInstance->getTableName()), self::DB_CODE_TABLE_UNWRITEABLE), self::EXCEPTION_SQL_QUERY); } } + + /** + * Getter for primary key of specified table or if not found null will be + * returned. This must be database-specific. + * + * @param $tableName Name of the table we need the primary key from + * @return $primaryKey Primary key column of the given table + */ + public function getPrimaryKeyOfTable ($tableName) { + // Default key is null + $primaryKey = null; + + // Does the table information exist? + if (isset($this->tableInfo[$tableName])) { + // Then return the primary key + $primaryKey = $this->tableInfo[$tableName]['primary']; + } // END - if + + // Return the column + return $primaryKey; + } } // [EOF]