* @package MCMS\System */ class System extends \MCMS\SystemBase implements \MCMS\Interfaces\iSystem { const _VERSION_ = '1.1.0.0'; const LOGNAME = 'MCMSSys'; protected static $log; protected $userSvc; private static $tbl_sysconfig = 'systemsettings'; private static $tbl_siteconfig = 'websitesettings'; /** * * @var Request */ protected $request; protected function __construct() { parent::__construct(); if(defined('_CLI_')) { // check for cli mode $this->request = new \MCMS\RequestCLI(); } else $this->request = new \MCMS\Request(); } /** * initialize the mammut cms system. * * this initializes the database connection, tries to get the active system instance * and user, and * searche/register active plugins */ static public function init(array $options = array()) { if(is_object(self::$instance)) throw new IllegalStateException('system already initialized'); self::$instance = new self(); // bind the instance property to an instance of this class if (isset($options['weaving'])) self::$instance->weaving = $options['weaving']; else { // fallback - load default file self::$instance->weaving = array_from_file(defined('WEAVINGCFG') ? constant('WEAVINGCFG') : _INCPATH_.__DS__.'mcms'.__DS__.'inc.weaving.php' , 'weaving'); } } /** * shut down the mammut cms system an cleans up all */ public static function shutdown() { if(!is_object(self::$instance)) throw new IllegalStateException('system not initialized'); self::$instance = NULL; // this should call the destructor } // site settings/component instance settings public function getSiteParam($siteInst, $modInst, $key, $default = NULL) { $this->LOG->traceStart(); $cache = self::getContext(self::CTX_CACHE); $cachekey = implode('@',array('siteparam',$siteInst,$modInst,$key)); $value = NULL; if(!$cache->keyExists($cachekey) || is_null($value = $cache->get($cachekey))) { $db = $this->getDB(); if(!is_object($db)) throw new IllegalStateException('database not initialized'); if (is_null($siteInst)) { $where = array('area' => new Parameter(),'key' => new Parameter()); $q = $db->select()->from(self::$tbl_sysconfig)->where($where); $result = $db->prepareStatement($q); $result->execute(array($modInst, $key)); } else { $where = array('site_id' => new Parameter(),'instance' => new Parameter(),'key' => new Parameter()); $q = $db->select()->from(self::$tbl_siteconfig)->where($where); $result = $db->prepareStatement($q); $result->execute(array($siteInst, $modInst, $key)); } if($result->getRowCount() == 1) { $value = $result->fetchObject()->value; $cache->set($cachekey, $value, 30); } $result->close(); } return is_null($value) ? $default : $value; } public function setSiteParam($siteInst, $comInst, $key, $value) { $this->LOG->traceStart(); $db = $this->getDB(); if(!is_object($db)) throw new IllegalStateException('database not initialized'); if (is_null($siteInst)) { $cond = array('area' => $comInst,'key' => $key); $table = $db->table(self::$tbl_sysconfig); $result = $table->select($cond); if($result->getRowCount() == 1) $table->update(array('value' => $value), $cond); else { $data = $cond; $data['value'] = $value; $table->insert($data); } } else { $cond = array('site_id' => $siteInst,'instance' => $comInst,'key' => $key); $table = $db->table(self::$tbl_siteconfig); $result = $table->select($cond); if($result->getRowCount() == 1) $table->update(array('value' => $value), $cond); else { $data = $cond; $data['value'] = $value; $table->insert($data); } } $cache = self::getContext(self::CTX_CACHE); // $this->cacheStore('[siteparam]-' . $siteInst, $comInst, $key, $value, 30); } public function getRequest() { $this->LOG->traceStart(); return $this->request; } public function initUserSvc($pluginClass, $cfg = array()) { $this->LOG->traceStart(); if(!is_null($this->userSvc)) throw new \BadMethodCallException("User plugin is set already"); if(!class_exists($pluginClass)) throw new \ErrorException("User plugin '{$pluginClass}' class not found"); $this->userSvc = new $pluginClass($cfg); $this->plugins['auth'][0] = $this->userSvc; } public function getUserSvc() { $this->LOG->traceStart(); return $this->userSvc; } public function isUserSystemAdmin(iUser $user) { $this->LOG->traceStart(); return false; // TODO: implement and use } public function getCache() { $this->LOG->traceStart(); return self::getContext(iSystem::CTX_CACHE); } public function onException(\Exception $e) { $this->LOG->traceStart(); if(defined('_CLI_')) { $this->onExceptionCLI($e); return; } $title = 'System Error'; $message = 'A critical error appeared while running this script. Please notify the admin of this page about this!'; $layout = 'Uncaught exception'; $layout .= '

Uncaught exception

'; $layout .= ''; if($e instanceof AccessDeniedException) { $layout = 'Access denied'; $layout .= '

Access denied

'; $layout .= ''; } $l2 = $layout; try { $filename = '_system_' . __DS__ . '_error_.php'; if(file_exists(_LAYOUTPATHX_ . __DS__ . $filename)) { $filename = _LAYOUTPATHX_ . __DS__ . $filename; ob_start(); include ($filename); $layout = ob_get_clean(); } elseif(file_exists(_LAYOUTPATH_ . __DS__ . $filename)) { $filename = _LAYOUTPATH_ . __DS__ . $filename; ob_start(); include ($filename); $layout = ob_get_clean(); } } catch(\Exception $e) { $layout = $l2; } $st = ''; try { $this->writeError2DB($e); } catch(\Exception $sqlex) { $st .= '

Note: SQL-Logger reported another error:' . $sqlex->getMessage() . '

'; $round = 0; $subEx = $sqlex; while(!is_null($subEx = $subEx->getPrevious()) && (++$round < 50)) $st .= '

Caused by ' . get_class($subEx) . ': ' . $subEx->getMessage() . '[' . $subEx->getFile() . ':' . $subEx->getLine() . ']

'; $st .= '
Stacktrace of subexception
' . $sqlex->getTraceAsString() . '
'; } if($e instanceof \ErrorException) { switch($e->getSeverity()) { case E_ERROR: $st .= '

Type: Error

'; break; case E_WARNING: case E_USER_WARNING: $st .= '

Type: Warning

'; break; case E_STRICT: $st .= '

Type: Strict coding convention

'; break; default: $st .= '

Type: unknown(' . $e->getSeverity() . ')

'; break; } } if($e instanceof AccessDeniedException) { $title = 'Access Denied'; $message = 'You have no access to this resource'; if(defined('DEBUG')) { $st .= 'Message: ' . $e->getMessage() . '
'; } else $st .= '

You are not authenticated or have not the needed privileges!

'; } else { self::log(Logger::ERROR, $e->getCode(), $e->getMessage()); $st .= 'Class: ' . get_class($e) . '
'; $st .= 'Code: ' . $e->getCode() . '
'; if(defined('DEBUG')) { $st .= 'Location: ' . $e->getFile() . ':' . $e->getLine() . '
'; $st .= 'Message: ' . htmlentities($e->getMessage()) . '
'; if($e instanceof \Mammut\DB\SQLException) { $st .= 'Query: ' . htmlentities($e->getQuery()) . '
'; if ($e->getParam()) $st .= 'Parameter: ' . htmlentities(print_r($e->getParam(), true)) . '
'; } $st .= '
Stacktrace
' . htmlentities($e->getTraceAsString()) . '
'; $subEx = $e; $round = 0; while(!is_null($subEx = $subEx->getPrevious()) && (++$round < 50)) $st .= '

Caused by ' . get_class($subEx) . ': ' . htmlentities($subEx->getMessage()) . '[' . $subEx->getFile() . ':' . $subEx->getLine() . ']

'; } else $st .= '

If you are a developer and need more information about this incident, define the DEBUG constant

'; } $layout = str_replace('', $title, $layout); $layout = str_replace('', $message, $layout); $st = str_replace('', $st, $layout); die($st); } /** * Optimized output on console * * @param \Exception $e * an exception */ protected function onExceptionCLI(\Exception $e) { $this->LOG->traceStart(); try { $this->writeError2DB($e); } catch(\Exception $sqlex) { echo 'Note: SQL-Logger reported another error:' . $sqlex->getMessage() . "\n"; $round = 0; $subEx = $sqlex; while(!is_null($subEx = $subEx->getPrevious()) && (++$round < 50)) echo 'Caused by ' . get_class($subEx) . ': ' . $subEx->getMessage() . '[' . $subEx->getFile() . ':' . $subEx->getLine() . "]\n"; echo "\nStacktrace of subexception:\n" . $sqlex->getTraceAsString() . "\n"; } if($e instanceof \ErrorException) { if(method_exists($e, 'getSeverity')) { switch($e->getSeverity()) { case E_ERROR: echo "Type: Error\n"; break; case E_WARNING: case E_USER_WARNING: echo "Type>: Warning\n"; break; case E_STRICT: echo "Type: Strict coding convention\n"; break; default: echo 'Type: unknown(' . $e->getSeverity() . ")\n"; break; } } else echo "Type: unknown\n"; } echo 'Class: ' . get_class($e) . "\n"; echo 'Code: ' . $e->getCode() . "\n"; if(defined('DEBUG')) { echo 'Location: ' . $e->getFile() . ':' . $e->getLine() . "\n"; echo 'Message: ' . $e->getMessage() . "\n"; if($e instanceof \Mammut\DB\SQLException) echo 'Query: ' . $e->getQuery() . "\n"; echo "\nStacktrace\n" . $e->getTraceAsString() . "\n"; $subEx = $e; $round = 0; while(!is_null($subEx = $subEx->getPrevious()) && (++$round < 50)) echo 'Caused by ' . get_class($subEx) . ': ' . $subEx->getMessage() . '[' . $subEx->getFile() . ':' . $subEx->getLine() . "]\n"; } else echo 'If you are a developer and need more information about this incident, define the DEBUG constant.' . "\n"; die(); } /** * Writes a log entry into the database * * @param \Exception $e * an exception */ protected function writeError2DB(\Exception $e) { $this->LOG->traceStart(); $db = self::getInstance()->getDB(); $data = new \stdClass(); $data->eventtime = new \DateTime(); $data->level = LOG_ERR; $data->area = 'system'; $data->areaname = NULL; $data->user = 0; $data->code = 0; $data->message = $e->getMessage(); if(strlen($data->message) > 254) $data->message = substr($data->message, 0, 254); $db->table('logs')->insert($data); $id = $db->getInsertId(); if($e instanceof \Mammut\DB\SQLException) { $data = new \stdClass(); $data->parent = $id; $data->eventtime = new \DateTime(); $data->level = LOG_ERR; $data->area = 'system'; $data->areaname = 'sql'; $data->user = 0; $data->code = 0; $data->readed = false; $data->message = '' . $e->getQuery(); if(strlen($data->message) > 254) $data->message = substr($data->message, 0, 254); $db->table('logs')->insert($data); } } public function getSiteLayout($siteId, $type = 'default') { $this->LOG->traceStart(); $t = new CTemplate(); $t->loadString(''); return $t; } /** * helper method which redirects the entry to the current system instance * * @param int $level an error constant * @param int $code an error code * @param mixed $message a representing the error */ public static function log($level, $code, $message) { Logger::getInstance(self::LOGNAME)->log($level, $message, NULL, array('code' => $code), 1); } }