add new genericdb optimized for PHP8+
This commit is contained in:
parent
680b5bad71
commit
210091ad9b
10 changed files with 2308 additions and 1720 deletions
29
conlite/classes/GenericDb/Driver/GenericDbDriver.php
Normal file
29
conlite/classes/GenericDb/Driver/GenericDbDriver.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace ConLite\GenericDb\Driver;
|
||||
|
||||
class GenericDbDriver
|
||||
{
|
||||
public $_sEncoding;
|
||||
public $_oItemClassInstance;
|
||||
|
||||
public function setEncoding($sEncoding)
|
||||
{
|
||||
$this->_sEncoding = $sEncoding;
|
||||
}
|
||||
|
||||
public function setItemClassInstance($oInstance)
|
||||
{
|
||||
$this->_oItemClassInstance = $oInstance;
|
||||
}
|
||||
|
||||
public function buildJoinQuery($destinationTable, $destinationClass, $destinationPrimaryKey, $sourceClass, $primaryKey)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function buildOperator($sField, $sOperator, $sRestriction)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
166
conlite/classes/GenericDb/Driver/MySql/GenericDbDriverMySql.php
Normal file
166
conlite/classes/GenericDb/Driver/MySql/GenericDbDriverMySql.php
Normal file
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
|
||||
namespace ConLite\GenericDb\Driver\MySql;
|
||||
|
||||
use ConLite\GenericDb\Driver\GenericDbDriver;
|
||||
|
||||
class GenericDbDriverMySql extends GenericDbDriver
|
||||
{
|
||||
|
||||
|
||||
public $_oItemClassInstance;
|
||||
public $_sEncoding;
|
||||
function buildJoinQuery($destinationTable, $destinationClass, $destinationPrimaryKey, $sourceClass, $primaryKey)
|
||||
{
|
||||
// Build a regular LEFT JOIN
|
||||
$field = "$destinationClass.$destinationPrimaryKey";
|
||||
$tables = "";
|
||||
$join = "LEFT JOIN $destinationTable AS $destinationClass ON " .
|
||||
Contenido_Security::toString($sourceClass . "." . $primaryKey) . " = " .
|
||||
Contenido_Security::toString($destinationClass . "." . $primaryKey);
|
||||
$where = "";
|
||||
|
||||
return ["field" => $field, "table" => $tables, "join" => $join, "where" => $where];
|
||||
}
|
||||
|
||||
function buildOperator($sField, $sOperator, $sRestriction)
|
||||
{
|
||||
$sOperator = strtolower($sOperator);
|
||||
|
||||
$sWhereStatement = "";
|
||||
|
||||
switch ($sOperator) {
|
||||
case "matchbool":
|
||||
$sqlStatement = "MATCH (%s) AGAINST ('%s' IN BOOLEAN MODE)";
|
||||
$sWhereStatement = sprintf($sqlStatement, $sField, $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "match":
|
||||
$sqlStatement = "MATCH (%s) AGAINST ('%s')";
|
||||
$sWhereStatement = sprintf($sqlStatement, $sField, $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "like":
|
||||
$sqlStatement = "%s LIKE '%%%s%%'";
|
||||
$sWhereStatement = sprintf($sqlStatement, Contenido_Security::toString($sField), $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "likeleft":
|
||||
$sqlStatement = "%s LIKE '%s%%'";
|
||||
$sWhereStatement = sprintf($sqlStatement, Contenido_Security::toString($sField), $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "likeright":
|
||||
$sqlStatement = "%s LIKE '%%%s'";
|
||||
$sWhereStatement = sprintf($sqlStatement, Contenido_Security::toString($sField), $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "notlike":
|
||||
$sqlStatement = "%s NOT LIKE '%%%s%%'";
|
||||
$sWhereStatement = sprintf($sqlStatement, Contenido_Security::toString($sField), $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "notlikeleft":
|
||||
$sqlStatement = "%s NOT LIKE '%s%%'";
|
||||
$sWhereStatement = sprintf($sqlStatement, Contenido_Security::toString($sField), $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "notlikeright":
|
||||
$sqlStatement = "%s NOT LIKE '%%%s'";
|
||||
$sWhereStatement = sprintf($sqlStatement, Contenido_Security::toString($sField), $this->_oItemClassInstance->_inFilter($sRestriction));
|
||||
break;
|
||||
case "diacritics":
|
||||
if (!is_object($GLOBALS["_cCharTable"])) {
|
||||
$GLOBALS["_cCharTable"] = new cCharacterConverter;
|
||||
}
|
||||
|
||||
$aliasSearch = [];
|
||||
|
||||
$metaCharacters = ["*", "[", "]", "^", '$', "\\", "*", "'", '"', '+'];
|
||||
|
||||
for ($i = 0; $i < strlen($sRestriction); $i++) {
|
||||
$char = substr($sRestriction, $i, 1);
|
||||
|
||||
$aliases = [];
|
||||
|
||||
$aliases = array_merge($aliases, $GLOBALS["_cCharTable"]->fetchDiacriticCharactersForNormalizedChar($this->_sEncoding, $char));
|
||||
$normalizedChars = $GLOBALS["_cCharTable"]->fetchNormalizedCharsForDiacriticCharacter($this->_sEncoding, $char);
|
||||
|
||||
foreach ($normalizedChars as $normalizedChar) {
|
||||
$aliases = array_merge($aliases, $GLOBALS["_cCharTable"]->fetchDiacriticCharactersForNormalizedChar($this->_sEncoding, $normalizedChar));
|
||||
}
|
||||
|
||||
$aliases = array_merge($aliases, $normalizedChars);
|
||||
|
||||
if ($aliases !== []) {
|
||||
$aliases[] = $char;
|
||||
$allAliases = [];
|
||||
|
||||
foreach ($aliases as $alias) {
|
||||
$alias1 = $this->_oItemClassInstance->_inFilter($alias);
|
||||
$allAliases[] = $alias1;
|
||||
$allAliases[] = $alias;
|
||||
}
|
||||
|
||||
$allAliases = array_unique($allAliases);
|
||||
$aliasSearch[] = "(" . implode("|", $allAliases) . ")";
|
||||
} else {
|
||||
$addChars = [];
|
||||
|
||||
|
||||
if (in_array($char, $metaCharacters)) {
|
||||
$addChars[] = "\\\\" . $char;
|
||||
} else {
|
||||
$addChars[] = $char;
|
||||
|
||||
$vChar = $this->_oItemClassInstance->_inFilter($char);
|
||||
|
||||
if ($char != $vChar) {
|
||||
$addChars[] = in_array($vChar, $metaCharacters) ? "\\\\" . $vChar : $vChar;
|
||||
}
|
||||
}
|
||||
|
||||
$aliasSearch[] = "(" . implode("|", $addChars) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
$restriction = "'" . implode("", $aliasSearch) . "'";
|
||||
$sWhereStatement = implode(" ", [$sField, "REGEXP", $restriction]);
|
||||
|
||||
break;
|
||||
case "fulltext":
|
||||
|
||||
break;
|
||||
case "in":
|
||||
if (is_array($sRestriction)) {
|
||||
$items = [];
|
||||
|
||||
foreach ($sRestriction as $sRestrictionItem) {
|
||||
$items[] = "'" . $this->_oItemClassInstance->_inFilter($sRestrictionItem) . "'";
|
||||
}
|
||||
|
||||
$sRestriction = implode(", ", $items);
|
||||
} else {
|
||||
$sRestriction = "'" . $sRestriction . "'";
|
||||
}
|
||||
|
||||
$sWhereStatement = implode(" ", [$sField, "IN (", $sRestriction, ")"]);
|
||||
break;
|
||||
case "notin":
|
||||
if (is_array($sRestriction)) {
|
||||
$items = [];
|
||||
|
||||
foreach ($sRestriction as $Restriction) {
|
||||
$items[] = "'" . $this->_oItemClassInstance->_inFilter($Restriction) . "'";
|
||||
}
|
||||
|
||||
$sRestriction = implode(", ", $items);
|
||||
} else {
|
||||
$sRestriction = "'" . $sRestriction . "'";
|
||||
}
|
||||
|
||||
$sWhereStatement = implode(" ", [$sField, "NOT IN (", $sRestriction, ")"]);
|
||||
break;
|
||||
default :
|
||||
$sRestriction = "'" . $this->_oItemClassInstance->_inFilter($sRestriction) . "'";
|
||||
|
||||
$sWhereStatement = implode(" ", [$sField, $sOperator, $sRestriction]);
|
||||
}
|
||||
|
||||
return $sWhereStatement;
|
||||
}
|
||||
|
||||
}
|
515
conlite/classes/GenericDb/Item.php
Normal file
515
conlite/classes/GenericDb/Item.php
Normal file
|
@ -0,0 +1,515 @@
|
|||
<?php
|
||||
|
||||
namespace ConLite\GenericDb;
|
||||
|
||||
use stdClass;
|
||||
abstract class Item extends ItemBaseAbstract
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $_lastSQL;
|
||||
/**
|
||||
* Storage of the source table to use for the user informations
|
||||
* @var array
|
||||
*/
|
||||
public $values;
|
||||
|
||||
/**
|
||||
* Storage of the fields which were modified, where the keys are the
|
||||
* fieldnames and the values just simple booleans.
|
||||
* @var array
|
||||
*/
|
||||
protected $modifiedValues;
|
||||
|
||||
/**
|
||||
* Stores the old primary key, just in case somebody wants to change it
|
||||
* @var string
|
||||
*/
|
||||
protected $oldPrimaryKey;
|
||||
|
||||
/**
|
||||
* List of funcion names of the filters used when data is stored to the db.
|
||||
* @var array
|
||||
*/
|
||||
protected $_arrInFilters = ['urlencode', 'clHtmlSpecialChars', 'addslashes'];
|
||||
|
||||
/**
|
||||
* List of funcion names of the filtersused when data is retrieved from the db
|
||||
* @var array
|
||||
*/
|
||||
protected $_arrOutFilters = ['stripslashes', 'htmldecode', 'urldecode'];
|
||||
|
||||
/**
|
||||
* Class name of meta object
|
||||
* @var string
|
||||
*/
|
||||
protected $_metaObject;
|
||||
|
||||
/**
|
||||
* Constructor function
|
||||
*
|
||||
* @param string $sTable The table to use as information source
|
||||
* @param string $sPrimaryKey The primary key to use
|
||||
* @param int $iLifetime
|
||||
*/
|
||||
public function __construct($sTable = '', $sPrimaryKey = '', $iLifetime = 10)
|
||||
{
|
||||
parent::__construct($sTable, $sPrimaryKey, get_parent_class($this), $iLifetime);
|
||||
}
|
||||
|
||||
function __destruct()
|
||||
{
|
||||
//print_r(self::$_oCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an item by colum/field from the database.
|
||||
*
|
||||
* @param string $sField Specifies the field
|
||||
* @param mixed $mValue Specifies the value
|
||||
* @param bool $bSafe Use inFilter or not
|
||||
* @return bool True if the load was successful
|
||||
*/
|
||||
public function loadBy($sField, mixed $mValue, $bSafe = true): bool
|
||||
{
|
||||
if ($bSafe) {
|
||||
$mValue = $this->_inFilter($mValue);
|
||||
}
|
||||
if ($sField === $this->primaryKey) {
|
||||
$aRecordSet = self::$_oCache->getItem($this->table . "_" . $mValue);
|
||||
} else {
|
||||
$aRecordSet = self::$_oCache->getItemByProperty($this->table . "_" . $sField, $mValue);
|
||||
}
|
||||
|
||||
if ($aRecordSet) {
|
||||
// entry in cache found, load entry from cache
|
||||
$this->loadByRecordSet($aRecordSet);
|
||||
return true;
|
||||
}
|
||||
|
||||
// SQL-Statement to select by field
|
||||
$sql = sprintf("SELECT * FROM `%s` WHERE %s = '%s'", $this->table, $sField, $mValue);
|
||||
//$sql = $this->db->prepare($sql, $this->table, $sField, $mValue);
|
||||
// Query the database
|
||||
$this->db->query($sql);
|
||||
|
||||
$this->_lastSQL = $sql;
|
||||
|
||||
if ($this->db->num_rows() > 1) {
|
||||
$sMsg = "Tried to load a single line with field $sField and value $mValue from "
|
||||
. $this->table . " but found more than one row";
|
||||
cWarning(__FILE__, __LINE__, $sMsg);
|
||||
}
|
||||
|
||||
// Advance to the next record, return false if nothing found
|
||||
if (!$this->db->next_record()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->loadByRecordSet($this->db->toArray());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an item by passed where clause from the database.
|
||||
* This function is expensive, since it executes allways a query to the database
|
||||
* to retrieve the primary key, even if the record set is aleady cached.
|
||||
* NOTE: Passed value has to be escaped before. This will not be done by this function.
|
||||
*
|
||||
* @param string $sWhere The where clause like 'idart = 123 AND idlang = 1'
|
||||
* @return bool True if the load was successful
|
||||
*/
|
||||
protected function _loadByWhereClause($sWhere)
|
||||
{
|
||||
// SQL-Statement to select by whee clause
|
||||
$sql = sprintf("SELECT %s AS pk FROM `%s` WHERE ", $this->primaryKey, $this->table) . $sWhere;
|
||||
//$sql = $this->db->prepare($sql, $this->primaryKey, $this->table);
|
||||
// Query the database
|
||||
$this->db->query($sql);
|
||||
|
||||
$this->_lastSQL = $sql;
|
||||
|
||||
if ($this->db->num_rows() > 1) {
|
||||
$sMsg = "Tried to load a single line with where clause '" . $sWhere . "' from "
|
||||
. $this->table . " but found more than one row";
|
||||
cWarning(__FILE__, __LINE__, $sMsg);
|
||||
}
|
||||
|
||||
// Advance to the next record, return false if nothing found
|
||||
if (!$this->db->next_record()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $this->db->f('pk');
|
||||
return $this->loadByPrimaryKey($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an item by ID from the database.
|
||||
*
|
||||
* @param string $mValue Specifies the primary key value
|
||||
* @return bool True if the load was successful
|
||||
*/
|
||||
public function loadByPrimaryKey($mValue)
|
||||
{
|
||||
$bSuccess = $this->loadBy($this->primaryKey, $mValue);
|
||||
|
||||
if (($bSuccess == true) && method_exists($this, '_onLoad')) {
|
||||
$this->_onLoad();
|
||||
}
|
||||
return $bSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an item by it's recordset.
|
||||
*
|
||||
* @param array $aRecordSet The recordset of the item
|
||||
*/
|
||||
public function loadByRecordSet(array $aRecordSet)
|
||||
{
|
||||
$this->values = $aRecordSet;
|
||||
$this->oldPrimaryKey = $this->values[$this->primaryKey];
|
||||
$this->virgin = false;
|
||||
self::$_oCache->addItem($this->table . "_" . $this->oldPrimaryKey, $this->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a the item is already loaded.
|
||||
* @return boolean
|
||||
*/
|
||||
public function isLoaded()
|
||||
{
|
||||
return !$this->virgin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function which is called whenever an item is loaded.
|
||||
* Inherited classes should override this function if desired.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _onLoad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a specific field.
|
||||
*
|
||||
* @param string $sField Specifies the field to retrieve
|
||||
* @return mixed Value of the field
|
||||
*/
|
||||
public function getField($sField)
|
||||
{
|
||||
if ($this->virgin == true) {
|
||||
$this->lasterror = 'No item loaded';
|
||||
return false;
|
||||
}
|
||||
return $this->_outFilter($this->values[$sField]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for getField (less to type).
|
||||
*
|
||||
* @param string $sField Specifies the field to retrieve
|
||||
* @return mixed Value of the field
|
||||
*/
|
||||
public function get($sField)
|
||||
{
|
||||
return $this->getField($sField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a specific field.
|
||||
*
|
||||
* @param string $sField Field name
|
||||
* @param string $mValue Value to set
|
||||
* @param bool $bSafe Flag to run defined inFilter on passed value
|
||||
*/
|
||||
public function setField($sField, $mValue, $bSafe = true): bool
|
||||
{
|
||||
if ($this->virgin == true) {
|
||||
$this->lasterror = 'No item loaded';
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->modifiedValues[$sField] = true;
|
||||
|
||||
if ($sField == $this->primaryKey) {
|
||||
$this->oldPrimaryKey = $this->values[$sField];
|
||||
}
|
||||
|
||||
$this->values[$sField] = $bSafe == true ? $this->_inFilter($mValue) : $mValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to setField.
|
||||
*
|
||||
* @param string $sField Field name
|
||||
* @param string $mValue Value to set
|
||||
* @param bool $bSafe Flag to run defined inFilter on passed value
|
||||
*/
|
||||
public function set($sField, $mValue, $bSafe = true)
|
||||
{
|
||||
return $this->setField($sField, $mValue, $bSafe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the loaded and modified item to the database.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
if (!$this->isLoaded()) {
|
||||
$this->lasterror = 'No item loaded';
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = 'UPDATE `' . $this->table . '` SET ';
|
||||
$first = true;
|
||||
|
||||
if (!is_array($this->modifiedValues)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (array_keys($this->modifiedValues) as $key) {
|
||||
if ($first == true) {
|
||||
$sql .= "`$key` = '" . $this->values[$key] . "'";
|
||||
$first = false;
|
||||
} else {
|
||||
$sql .= ", `$key` = '" . $this->values[$key] . "'";
|
||||
}
|
||||
}
|
||||
|
||||
$sql .= " WHERE " . $this->primaryKey . " = '" . $this->oldPrimaryKey . "'";
|
||||
|
||||
$this->db->query($sql);
|
||||
|
||||
$this->_lastSQL = $sql;
|
||||
|
||||
if ($this->db->affected_rows() > 0) {
|
||||
self::$_oCache->addItem($this->table . "_" . $this->oldPrimaryKey, $this->values);
|
||||
}
|
||||
|
||||
return $this->db->affected_rows() >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current item data as an assoziative array.
|
||||
*/
|
||||
public function toArray(): array|false
|
||||
{
|
||||
if ($this->virgin == true) {
|
||||
$this->lasterror = 'No item loaded';
|
||||
return false;
|
||||
}
|
||||
|
||||
$aReturn = [];
|
||||
foreach (array_keys($this->values) as $field) {
|
||||
$aReturn[$field] = $this->getField($field);
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current item data as an object.
|
||||
*/
|
||||
public function toObject(): stdClass|false
|
||||
{
|
||||
$return = $this->toArray();
|
||||
return (false !== $return) ? (object)$return : $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom property.
|
||||
*
|
||||
* @param string $sType Specifies the type
|
||||
* @param string $sName Specifies the name
|
||||
* @param mixed $mValue Specifies the value
|
||||
* @return bool
|
||||
*/
|
||||
public function setProperty($sType, $sName, mixed $mValue)
|
||||
{
|
||||
// If this object wasn't loaded before, return false
|
||||
if ($this->virgin == true) {
|
||||
$this->lasterror = 'No item loaded';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the value
|
||||
$oProperties = $this->_getPropertiesCollectionInstance();
|
||||
return $oProperties->setValue(
|
||||
$this->primaryKey, $this->get($this->primaryKey), $sType, $sName, $mValue
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a custom property.
|
||||
*
|
||||
* @param string $sType Specifies the type
|
||||
* @param string $sName Specifies the name
|
||||
* @return mixed Value of the given property or false
|
||||
*/
|
||||
public function getProperty($sType, $sName)
|
||||
{
|
||||
// If this object wasn't loaded before, return false
|
||||
if ($this->virgin == true) {
|
||||
$this->lasterror = 'No item loaded';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return the value
|
||||
$oProperties = $this->_getPropertiesCollectionInstance();
|
||||
return $oProperties->getValue(
|
||||
$this->primaryKey, $this->get($this->primaryKey), $sType, $sName
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a custom property.
|
||||
*
|
||||
* @param string $sType Specifies the type
|
||||
* @param string $sName Specifies the name
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteProperty($sType, $sName)
|
||||
{
|
||||
// If this object wasn't loaded before, return false
|
||||
if ($this->virgin == true) {
|
||||
$this->lasterror = 'No item loaded';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete the value
|
||||
$oProperties = $this->_getPropertiesCollectionInstance();
|
||||
return $oProperties->deleteValue(
|
||||
$this->primaryKey, $this->get($this->primaryKey), $sType, $sName
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a custom property by its id.
|
||||
*
|
||||
* @param int $idprop Id of property
|
||||
* @return bool
|
||||
*/
|
||||
public function deletePropertyById($idprop)
|
||||
{
|
||||
$oProperties = $this->_getPropertiesCollectionInstance();
|
||||
return $oProperties->delete($idprop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the current item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// Method doesn't work, remove in future versions
|
||||
// function delete()
|
||||
// {
|
||||
// $this->_collectionInstance->delete($item->get($this->primaryKey));
|
||||
//}
|
||||
|
||||
/**
|
||||
* Define the filter functions used when data is being stored or retrieved
|
||||
* from the database.
|
||||
*
|
||||
* Examples:
|
||||
* <pre>
|
||||
* $obj->setFilters(array('addslashes'), array('stripslashes'));
|
||||
* $obj->setFilters(array('htmlencode', 'addslashes'), array('stripslashes', 'htmlencode'));
|
||||
* </pre>
|
||||
*
|
||||
* @param array $aInFilters Array with function names
|
||||
* @param array $aOutFilters Array with function names
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setFilters($aInFilters = [], $aOutFilters = [])
|
||||
{
|
||||
$this->_arrInFilters = $aInFilters;
|
||||
$this->_arrOutFilters = $aOutFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the passed data using the functions defines in the _arrInFilters array.
|
||||
*
|
||||
* @param mixed $mData Data to filter
|
||||
* @return mixed Filtered data
|
||||
* @see setFilters
|
||||
*
|
||||
* @todo This method is used from public scope, but it should be protected
|
||||
*
|
||||
*/
|
||||
public function _inFilter(mixed $mData)
|
||||
{
|
||||
if (is_numeric($mData) || is_array($mData)) {
|
||||
return $mData;
|
||||
}
|
||||
|
||||
if (is_null($mData)) {
|
||||
$mData = '';
|
||||
}
|
||||
|
||||
foreach ($this->_arrInFilters as $_arrInFilter) {
|
||||
if (function_exists($_arrInFilter)) {
|
||||
$mData = $_arrInFilter($mData);
|
||||
}
|
||||
}
|
||||
return $mData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the passed data using the functions defines in the _arrOutFilters array.
|
||||
*
|
||||
* @param mixed $mData Data to filter
|
||||
* @return mixed Filtered data
|
||||
* @see setFilters
|
||||
*
|
||||
*/
|
||||
protected function _outFilter(mixed $mData)
|
||||
{
|
||||
if (is_numeric($mData))
|
||||
return $mData;
|
||||
|
||||
foreach ($this->_arrOutFilters as $_arrOutFilter) {
|
||||
if (function_exists($_arrOutFilter)) {
|
||||
$mData = $_arrOutFilter($mData);
|
||||
}
|
||||
}
|
||||
return $mData;
|
||||
}
|
||||
|
||||
protected function _setMetaObject($sObjectName)
|
||||
{
|
||||
$this->_metaObject = $sObjectName;
|
||||
}
|
||||
|
||||
public function getMetaObject()
|
||||
{
|
||||
global $_metaObjectCache;
|
||||
|
||||
if (!is_array($_metaObjectCache)) {
|
||||
$_metaObjectCache = [];
|
||||
}
|
||||
|
||||
$sClassName = $this->_metaObject;
|
||||
$qclassname = strtolower($sClassName);
|
||||
|
||||
if (array_key_exists($qclassname, $_metaObjectCache) && is_object($_metaObjectCache[$qclassname])) {
|
||||
if (strtolower($_metaObjectCache[$qclassname]::class) === $qclassname) {
|
||||
$_metaObjectCache[$qclassname]->setPayloadObject($this);
|
||||
return $_metaObjectCache[$qclassname];
|
||||
}
|
||||
}
|
||||
|
||||
if (class_exists($sClassName)) {
|
||||
$_metaObjectCache[$qclassname] = new $sClassName($this);
|
||||
return $_metaObjectCache[$qclassname];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
166
conlite/classes/GenericDb/ItemBaseAbstract.php
Normal file
166
conlite/classes/GenericDb/ItemBaseAbstract.php
Normal file
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
|
||||
namespace ConLite\GenericDb;
|
||||
|
||||
// security check
|
||||
defined('CON_FRAMEWORK') or die('Illegal call');
|
||||
|
||||
use DB_ConLite;
|
||||
use PropertyCollection;
|
||||
|
||||
abstract class ItemBaseAbstract
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Database instance, contains the database object
|
||||
* @var DB_ConLite
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Second DB instance, is required for some additional queries without
|
||||
* losing an current existing query result.
|
||||
* @var DB_ConLite
|
||||
*/
|
||||
protected $secondDb;
|
||||
|
||||
/**
|
||||
* Property collection instance
|
||||
* @var PropertyCollection
|
||||
*/
|
||||
protected $properties;
|
||||
|
||||
/**
|
||||
* Item cache instance
|
||||
* @var ItemCache
|
||||
*/
|
||||
protected static ItemCache $_oCache;
|
||||
|
||||
/**
|
||||
* GenericDB settings, see $cfg['sql']
|
||||
* @var array
|
||||
*/
|
||||
protected $_settings;
|
||||
|
||||
/**
|
||||
* Storage of the source table to use for the information
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* Storage of the primary key
|
||||
* @var string
|
||||
* @todo remove access from public
|
||||
*/
|
||||
public $primaryKey;
|
||||
|
||||
/**
|
||||
* Checks for the virginity of created objects. If true, the object
|
||||
* is virgin and no operations on it except load-Functions are allowed.
|
||||
* @todo remove access from public
|
||||
* @var bool
|
||||
*/
|
||||
public $virgin;
|
||||
|
||||
/**
|
||||
* Lifetime of results/created objects?
|
||||
* FIXME Not used at the moment!
|
||||
* @var int
|
||||
*/
|
||||
protected $lifetime;
|
||||
|
||||
/**
|
||||
* Storage of the last occured error
|
||||
* @var string
|
||||
*/
|
||||
protected $lasterror = '';
|
||||
|
||||
/**
|
||||
* Cache the result items
|
||||
* FIXME seems to not used, remove it!
|
||||
* @var array
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* Classname of current instance
|
||||
* @var string
|
||||
*/
|
||||
protected $_className;
|
||||
|
||||
protected $_bDebug;
|
||||
|
||||
/**
|
||||
* Sets some common properties
|
||||
*
|
||||
* @param string $sTable Name of table
|
||||
* @param string $sPrimaryKey Primary key of table
|
||||
* @param string $sClassName Name of parent class
|
||||
* @param int $iLifetime Lifetime of the object in seconds (NOT USED!)
|
||||
* @throws ItemException
|
||||
*/
|
||||
protected function __construct($sTable, $sPrimaryKey, $sClassName, $iLifetime = 10) {
|
||||
global $cfg;
|
||||
|
||||
$this->db = new DB_ConLite();
|
||||
|
||||
if ($sTable == '') {
|
||||
$sMsg = "$sClassName: No table specified. Inherited classes *need* to set a table";
|
||||
throw new ItemException($sMsg);
|
||||
} elseif ($sPrimaryKey == '') {
|
||||
$sMsg = "No primary key specified. Inherited classes *need* to set a primary key";
|
||||
throw new ItemException($sMsg);
|
||||
}
|
||||
|
||||
$this->_settings = $cfg['sql'];
|
||||
|
||||
// instanciate caching
|
||||
$aCacheOpt = (isset($this->_settings['cache'])) ? $this->_settings['cache'] : array();
|
||||
self::$_oCache = ItemCache::getInstance($sTable, $aCacheOpt);
|
||||
|
||||
$this->table = $sTable;
|
||||
$this->primaryKey = $sPrimaryKey;
|
||||
$this->virgin = true;
|
||||
$this->lifetime = $iLifetime;
|
||||
$this->_className = $sClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape string for using in SQL-Statement.
|
||||
*
|
||||
* @param string $sString The string to escape
|
||||
* @return string Escaped string
|
||||
*/
|
||||
public function escape($sString) {
|
||||
return $this->db->escape($sString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the second database instance, usable to run additional statements
|
||||
* without losing current query results.
|
||||
*
|
||||
* @return DB_ConLite
|
||||
*/
|
||||
protected function _getSecondDBInstance() {
|
||||
if (!isset($this->secondDb) || !($this->secondDb instanceof DB_ConLite)) {
|
||||
$this->secondDb = new DB_ConLite();
|
||||
}
|
||||
return $this->secondDb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns properties instance, instantiates it if not done before.
|
||||
*
|
||||
* @return PropertyCollection
|
||||
*/
|
||||
protected function _getPropertiesCollectionInstance() {
|
||||
// Runtime on-demand allocation of the properties object
|
||||
if (!isset($this->properties) || !($this->properties instanceof PropertyCollection)) {
|
||||
$this->properties = new PropertyCollection();
|
||||
}
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
}
|
187
conlite/classes/GenericDb/ItemCache.php
Normal file
187
conlite/classes/GenericDb/ItemCache.php
Normal file
|
@ -0,0 +1,187 @@
|
|||
<?php
|
||||
|
||||
namespace ConLite\GenericDb;
|
||||
|
||||
// security check
|
||||
defined('CON_FRAMEWORK') or die('Illegal call');
|
||||
|
||||
class ItemCache
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* List of self instances (Contenido_ItemCache)
|
||||
* @var array
|
||||
*/
|
||||
protected static $_oInstances = [];
|
||||
|
||||
/**
|
||||
* Assoziative cache array
|
||||
* @var array
|
||||
*/
|
||||
protected $_aItemsCache = [];
|
||||
|
||||
/**
|
||||
* Max number of items to cache
|
||||
* @var int
|
||||
*/
|
||||
protected $_iMaxItemsToCache = 10;
|
||||
|
||||
/**
|
||||
* Enable caching
|
||||
* @var bool
|
||||
*/
|
||||
protected $_bEnable = false;
|
||||
protected $_iFrame;
|
||||
|
||||
/**
|
||||
* Contructor of Contenido_ItemCache
|
||||
* @param string $_sTable Table name
|
||||
* @param array $aOptions Options array as follows:
|
||||
* - $aOptions['max_items_to_cache'] = (int) Number of items to cache
|
||||
* - $aOptions['enable'] = (bool) Flag to enable caching
|
||||
*/
|
||||
protected function __construct(protected $_sTable, array $aOptions = []) {
|
||||
if (isset($aOptions['max_items_to_cache']) && (int) $aOptions['max_items_to_cache'] > 0) {
|
||||
$this->_iMaxItemsToCache = (int) $aOptions['max_items_to_cache'];
|
||||
}
|
||||
if (isset($aOptions['enable']) && is_bool($aOptions['enable'])) {
|
||||
$this->_bEnable = $aOptions['enable'];
|
||||
}
|
||||
|
||||
if (isset($_GET['frame']) && is_numeric($_GET['frame'])) {
|
||||
$this->_iFrame = (int) $_GET['frame'];
|
||||
} else {
|
||||
$this->_bEnable = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns item cache instance, creates it, if not done before.
|
||||
* Works as a singleton for one specific table.
|
||||
*
|
||||
* @param string $sTable Table name
|
||||
* @param array $aOptions Options array as follows:
|
||||
* - $aOptions['max_items_to_cache'] = (int) Number of items to cache
|
||||
* - $aOptions['enable'] = (bool) Flag to enable caching
|
||||
*/
|
||||
public static function getInstance($sTable, array $aOptions = []) {
|
||||
if (!isset(self::$_oInstances[$sTable])) {
|
||||
self::$_oInstances[$sTable] = new self($sTable, $aOptions);
|
||||
}
|
||||
return self::$_oInstances[$sTable];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns items cache list.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getItemsCache() {
|
||||
return $this->_aItemsCache[$this->_iFrame];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns existing entry from cache by it's id.
|
||||
*/
|
||||
public function getItem(mixed $mId): ?array {
|
||||
if (!$this->_bEnable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($this->_aItemsCache[$this->_iFrame][$mId])) {
|
||||
return $this->_aItemsCache[$this->_iFrame][$mId];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns existing entry from cache by matching propery value.
|
||||
*/
|
||||
public function getItemByProperty(mixed $mProperty, mixed $mValue): ?array {
|
||||
if (!$this->_bEnable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// loop thru all cached entries and try to find a entry by it's property
|
||||
if (is_array($this->_aItemsCache[$this->_iFrame]) && $this->_aItemsCache[$this->_iFrame] !== []) {
|
||||
foreach ($this->_aItemsCache[$this->_iFrame] as $aEntry) {
|
||||
if (isset($aEntry[$mProperty]) && $aEntry[$mProperty] == $mValue) {
|
||||
return $aEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns existing entry from cache by matching properties and their values.
|
||||
*
|
||||
* @param array $aProperties Assoziative key value pairs
|
||||
*/
|
||||
public function getItemByProperties(array $aProperties): ?array {
|
||||
if (!$this->_bEnable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// loop thru all cached entries and try to find a entry by it's property
|
||||
foreach ($this->_aItemsCache as $_aItemCache) {
|
||||
$mFound = null;
|
||||
foreach ($aProperties as $key => $value) {
|
||||
if (isset($_aItemCache[$key]) && $_aItemCache[$key] == $value) {
|
||||
$mFound = true;
|
||||
} else {
|
||||
$mFound = false;
|
||||
break;
|
||||
}
|
||||
return $_aItemCache;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds passed item data to internal cache
|
||||
*
|
||||
* @param array $aData Usually the recordset
|
||||
* @return void
|
||||
*/
|
||||
public function addItem(mixed $mId, array $aData) {
|
||||
if (!$this->_bEnable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($this->_aItemsCache[$this->_iFrame])) {
|
||||
$aTmpItemsArray = $this->_aItemsCache[$this->_iFrame];
|
||||
|
||||
if ($this->_iMaxItemsToCache == (is_countable($aTmpItemsArray) ? count($aTmpItemsArray) : 0)) {
|
||||
// we have reached the maximum number of cached items, remove first entry
|
||||
$firstEntryKey = array_shift($aTmpItemsArray);
|
||||
if (is_array($firstEntryKey))
|
||||
return null;
|
||||
unset($this->_aItemsCache[$this->_iFrame][$firstEntryKey]);
|
||||
}
|
||||
}
|
||||
|
||||
// add entry
|
||||
$this->_aItemsCache[$this->_iFrame][$mId] = $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes existing cache entry by it's key
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeItem(mixed $mId) {
|
||||
if (!$this->_bEnable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// remove entry
|
||||
if (isset($this->_aItemsCache[$this->_iFrame][$mId])) {
|
||||
unset($this->_aItemsCache[$this->_iFrame][$mId]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1231
conlite/classes/GenericDb/ItemCollection.php
Normal file
1231
conlite/classes/GenericDb/ItemCollection.php
Normal file
File diff suppressed because it is too large
Load diff
9
conlite/classes/GenericDb/ItemException.php
Normal file
9
conlite/classes/GenericDb/ItemException.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace ConLite\GenericDb;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ItemException extends Exception {
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -142,7 +142,7 @@ require_once($cfg['path']['conlite'] . $cfg['path']['includes'] . '/api/function
|
|||
include_once($cfg['path']['conlite'] . $cfg['path']['classes'] . 'class.autoload.php');
|
||||
cAutoload::initialize($cfg);
|
||||
// init composer autoload
|
||||
include_once($cfg['path']['conlite'] . 'vendor/autoload.php');
|
||||
include_once(dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'vendor/autoload.php');
|
||||
|
||||
|
||||
// 2. security check: Check HTTP parameters, if requested
|
||||
|
|
4
vendor/composer/installed.php
vendored
4
vendor/composer/installed.php
vendored
|
@ -5,7 +5,7 @@
|
|||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '727cad0e1e2ad00ac92dac6aa02e5ea0b4ca1dfb',
|
||||
'reference' => '680b5bad712adbaf56c58c3d71ff53edac53c924',
|
||||
'name' => 'org.conlite/conlite',
|
||||
'dev' => false,
|
||||
),
|
||||
|
@ -16,7 +16,7 @@
|
|||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '727cad0e1e2ad00ac92dac6aa02e5ea0b4ca1dfb',
|
||||
'reference' => '680b5bad712adbaf56c58c3d71ff53edac53c924',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpmailer/phpmailer' => array(
|
||||
|
|
Loading…
Reference in a new issue