* @version 0.0.0
* @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 Core Developer Team
* @license GNU GPL 3.0 or any newer version
* @link http://www.ship-simu.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
class DatabaseResult extends BaseFrameworkSystem implements SearchableResult, UpdateableResult, SeekableIterator {
// Exception constants
const EXCEPTION_INVALID_DATABASE_RESULT = 0x1c0;
const EXCEPTION_RESULT_UPDATE_FAILED = 0x1c1;
/**
* Current position in array
*/
private $currentPos = -1;
/**
* Current row
*/
private $currentRow = null;
/**
* Result array
*/
private $resultArray = array();
/**
* Array of out-dated entries
*/
private $outDated = array();
/**
* Affected rows
*/
private $affectedRows = 0;
/**
* Found value
*/
private $foundValue = '';
/**
* Protected constructor
*
* @return void
*/
protected function __construct () {
// Call parent constructor
parent::__construct(__CLASS__);
}
/**
* Creates an instance of this result by a provided result array
*
* @param $resultArray The array holding the result from query
* @return $resultInstance An instance of this class
*/
public static final function createDatabaseResult (array $resultArray) {
// Get a new instance
$resultInstance = new DatabaseResult();
// Set the result array
$resultInstance->setResultArray($resultArray);
// Return the instance
return $resultInstance;
}
/**
* Setter for result array
*
* @param $resultArray The array holding the result from query
* @return void
*/
protected final function setResultArray (array $resultArray) {
$this->resultArray = $resultArray;
}
/**
* Updates the current entry by given update criteria
*
* @param $updateInstance An instance of an Updateable criteria
* @return void
*/
private function updateCurrentEntryByCriteria (LocalUpdateCriteria $updateInstance) {
// Get the current entry key
$entryKey = $this->key();
// Now get the update criteria array and update all entries
foreach ($updateInstance->getUpdateCriteria() as $criteriaKey => $criteriaValue) {
// Update data
$this->resultArray['rows'][$entryKey][$criteriaKey] = $criteriaValue;
// Mark it as out-dated
$this->outDated[$criteriaKey] = 1;
} // END - foreach
}
/**
* "Iterator" method next() to advance to the next valid entry. This method
* does also check if result is invalid
*
* @return $nextValid Wether the next entry is valid
*/
public function next () {
// Default is not valid
$nextValid = false;
// Is the result valid?
if ($this->valid()) {
// Next entry found, so count one up and cache it
$this->currentPos++;
$this->currentRow = $this->resultArray['rows'][$this->currentPos];
$nextValid = true;
} // END - if
// Return the result
return $nextValid;
}
/**
* Seeks for to a specified position
*
* @param $index Index to seek for
* @return void
*/
public function seek ($index) {
// Rewind to beginning
$this->rewind();
// Search for the entry
while ($this->currentPos < $index && ($this->valid())) {
// Continue on
$this->next();
} // END - while
}
/**
* Gives back the current position or null if not found
*
* @return $current Current element to give back
*/
public function current () {
// Default is not found
$current = null;
// Does the current enty exist?
if (isset($this->resultArray['rows'][$this->currentPos])) {
// Then get it
$current = $this->resultArray['rows'][$this->currentPos];
} // END - if
// Return the result
return $current;
}
/**
* Checks if next() and rewind will give a valid result
*
* @return $isValid Wether the next/rewind entry is valid
*/
public function valid () {
// By default nothing is valid
$isValid = false;
// Check if
if (($this->ifStatusIsOkay()) && (isset($this->resultArray['rows'][($this->currentPos + 1)])) && (isset($this->resultArray['rows'][0]))) {
// All fine!
$isValid = true;
} // END - if
// Return the result
return $isValid;
}
/**
* Determines wether the status of the query was fine (LocalfileDatabase::RESULT_OKAY)
*
* @return $ifStatusOkay Wether the status of the query was okay
*/
public function ifStatusIsOkay () {
return ((isset($this->resultArray['status'])) && ($this->resultArray['status'] === LocalfileDatabase::RESULT_OKAY));
}
/**
* Gets the current key of iteration
*
* @return $currentPos Key from iterator
*/
public function key () {
return $this->currentPos;
}
/**
* Rewind to the beginning and clear array $currentRow
*
* @return void
*/
public function rewind () {
$this->currentPos = -1;
$this->currentRow = array();
}
/**
* Searches for an entry in data result and returns it
*
* @param $criteriaInstance The criteria to look inside the data set
* @return $result Found result entry
* @todo 0% done
*/
public function searchEntry (LocalSearchCriteria $criteriaInstance) {
die(__METHOD__.": Unfinished!");
}
/**
* Adds an update request to the database result for writing it to the
* database layer
*
* @param $criteriaInstance An instance of a updateable criteria
* @return void
* @throws ResultUpdateException If no result was updated
*/
public function add2UpdateQueue (LocalUpdateCriteria $criteriaInstance) {
// Rewind the pointer
$this->rewind();
// Get search criteria
$searchInstance = $criteriaInstance->getSearchInstance();
// And start looking for the result
$foundEntries = 0;
while (($this->valid()) && ($foundEntries < $searchInstance->getLimit())) {
// Get next entry
$this->next();
$currentEntry = $this->current();
// Is this entry found?
if ($searchInstance->ifEntryMatches($currentEntry)) {
// Update this entry
$this->updateCurrentEntryByCriteria($criteriaInstance);
// Count one up
$foundEntries++;
} // END - if
} // END - while
// If no entry is found/updated throw an exception
if ($foundEntries == 0) {
// Throw an exception here
throw new ResultUpdateException($this, self::EXCEPTION_RESULT_UPDATE_FAILED);
} // END - if
// Set affected rows
$this->setAffectedRows($foundEntries);
// Set update instance
$this->setUpdateInstance($criteriaInstance);
}
/**
* Setter for affected rows
*
* @param $rows Number of affected rows
* @return void
*/
public final function setAffectedRows ($rows) {
$this->affectedRows = $rows;
}
/**
* Getter for affected rows
*
* @return $rows Number of affected rows
*/
public final function getAffectedRows () {
return $this->affectedRows;
}
/**
* Getter for found value of previous found() call
*
* @return $foundValue Found value of previous found() call
*/
public final function getFoundValue () {
return $this->foundValue;
}
/**
* Checks wether we have out-dated entries or not
*
* @return $needsUpdate Wether we have out-dated entries
*/
public function ifDataNeedsFlush () {
$needsUpdate = (count($this->outDated) > 0);
return $needsUpdate;
}
/**
* Adds registration elements to a given dataset instance
*
* @param $criteriaInstance An instance of a storeable criteria
* @return void
*/
public function addElementsToDataSet (StoreableCriteria $criteriaInstance) {
// Walk only through out-dated columns
foreach ($this->outDated as $key => $dummy) {
// Does this key exist?
//* DEBUG: */ echo "outDated: {$key}
\n";
if ($this->find($key)) {
// Then update it
$criteriaInstance->addCriteria($key, $this->getFoundValue());
} // END - if
} // END - foreach
}
/**
* Find a key inside the result array
*
* @param $key The key we shall find
* @return $found Wether the key was found or not
*/
public function find ($key) {
// By default nothing is found
$found = false;
// Rewind the pointer
$this->rewind();
// Walk through all entries
while ($this->valid()) {
// Advance to next entry
$this->next();
// Get the whole array
$currentEntry = $this->current();
// Is the element there?
if (isset($currentEntry[$key])) {
// Okay, found!
$found = true;
// So "cache" it
$this->foundValue = $currentEntry[$key];
// And stop searching
break;
} // END - if
} // END - while
// Return the result
return $found;
}
/**
* Solver for result index value with call-back method
*
* @param $databaseColumn Database column where the index might be found
* @param $wrapperInstance The wrapper instance to ask for array element
* @para $callBack Call-back object for setting the index;
* 0=object instance,1=method name
* @return void
4 * @todo Find a caching way without modifying the result array
*/
public function solveResultIndex ($databaseColumn, BaseDatabaseWrapper $wrapperInstance, array $callBack) {
// By default nothing is found
$indexValue = 0;
// Is the element in result itself found?
if ($this->find($databaseColumn)) {
// Use this value
$indexValue = $this->getFoundValue();
} elseif ($this->find($wrapperInstance->getIndexKey())) {
// Use this value
$indexValue = $this->getFoundValue();
}
// Set the index
call_user_func_array($callBack, array($indexValue));
}
}
// [EOF]
?>