ConLite/conlite/classes/class.properties.php

516 Zeilen
17 KiB
PHP

<?php
/**
* Project:
* Contenido Content Management System
*
* Description:
* Custom properties
*
* Requirements:
* @con_php_req 5.0
*
*
* @package Contenido Backend classes
* @version 1.2
* @author Timo A. Hummel
* @copyright four for business AG <www.4fb.de>
* @license http://www.contenido.org/license/LIZENZ.txt
* @link http://www.4fb.de
* @link http://www.contenido.org
* @since file available since contenido release <= 4.6
*
* {@internal
* created 2003-12-21
* modified 2008-06-30, Dominik Ziegler, add security fix
* modified 2009-09-27, Dominik Ziegler, fixed wrong (un)escaping
* modified 2011-02-05, Murat Purc, cleanup, formatting and documentation.
* modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
*
2019-07-03 11:58:28 +00:00
* $Id$:
* }}
*
*/
if (!defined('CON_FRAMEWORK')) {
die('Illegal call');
}
/* Custom properties
* -----------------
*
* Custom properties are properties which can be assigned to virtually any element
* in Contenido and underlaying websites.
*
*
* Table structure
* ---------------
*
* Field Size Description
* ----- ---- -----------
* idproperty int(10) idproperty (automatically handled by this class)
* itemtype varchar(32) Custom item type (e.g. idcat, idart, idartlang, custom)
* itemid varchar(32) ID of the item
* type varchar(32) Property type
* name varchar(32) Property name
* value text Property value
* author varchar(32) Author (md5-hash of the username)
* created datetime Created date and time
* modified datetime Modified date and time
* modifiedby varchar(32) Modified by (md5-hash of the username)
*
*
* Example:
* --------
* A module needs to store custom properties for categories. Modifying the database
* would be a bad thing, since the changes might get lost during an upgrade or
* reinstall.
*
* If the custom property for a category would be the path to a category image,
* we would fill a row as follows:
*
* itemtype: idcat
* itemid: <number of your category>
* type: category
* name: image
* value: images/category01.gif
*
* idproperty, author, created, modified and modifiedby are automatically handled by
* the class.
*/
class PropertyCollection extends ItemCollection
{
public $client;
/**
* Constructor Function
* @param none
*/
public function __construct()
{
global $cfg, $client;
$this->client = Contenido_Security::toInteger($client);
parent::__construct($cfg['tab']['properties'], 'idproperty');
$this->_setItemClass('PropertyItem');
}
/**
* Creates a new property item.
*
* Example:
*
* $properties->create('idcat', 27, 'visual', 'image', 'images/tool.gif');
*
* @param mixed $itemtype Type of the item (example: idcat)
* @param mixed $itemid ID of the item (example: 31)
* @param mixed $type Type of the data to store (arbitary data)
* @param mixed $name Entry name
* @param mixed $value Value
* @param bool $bInternally Optionally default false (on internal call do not escape parameters again
* @return PropertyItem
*/
public function create($itemtype, $itemid, $type, $name, $value, $bInternally = false)
{
global $cfg, $auth;
$item = parent::createNewItem();
if (!$bInternally) {
$itemtype = Contenido_Security::escapeDB($itemtype, null);
$itemid = Contenido_Security::escapeDB($itemid, null);
$value = Contenido_Security::escapeDB($value, null);
$type = Contenido_Security::escapeDB($type, null);
$name = Contenido_Security::escapeDB($name, null);
}
$item->set('idclient', $this->client);
$item->set('itemtype', $itemtype, false);
$item->set('itemid', $itemid, false);
$item->set('type', $type);
$item->set('name', $name);
$item->set('value', $value);
$item->set('created', date('Y-m-d H:i:s'), false);
$item->set('author', Contenido_Security::escapeDB($auth->auth['uid'], null));
$item->store();
return ($item);
}
/**
* Returns the value for a given item.
*
* Example:
*
* $file = $properties->getValue('idcat', 27, 'visual', 'image');
*
* @param mixed $itemtype Type of the item (example: idcat)
* @param mixed $itemid ID of the item (example: 31)
* @param mixed $type Type of the data to store (arbitary data)
* @param mixed $name Entry name
* @return mixed Value
*/
public function getValue($itemtype, $itemid, $type, $name, $default = false)
{
$itemtype = Contenido_Security::escapeDB($itemtype, null);
$itemid = Contenido_Security::escapeDB($itemid, null);
$type = Contenido_Security::escapeDB($type, null);
$name = Contenido_Security::escapeDB($name, null);
if($mValue = cPropertyCache::getProp($itemtype, $itemid, $type, $name)) {
return $mValue;
}
if (isset($this->client)) {
$this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
} else {
$this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
}
if ($item = $this->next()) {
cPropertyCache::addProp($item);
return (Contenido_Security::unescapeDB($item->get('value')));
}
//return $default;
}
/**
* Returns the value for a given item.
*
* Example:
*
* $file = $properties->getValuesByType('idcat', 27, 'visual');
*
* @param mixed $itemtype Type of the item (example: idcat)
* @param mixed $itemid ID of the item (example: 31)
* @param mixed $type Type of the data to store (arbitary data)
* @return array Value
**/
public function getValuesByType($itemtype, $itemid, $type)
{
$aResult = array();
$itemtype = Contenido_Security::escapeDB($itemtype, null);
$itemid = Contenido_Security::escapeDB($itemid, null);
$type = Contenido_Security::escapeDB($type, null);
if (isset($this->client)) {
$this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."'");
} else {
$this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."'");
}
while ($item = $this->next()) {
cPropertyCache::addProp($item);
$aResult[$item->get('name')] = Contenido_Security::unescapeDB($item->get('value'));
}
return $aResult;
}
/**
* Sets a property item. Handles creation and updating.
*
* Example:
*
* $properties->setValue('idcat', 27, 'visual', 'image', 'images/tool.gif');
*
* @param mixed $itemtype Type of the item (example: idcat)
* @param mixed $itemid ID of the item (example: 31)
* @param mixed $type Type of the data to store (arbitary data)
* @param mixed $name Entry name
* @param mixed $value Value
* @param int $idProp Id of database record (if set, update on this basis (possiblity to update name value and type))
*/
public function setValue($itemtype, $itemid, $type, $name, $value, $idProp = 0)
{
$itemtype = Contenido_Security::escapeDB($itemtype, null);
$itemid = Contenido_Security::escapeDB($itemid, null);
$type = Contenido_Security::escapeDB($type, null);
$name = Contenido_Security::escapeDB($name, null);
$value = Contenido_Security::escapeDB($value, null);
$idProp = Contenido_Security::toInteger($idProp);
if ($idProp == 0) {
$this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
} else {
$this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND idproperty = '".$idProp."'");
}
if ($item = $this->next()) {
$item->set('value', $value);
$item->set('name', $name);
$item->set('type', $type);
$item->store();
} else {
$this->create($itemtype, $itemid, $type, $name, $value, true);
}
}
/**
* Delete a property item.
*
* Example:
*
* $properties->deleteValue('idcat', 27, 'visual', 'image');
*
* @param mixed $itemtype Type of the item (example: idcat)
* @param mixed $itemid ID of the item (example: 31)
* @param mixed $type Type of the data to store (arbitary data)
* @param mixed $name Entry name
*/
public function deleteValue($itemtype, $itemid, $type, $name)
{
$itemtype = Contenido_Security::escapeDB($itemtype, null);
$itemid = Contenido_Security::escapeDB($itemid, null);
$type = Contenido_Security::escapeDB($type, null);
$name = Contenido_Security::escapeDB($name, null);
if (isset($this->client)) {
$this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
} else {
$this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
}
if ($item = $this->next()) {
$this->delete($item->get('idproperty'));
}
}
/**
* Checks if values for a given item are available.
*
* @param mixed $itemtype Type of the item (example: idcat)
* @param mixed $itemid ID of the item (example: 31)
* @return array For each given item
*/
public function getProperties($itemtype, $itemid)
{
$itemtype = Contenido_Security::escapeDB($itemtype, null);
$itemid = Contenido_Security::escapeDB($itemid, null);
if (isset($this->client)) {
$this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
} else {
$this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
}
$result[$itemid] = false;
while ($item = $this->next()) {
cPropertyCache::addProp($item);
// enable accessing property values per number and field name
$result[$item->get('itemid')][$item->get('idproperty')] = array(
0=> $item->get('type'), 'type'=> $item->get('type'),
1=> $item->get('name'), 'name'=> $item->get('name'),
2=> $item->get('value'), 'value'=> $item->get('value')
);
}
return $result;
}
/**
* Returns all datasets selected by given field and value combination
*
* @param mixed $field Field to search in
* @param mixed $fieldValue Value to search for
* @param Contenido_Auth $auth Narrow result down to user in auth objext
* @return array For each given item
*/
public function getAllValues($field, $fieldValue, $auth=NULL)
{
$authString = '';
2019-07-03 19:14:30 +00:00
if (!is_null($auth)
&& is_countable($auth)
&& sizeof($auth) > 0) {
$authString .= " AND author = '" . $auth->auth["uid"] . "'";
}
if (isset($this->client)) {
$this->select("idclient = '" . $this->client . "' AND " . $field . " = '" . $fieldValue . "'" . $authString, '' ,'itemid');
} else {
$this->select($field . " = '" . $fieldValue . "'" . $authString);
}
$retValue = array();
while ($item = $this->next()) {
cPropertyCache::addProp($item);
$dbLine = array(
'idproperty' => $item->get('idproperty'),
'idclient' => $item->get('idclient'),
'itemtype' => $item->get('itemtype'),
'itemid' => $item->get('itemid'),
'type' => $item->get('type'),
'name' => $item->get('name'),
'value' => $item->get('value'),
'author' => $item->get('author'),
'created' => $item->get('created'),
'modified' => $item->get('modified'),
'modifiedby' => $item->get('modifiedby')
);
$retValue[] = $dbLine;
}
return $retValue;
}
/**
* Delete all properties which match itemtype and itemid
*
* @param mixed $itemtype Type of the item (example: idcat)
* @param mixed $itemid ID of the item (example: 31)
*/
public function deleteProperties($itemtype, $itemid)
{
$itemtype = Contenido_Security::escapeDB($itemtype, null);
$itemid = Contenido_Security::escapeDB($itemid, null);
if (isset($this->client)) {
$this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
} else {
$this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
}
$deleteProperties = array();
while ($item = $this->next()) {
$deleteProperties[] = $item->get('idproperty');
}
foreach($deleteProperties as $idproperty) {
cPropertyCache::deleteProp($idproperty);
$this->delete($idproperty);
}
}
public function changeClient($idclient)
{
$this->client = $idclient;
}
}
class PropertyItem extends Item
{
/**
* maximumLength: Array which stores the maximum string length of each field
*/
public $maximumLength;
/**
* Constructor Function
* @param mixed $mId Specifies the ID of item to load
*/
public function __construct($mId = false)
{
global $cfg;
parent::__construct($cfg['tab']['properties'], 'idproperty');
// Initialize maximum lengths for each column
$this->maximumLength = array();
$this->maximumLength['itemtype'] = 64;
$this->maximumLength['itemid'] = 255;
$this->maximumLength['type'] = 96;
$this->maximumLength['name'] = 96;
if ($mId !== false) {
$this->loadByPrimaryKey($mId);
}
}
/**
* Stores changed PropertyItem
*/
public function store()
{
global $auth;
$this->set('modified', date('Y-m-d H:i:s'), false);
$this->set('modifiedby', $auth->auth['uid']);
parent::store();
}
/**
* Sets value of a field
*
* @param string $field
* @param string $value
* @param bool $safe Flag to run filter on passed value
*/
public function setField($field, $value, $safe = true)
{
if (array_key_exists($field, $this->maximumLength)) {
if (strlen($value) > $this->maximumLength[$field]) {
cWarning(__FILE__, __LINE__, "Tried to set field $field to value $value, but the field is too small. Truncated.");
}
}
parent::setField($field, $value, $safe);
}
}
class cPropertyCache {
/**
* Property cache array
* @var array
*/
public static $_aEntries;
/**
* add item to cache
*
* @param object $oEntry
*/
public static function addProp($oEntry) {
if(!is_array(self::$_aEntries)) {
self::$_aEntries = array();
}
$aData = $oEntry->toArray();
self::$_aEntries[$aData['idproperty']] = $aData;
}
/**
* Delete item from cache
*
* @param int $iId id of prperty
*/
public static function deleteProp($iId) {
if(isset(self::$_aEntries[$iId]) && is_array(self::$_aEntries[$iId])) {
unset(self::$_aEntries[$iId]);
}
}
/**
* get property from cache
*
* @param string $itemtype
* @param int $itemid
* @param string $type
* @param string $name
* @return string|boolean string of entry or false
*/
public static function getProp($itemtype, $itemid, $type, $name) {
if(!is_array(self::$_aEntries) || empty(self::$_aEntries)) {
return false;
}
foreach (self::$_aEntries as $id => $entry) {
if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid && $entry['type'] == $type && $entry['name'] == $name) {
return (string) $entry['value'];
}
}
return false;
}
}
?>