Files
bm/public_html/public/cms/modules/_cmsobject.class.php
2025-09-24 13:26:28 +02:00

928 lines
24 KiB
PHP

<?php
require_once(ROOT."include/template.inc.php");
require_once(ROOT."include/error.inc.php");
require_once(ROOT."include/config.inc.php");
require_once(ROOT."include/array.inc.php");
require_once(ROOT."include/db.inc.php");
require_once(ROOT."include/url.inc.php");
$php = explode(".", phpversion());
if($php[0] < 5){
require_once(ROOT."include/clone.inc.php");
}
#
# My PHP4 OOP Coding Guidelines:
#
# Methods starting with 'do' (eg. doFoo()) are meant to be private
# Methods in uppercase letters (eg. FOO()) are meant to be static
# Methods with an empty implementation {} are meant to be abstract
#
/** CMS Object
* abstract superclass for all CMS objects
*
* @version 2.1.0
* @since 2007-05-01
* @author martin lenzelbauer
*
* @todo implement locking mechanism
*
* @change 2007-06-21
* added htmlspecialchars() in printChildContent()
*
* @change 2008-09-23
* updated loading & publishing routines to keep memory low in PHP5
*
*/
class CmsObject{
// --- object metadata --- //
var $id; //unique id of the object
var $name; //the name of the object
var $parentId; //id of the parent element
var $parentObj; //the parent element
var $childObjects; //array of child objects
var $allowedChildObjects; //names of classes that are allowed as child objects
var $visible; //true, if the page is visible online
var $editable; //editable by USER_ALL, USER_NORMAL or USER_ADMIN
var $listable; //listable for USER_ALL, USER_NORMAL or USER_ADMIN
var $lastUpdate; //date of last changes
// --- static metadata --- //
var $lockable; //true, if the page can be locked from editing by other users at the same time
var $dynamic; //true, if the page is dynamic -> rendered each time it is shown
//flase, if the page is static -> rendered one time and saved to db cache
// --- menu buttons --- //
var $buttonPreview; //true, if there should be a preview button
var $buttonPublish; //true, if there should be a publish button
var $buttonDelete; //true, if there should be a delete button (for non-admin users)
var $buttonMove; //true, if there should be a move button (for non-admin users)
// --- helper variables --- //
var $loaded; //true, if the data is loaded
var $locked; //true, if the page is locked (currently edited by another user)
var $errors; //array of error messages
/** C'tor (default settings)
* @param parent parent element
*/
//-----------------------------------------------
function CmsObject($id=0, $parent=NULL){
//-----------------------------------------------
$this->id = $id;
$this->name = "[unbenannt]";
$this->parentId = 0;
$this->parentObj = $parent;
$this->childObjects = array();
$this->allowedChildObjects = array();
$this->lockable = true;
$this->editable = USER_GROUP;
$this->listable = USER_ALL;
$this->locked = false;
$this->loaded = false;
$this->visible = 0;
$this->dynamic = false;
$this->errors = array();
$this->buttonPreview = false;
$this->buttonPublish = false;
$this->buttonDelete = false;
$this->buttonMove = false;
$this->lastUpdate = "0000-00-00 00:00:00";
if($parent){
$this->parentId = $parent->getId();
}
}
/** toString()
* @return html encoded string
*/
//-----------------------------------------------
function toString(){
//-----------------------------------------------
return stripslashes(htmlspecialchars($this->name));
}
/** loads the object
* @param path path to the currently editing object
* @return nothing
*/
//-----------------------------------------------
function load($path=array()){}
//-----------------------------------------------
/** unloads all child contents
* @param depth the depth into the child hierachy to unload
* 0 = completely unload this
* 1 = completely unload the child elements but keep them in this
* 2 = completely unload the grand child elements ...
*/
//-----------------------------------------------
function unload($depth=1){
//-----------------------------------------------
for($i = 0; $i < sizeof($this->childObjects); $i++) {
$this->childObjects[$i]->unload($depth - 1);
if ($depth <= 0) {
unset($this->childObjects[$i]);
}
}
if ($depth <= 0) {
unset($this->childObjects);
$this->childObjects = array();
}
$this->loaded = false;
}
/** unloads the parent object and all it's parents
*/
//----------------------------------------------
function unloadParent(){
//----------------------------------------------
if($this->parentObj){
$this->parentObj->unload(0);
$this->parentObj->unloadParent();
unset($this->parentObj);
}
}
/** saves the object
* @return nothing
*/
//-----------------------------------------------
function save(){}
//-----------------------------------------------
/** deletes the page content and all subpages
* @return true, if deleted successfully
*/
//-----------------------------------------------
function delete(){}
//-----------------------------------------------
/** inserts a child object
* @param index position
* @param class class name
* @return the inserted child object
*/
//-----------------------------------------------
function &insertChild($index, $class){
//-----------------------------------------------
$this->childObjects = array_insert($this->childObjects, $index, FlexiconFactory::instanceByClass($class, $this));
return $this->childObjects[$index];
}
/** moves the position of a child element
* @param id flexicon id
* @param direction "up" or "down"
* @return nothing
*/
//----------------------------------------------
function moveChild($id, $direction){
//----------------------------------------------
//search index
$index = -1;
for($i=0; $i<sizeof($this->childObjects) && $index == -1; $i++){
if($this->childObjects[$i]->getId() == $id){
$index = $i;
}
}
//move child
if($index >= 0){
if($direction == "up" && $index > 0){
$this->childObjects = array_swap($this->childObjects, $index, $index-1);
}
if($direction == "down" && $index < sizeof($this->childObjects)-1){
$this->childObjects = array_swap($this->childObjects, $index, $index+1);
}
}
}
/** cuts a child object and saves its flexicon id to the session
* @param id flexicon id
* @return nothing
*/
//-----------------------------------------------
function cutChild($id){
//-----------------------------------------------
for($i=0; $i<sizeof($this->childObjects); $i++){
if($this->childObjects[$i]->getId() == $id){
array_splice($this->childObjects, $i, 1);
$_SESSION['flexicon_cut_object_id'] = $id;
return;
}
}
}
/** pastes a child object from the session
* @return nothing
*/
//-----------------------------------------------
function pasteChild($index){
//-----------------------------------------------
$id = $_SESSION['flexicon_cut_object_id'];
$child = FlexiconFactory::instanceById($id, $this);
$child->load();
$child->setParentId($this->getId());
array_splice($this->childObjects, $index, 0, array($child));
unset($_SESSION['flexicon_cut_object_id']);
}
/** deletes a child object
* @param id flexicon id
* @return nothing
*/
//-----------------------------------------------
function deleteChild($id){
//-----------------------------------------------
//search index
$index = -1;
for($i=0; $i<sizeof($this->childObjects) && $index == -1; $i++){
if($this->childObjects[$i]->getId() == $id){
$index = $i;
}
}
//delete child
if($index >= 0){
if($this->childObjects[$index]->delete()){
$this->childObjects = array_remove($this->childObjects, $index);
$this->save();
}
else{
$this->addError($this->childObjects[$index]->getErrors());
}
}
}
/** processes $_POST data
* @return nothing
*/
//-----------------------------------------------
function update(){}
//-----------------------------------------------
/** prints the content form
*/
//-----------------------------------------------
function printContent(){
//-----------------------------------------------
if($this->locked){
return $this->doPrintLocked();
}
$out = $this->doPrintErrors();
if($_SESSION['userlevel'] == USER_ADMIN){
$out .= $this->doPrintMetadata();
}
if($this->isEditable()){
$out .= $this->doPrintClassContent();
for($i = 0; $i < sizeof($this->childObjects); $i++) {
if($this->childObjects[$i]->isListable()){
$out .= $this->doPrintInsertBar($i);
$out .= $this->childObjects[$i]->printChildContent();
}
}
$out .= $this->doPrintInsertBar(sizeof($this->childObjects));
$out .= $this->doPrintButtons();
}
else{
$out .= $this->doPrintNotEditable();
}
return $out;
}
/** prints the common metadata
* @return string
*/
//-----------------------------------------------
function doPrintMetadata(){
//-----------------------------------------------
$t = new Template(CMS_TEMPLATE_DIR."metadata.html");
$t->setVar("NAME", htmlspecialchars($this->name));
for($i=1; $i<=3; $i++){
if($this->editable == $i){
$t->setVar("EDITABLE$i", 'selected="selected"');
}
else{
$t->setVar("EDITABLE$i", '');
}
}
for($i=1; $i<=3; $i++){
if($this->listable == $i){
$t->setVar("LISTABLE$i", 'selected="selected"');
}
else{
$t->setVar("LISTABLE$i", '');
}
}
if($this->visible){
$t->setVar("VISIBLE", 'checked="checked"');
}
else{
$t->setVar("VISIBLE", '');
}
return $t->toString();
}
/** prints the page content if the page is the current page
* @return string
*/
//-----------------------------------------------
function doPrintClassContent(){
//-----------------------------------------------
return "";
}
/** prints the page content if the page is a child of the current page
* @return string
*/
//-----------------------------------------------
function printChildContent(){
//-----------------------------------------------
$t = new Template(CMS_TEMPLATE_DIR."child.html");
$t->setVar("TITLE", FlexiconFactory::nameOfClass(get_class($this)));
$t->setVar("NAME", htmlspecialchars($this->name));
$t->setVar("CLASS", strtolower(get_class($this)));
$t->setVar("PATH", $this->printPath());
$t->setVar("ID", $this->id);
if(!$this->buttonDelete && $_SESSION['userlevel'] < USER_ADMIN){
$t->removeBlock("DELETE");
}
if(!$this->buttonMove && $_SESSION['userlevel'] < USER_ADMIN){
$t->removeBlock("MOVE");
}
if ($_SESSION['userlevel'] < USER_ADMIN || isset($_SESSION['flexicon_cut_object_id'])){
$t->removeBlock("CUT");
}
if ($_SESSION['userlevel'] < USER_ADMIN){
$t->removeBlock("ADMIN");
}
return $t->toString();
}
/** prints a bar with buttons for inserting child objects
* @param index position, where the child element will be inserted
* @return string
*/
//-----------------------------------------------
function doPrintInsertBar($index){
//-----------------------------------------------
if(sizeof($this->allowedChildObjects) == 0){
return "";
}
$t = new Template(CMS_TEMPLATE_DIR."insertbar.html");
$out = "";
foreach($this->allowedChildObjects as $class){
$out .= sprintf("<div class=\"insert\" onMouseOver=\"showTooltip('%s einf&uuml;gen')\" onClick=\"insertElement('%s', %d)\">".
"<img src=\"images/%s1.png\" alt=\"%s einf&uuml;gen\" onMouseOver=\"swapImage(this,2)\" onMouseOut=\"swapImage(this,1)\" />".
"</div>",
htmlspecialchars(FlexiconFactory::nameOfClass($class)),
$class,
$index,
$class,
htmlspecialchars(FlexiconFactory::nameOfClass($class)));
}
$t->setVar("CLASSES", $out);
$t->setVar("INDEX", $index);
if ($_SESSION['userlevel'] < USER_ADMIN || !isset($_SESSION['flexicon_cut_object_id'])){
$t->removeBlock("PASTE");
}
return $t->toString();
}
/** prints error messages
* @return errors as unordered list
*/
//-----------------------------------------------
function doPrintErrors(){
//-----------------------------------------------
if(sizeof($this->errors) == 0){
return "";
}
$t = new Template(CMS_TEMPLATE_DIR."errors.html");
$t->setVar("ERRORS", array_print($this->errors));
return $t->toString();
}
/** prints content for not editable objects
*/
//----------------------------------------------------
function doPrintNotEditable(){
//----------------------------------------------------
/*$t =& new Template(CMS_TEMPLATE_DIR."noteditable.html");
return $t->toString();*/
$out = "";
foreach($this->childObjects as $i=>$child){
if($this->childObjects[$i]->isListable()){
$out .= $this->childObjects[$i]->printChildContent();
}
}
return $out;
}
/** prints a message that the element is locked
* @return output string
*/
//----------------------------------------------
function doPrintLocked(){
//----------------------------------------------
$query = sprintf("SELECT user FROM bruckm_lock WHERE pageId = %d LIMIT 1",
$this->id);
$result = dbQuery($query);
$line = mysqli_fetch_array($result, MYSQLI_ASSOC);
$t = new Template(CMS_TEMPLATE_DIR."locked.html");
$t->setVar("USER", $line['user']);
return $t->toString();
}
/** prints buttons
* @return string
*/
//-----------------------------------------------
function doPrintButtons(){
//-----------------------------------------------
$t = new Template(CMS_TEMPLATE_DIR."buttons.html");
$t->setVar("ID", $this->id);
if(!$this->buttonPreview){
$t->removeBlock("PREVIEW");
}
if(!$this->buttonPublish){
$t->removeBlock("PUBLISH");
}
return $t->toString();
}
/** prints tree menu with $this as root
* @param path path to the current object
* @return string
*/
//----------------------------------------------------
function printTreeMenu($path){
//----------------------------------------------------
$out = "";
if($_SESSION['userlevel'] < $this->listable){
return "";
}
if($this->id != 0){
if(sizeof($path) == 1 && $path[0] == $this->id){
$out .= "<li class=\"".$this->getCssClass()."\"><b>".$this->toString()."</b>";
}
else{
$out .= "<li class=\"".$this->getCssClass()."\">";
$out .= "<a href=\"javascript:loadPage('" . $this->printPath() . "')\" target=\"_self\">";
$out .= $this->toString();
$out .= "</a>";
}
}
if(sizeof($path) >= 1 && $path[0] == $this->id && sizeof($this->childObjects) > 0){
$out .= "<ul>";
array_shift($path);
foreach($this->childObjects as $i=>$child){
if($this->childObjects[$i]->isListable()){
$out .= $this->childObjects[$i]->printTreeMenu($path);
}
}
$out .= "</ul>";
}
if($this->id != 0){
$out .= "</li>";
}
return $out;
}
/** prints breadcrums menu with $this as root
* @param path path to the current object
* @return string
*/
//----------------------------------------------------
function printBreadcrumbs($path){
//----------------------------------------------------
$out = "";
if(!$path || sizeof($path) <= 1){
return "<strong>" . $this->toString() . "</strong>";
}
if($this->isListable()){
$out = "<a href=\"javascript:loadPage('" . $this->printPath() . "')\" target=\"_self\">";
$out .= $this->toString();
$out .= "</a>";
}
else{
$out = $this->toString();
}
$out .= " &raquo; ";
array_shift($path);
if(sizeof($this->childObjects) > 0){
foreach($this->childObjects as $i=>$child){
if($this->childObjects[$i]->getId() == $path[0]){
$out .= $this->childObjects[$i]->printBreadcrumbs($path);
return $out;
}
}
}
return $out;
}
/** prints the path array as id-id-id-id string
* @rteurn string
*/
//-----------------------------------------------
function printPath(){
//-----------------------------------------------
return implode("/", $this->getPath());
}
/** processes individual element actions
* @param action action name
* @param position additional parameter
* @param type additional parameter
*/
//---------------------------------------------
function handleAction($action, $position=0, $type=NULL){
//---------------------------------------------
return;
}
/** adds an error message
* @param msg error message or array of errors
*/
//---------------------------------------------
function addError($msg){
//---------------------------------------------
if(is_string($msg)){
$msg = "<b>".$this->toString()."</b>: ".htmlspecialchars($msg);
}
$this->errors[] = $msg;
}
/** publishes the content for the web
* @return true, if successful
*/
//---------------------------------------------
function publish(){
//---------------------------------------------
if($this->canBePublished()){
$out = $this->doPublish();
if(!$this->dynamic){
$query = sprintf("UPDATE bruckm_index SET cache = %s WHERE id = %d",
sqlstring($out),
sqlnum($this->id));
dbQuery($query);
}
return true;
}
return false;
}
/** checks if the object is valid for publishing
* @return true, if valid
*/
//----------------------------------------------
function canBePublished(){
//----------------------------------------------
return true;
}
/** creates the web content
* @return string or null
*/
//---------------------------------------------
function doPublish(){}
//---------------------------------------------
/** creates a preview
* @return string
*/
//---------------------------------------------
function preview(){
//---------------------------------------------
if($this->canBePublished()){
return $this->doPublish();
}
$t = new Template(TEMPLATE_DIR."errorpage.html");
$t->setVar("MESSAGE", $this->doPrintErrors());
return $t->toString();
}
/** shows the content for web
* @return string
*/
//---------------------------------------------
function show(){
//---------------------------------------------
$query = sprintf("SELECT * FROM bruckm_index WHERE id = %d", sqlnum($this->id));
$result = dbQuery($query);
$line = mysqli_fetch_array($result, MYSQLI_ASSOC);
if (!$line['cache']){
// try menu
$query = sprintf("SELECT class,classId FROM bruckm_index WHERE id = %d", sqlnum($this->id));
$result = dbQuery($query);
$line = mysqli_fetch_array($result, MYSQLI_ASSOC);
if (strtolower($line['class']) == "menu") {
$query = sprintf("SELECT startPage FROM bruckm_menu WHERE id = %d", $line['classId']);
$result = dbQuery($query);
$line = mysqli_fetch_array($result, MYSQLI_ASSOC);
$page = FlexiconFactory::instanceById($line['startPage']);
$page->load();
return $page->show();
}
// throw exception
logError(3, "Page content is NULL - id: ".$this->id." referer: ".$_SERVER['HTTP_REFERER'], __FILE__, __LINE__);
header("Location: index.php");
return;
}
return $this->fixEncoding($line['cache']);
}
function fixEncoding($str) {
return $str;
//return iconv('ISO-8859-1', 'UTF-8', $str);
}
/** locks the page for editing
* @throws DBException
* @return true, if the page was locked successfully
*/
//---------------------------------------------
function lock(){
//---------------------------------------------
/*
if(!$this->lockable){
$this->locked = false;
return true;
}
if($this->id == 0){
$this->locked = false;
return true;
}
//check if page is currently locked by another user
$query = sprintf("SELECT (TIME_TO_SEC(NOW()) - TIME_TO_SEC(lockTime)), user, id FROM bruckm_lock
WHERE elementId = %d AND class = %s",
$this->id,
sqlstring(get_class($this)));
$result = dbQuery($query);
if(!$result){
recipientsception($query, mysql_error());
}
$line = mysqli_fetch_array($result, MYSQL_NUM);
//page is locked
if($line[0] == 1){
if($line[1] < 3600 && $line[2] != $_SESSION['user']){
$this->locked = true;
return false;
}
$query = sprintf("UPDATE bruckm_lock SET lockTime = NOW() WHERE id = %d", $line[2]);
dbQuery($query);
return true;
}
//lock page
$query = sprintf("INSERT INTO bruckm_lock (elementId, class, user, lockTime) VALUES (%d, %s, %s, NOW())",
$this->id,
sqlstring(get_class($this)),
sqlstring($_SESSION['user']));
$result = dbQuery($query);
if(!$result){
recipientsception($query, mysql_error());
}
$this->locked = false;
return true;
*/
}
/** unlocks the page after editing
* @throws DBException
*/
//-----------------------------------------------
function unlock(){
//-----------------------------------------------
/*if(!$this->lockable){
return;
}
if($this->locked){
return;
}
if($this->id == 0){
return;
}
$query = sprintf("DELETE FROM bruckm_lock WHERE elementId = %d AND class = %s LIMIT 1",
$this->id,
sqlstring(get_class($this)));
$result = dbQuery($query);
if(!$result){
recipientsception($query, mysql_error());
} */
}
#### GETTER ######################################################################
/** returns the unique id of the object
*/
//-----------------------------------------------
function getId(){
//-----------------------------------------------
return $this->id;
}
/** returns the name of the object
*/
//-----------------------------------------------
function getName(){
//-----------------------------------------------
return $this->name;
}
/** returns the last update of the object
*/
//-----------------------------------------------
function getLastUpdate(){
//-----------------------------------------------
return $this->lastUpdate;
}
/** returns the css class for the list item formatting (defined in flexicon.css)
* @return name of css class
*/
//-----------------------------------------------
function getCssClass(){}
//-----------------------------------------------
/** checks if the page is visible in the cms
* @return boolean
*/
//-----------------------------------------------
function isListable(){
//-----------------------------------------------
if($_SESSION['userlevel'] >= $this->listable){
return true;
}
return false;
}
/** checks if the page is editable for the current user
* @return boolean
*/
//-----------------------------------------------
function isEditable(){
//-----------------------------------------------
if($_SESSION['userlevel'] >= $this->editable){
return true;
}
return false;
}
/** checks if the page is visible in the menu
* @return boolean
*/
//-----------------------------------------------
function isVisible(){
//-----------------------------------------------
return $this->visible;
}
/** checks if the data is loaded
* @return boolean
*/
//-----------------------------------------------
function isLoaded(){
//-----------------------------------------------
return $this->loaded;
}
/** returns a chain of indices pointing from root to this
* @return array
*/
//--------------------------------------------------
function getPath(){
//--------------------------------------------------
if($this->parentObj){
$path = $this->parentObj->getPath();
$path[] = $this->id;
return $path;
}
return array($this->id);
}
/** returns the currently edited object
* @param path path to the page
* @return CmsObject
*/
//-------------------------------------------
function &getCurrent($path){
//-------------------------------------------
if(!$path || sizeof($path) <= 1){
return $this;
}
array_shift($path);
foreach($this->childObjects as $i=>$child){
if($this->childObjects[$i]->getId() == $path[0]){
return $this->childObjects[$i]->getCurrent($path);
}
}
logError(4, "no child object found", __FILE__, __LINE__);
}
/** returns the object's errors array
* @return errors
*/
//------------------------------------------
function getErrors(){
//------------------------------------------
return $this->errors;
}
// === SETTER ====================================================== //
/** sets the parent object
* @param parent parent
*/
//-------------------------------------------
function setParent($parent){
//-------------------------------------------
$this->parentObj = $parent;
}
/** sets the parent id
* @param parentId parent id
*/
//-------------------------------------------
function setParentId($parentId){
//-------------------------------------------
$this->parentId = $parentId;
}
};
?>