* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class LocalFileDatabase extends BaseDatabaseFrontend implements DatabaseFrontendInterface {
+
// Constants for MySQL backward-compatiblity (PLEASE FIX THEM!)
- const DB_CODE_TABLE_MISSING = 0x000;
+ const DB_CODE_TABLE_MISSING = 0x000;
+ const DB_CODE_TABLE_UNWRITEABLE = 0x001;
/**
* Save path for "file database"
$this->setObjectDescription("Class for local file databases");
// Create unique ID
- $this->createUniqueID();
+ $this->generateUniqueId();
// Clean up a little
$this->removeSystemArray();
* Saves a given object to the local file system by serializing and
* transparently compressing it
*
- * @param $object The object we shall save to the local file system
+ * @param $object The object we shall save to the local file system
* @return void
- * @throws NullPointerException If the object instance is null
- * @throws NoObjectException If the parameter $object is not
- * an object
*/
- public final function saveObject ($object) {
- // Some tests on the parameter...
- if (is_null($object)) {
- // Is null, throw exception
- throw new NullPointerException($object, self::EXCEPTION_IS_NULL_POINTER);
- } elseif (!is_object($object)) {
- // Is not an object, throw exception
- throw new NoObjectException($object, self::EXCEPTION_IS_NO_OBJECT);
- } elseif (!method_exists($object, '__toString')) {
- // A highly required method was not found... :-(
- throw new MissingMethodException(array($object, '__toString'), self::EXCEPTION_MISSING_METHOD);
- }
-
+ public final function saveObject (FrameworkInterface $object) {
// Get a string containing the serialized object. We cannot exchange
// $this and $object here because $object does not need to worry
// about it's limitations... ;-)
/**
* Get a serialized string from the given object
*
- * @param $object The object we want to serialize and transparently
- * compress
- * @return $serialized A string containing the serialzed/compressed object
+ * @param $object The object we want to serialize and transparently
+ * compress
+ * @return $serialized A string containing the serialzed/compressed object
* @see ObjectLimits An object holding limition information
* @see SerializationContainer A special container class for e.g.
- * attributes from limited objects
+ * attributes from limited objects
*/
- private function serializeObject ($object) {
+ private function serializeObject (FrameworkInterface $object) {
// If there is no limiter instance we serialize the whole object
// otherwise only in the limiter object (ObjectLimits) specified
// attributes summarized in a special container class
* 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
+ * @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
+ * 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
*/
// Initialize the search loop
$isValid = false;
- while ($dataFile = $dirInstance->readDirectoryExcept(array(".", "..", ".htaccess"))) {
+ while ($dataFile = $dirInstance->readDirectoryExcept(array(".", "..", ".htaccess", ".svn"))) {
// Generate FQFN for testing
$fqfn = sprintf("%s/%s", $pathName, $dataFile);
$this->setLastFile($fqfn);
* @throws UnsupportedCriteriaException If the criteria is unsupported
* @throws SqlException If an "SQL error" occurs
*/
- public function querySelect ($resultType, $tableName, Criteria $criteriaInstance) {
+ public function querySelect ($resultType, $tableName, LocalSearchCriteria $criteriaInstance) {
// The result is null by any errors
$resultData = null;
- // Is this criteria supported?
- if (!$criteriaInstance instanceof LocalCriteria) {
- // Not supported by this database layer
- throw new UnsupportedCriteriaException(array($this, $criteriaInstance), self::EXCEPTION_REQUIRED_INTERFACE_MISSING);
- }
-
// Create full path name
$pathName = $this->getSavePath() . $tableName . '/';
'rows' => array()
);
+ // Initialize limit/skip
+ $limitFound = 0; $skipFound = 0;
+
// Read the directory with some exceptions
- while ($dataFile = $directoryInstance->readDirectoryExcept(array(".", "..", ".htaccess"))) {
- $this->partialStub(sprintf("File %s found.", $dataFile));
+ while (($dataFile = $directoryInstance->readDirectoryExcept(array(".", "..", ".htaccess", ".svn"))) && ($limitFound < $criteriaInstance->getLimit())) {
+ // Open this file for reading
+ $filePointer = FrameworkFileInputPointer::createFrameworkFileInputPointer($pathName . $dataFile);
+
+ // Get the raw data and BASE64-decode it
+ $compressedData = base64_decode($filePointer->readLinesFromFile());
+
+ // Close the file and throw the instance away
+ $filePointer->closeFile();
+ unset($filePointer);
+
+ // Decompress it
+ $serializedData = $this->getCompressorChannel()->getCompressor()->decompressStream($compressedData);
+
+ // Unserialize it
+ $dataArray = unserialize($serializedData);
+
+ // Is this an array?
+ if (is_array($dataArray)) {
+ // Search in the criteria with FMFW (First Matches, First Wins)
+ foreach ($dataArray as $key=>$value) {
+ // Get criteria element
+ $criteria = $criteriaInstance->getCriteriaElemnent($key);
+
+ // Is the criteria met?
+ if ((!is_null($criteria)) && ($criteria == $value)) {
+
+ // Shall we skip this entry?
+ if ($criteriaInstance->getSkip() > 0) {
+ // We shall skip some entries
+ if ($skipFound < $criteriaInstance->getSkip()) {
+ // Skip this entry
+ $skipFound++;
+ break;
+ } // END - if
+ } // END - if
+
+ // Entry found!
+ $resultData['rows'][] = $dataArray;
+ $limitFound++;
+ break;
+ } // END - if
+ } // END - foreach
+ } // END - if
} // END - while
// Close directory and throw the instance away
// Return the gathered result
return $resultData;
}
+
+ /**
+ * "Inserts" a data set instance into a local file database folder
+ *
+ * @param $dataSetInstance A storeable data set
+ * @return void
+ * @throws SqlException If an SQL error occurs
+ */
+ public function queryInsertDataSet (StoreableCriteria $dataSetInstance) {
+ // Create full path name
+ $fqfn = sprintf("%s%s/%s.%s",
+ $this->getSavePath(),
+ $dataSetInstance->getTableName(),
+ md5($dataSetInstance->getUniqueValue()),
+ $this->getFileExtension()
+ );
+
+ // Try to save the request away
+ try {
+ // Get a file pointer instance
+ $filePointer = FrameworkFileOutputPointer::createFrameworkFileOutputPointer($fqfn, 'w');
+
+ // Get the criteria array from the dataset
+ $criteriaArray = $dataSetInstance->getCriteriaArray();
+
+ // Serialize and compress it
+ $compressedData = $this->getCompressorChannel()->getCompressor()->compressStream(serialize($criteriaArray));
+
+ // Write this data BASE64 encoded to the file
+ $filePointer->writeToFile(base64_encode($compressedData));
+
+ // Close the file pointer
+ $filePointer->closeFile();
+
+ // Reset last error message and exception
+ $this->resetLastError();
+ } catch (FrameworkException $e) {
+ // Catch all exceptions and store them in last error
+ $this->lastException = $e;
+ $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);
+ }
+ }
}
// [EOF]