openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit d42b3574469f24d754246c6ff2b9d7875e73b220
parent 488408be1e6b67dae7a0904bdf508929f0bac88c
Author: dankert <openrat@jandankert.de>
Date:   Sun, 13 Feb 2022 23:35:26 +0100

Refactoring: New class "Response" which stores all output information.

Diffstat:
Mmodules/cms/Dispatcher.class.php | 44+++++++++++++++++++++++++-------------------
Mmodules/cms/action/Action.class.php | 113++++++++++++++++++++++---------------------------------------------------------
Amodules/cms/action/Response.class.php | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmodules/cms/action/file/FileShowAction.class.php | 18+++++++++---------
Mmodules/cms/action/folder/FolderShowAction.class.php | 8++++----
Mmodules/cms/action/link/LinkShowAction.class.php | 8++++----
Mmodules/cms/action/login/LoginOidcAction.class.php | 2+-
Mmodules/cms/action/page/PageShowAction.class.php | 6+++---
Mmodules/cms/action/template/TemplateShowAction.class.php | 2+-
Mmodules/cms/action/url/UrlShowAction.class.php | 8++++----
Mmodules/cms/output/BaseOutput.class.php | 18++++++++++++++----
Mmodules/cms/ui/action/index/IndexShowAction.class.php | 2+-
12 files changed, 220 insertions(+), 132 deletions(-)

diff --git a/modules/cms/Dispatcher.class.php b/modules/cms/Dispatcher.class.php @@ -8,6 +8,7 @@ namespace cms; use BadMethodCallException; use cms\action\Action; use cms\action\RequestParams; +use cms\action\Response; use cms\auth\Auth; use cms\auth\InternalAuth; use cms\base\Configuration; @@ -51,13 +52,16 @@ class Dispatcher /** * @var RequestParams */ - public $request; + private $request; + + /** + * @var Response + */ + private $response; /** * Vollständige Abarbeitug einer Aktion. * Führt die gesamte Abarbeitung einer Aktion durch, incl. Datenbank-Transaktionssteuerung. - * - * @return array data for the client */ public function doAction() { @@ -105,8 +109,7 @@ class Dispatcher $this->checkLogin(); try{ - - $result = $this->callActionMethod(); + $this->callActionMethod(); } catch(Exception $e) { @@ -127,24 +130,28 @@ class Dispatcher $this->commitDatabaseTransaction(); if ( DEVELOPMENT ) - Logger::trace('Output' . "\n" . print_r($result, true)); - - // Weitere Variablen anreichern. - $result['session'] = array('name' => session_name(), 'id' => session_id(), 'token' => Session::token()); - $result['version'] = Startup::VERSION; - $result['api'] = Startup::API_LEVEL; - $result['output']['_token'] = Session::token(); - $result['output']['_id' ] = $this->request->id; + Logger::info('Output' . "\n" . print_r( $this->response->getOutputData(),true)); // Ablaufzeit für den Inhalt auf aktuelle Zeit setzen. - header('Expires: ' . substr(date('r', time() - date('Z')), 0, -5) . 'GMT', false); - - return $result; + if ( !$this->response->hasHeader('Expires') ) + $this->response->addHeader('Expires', substr(date('r', time() - date('Z')), 0, -5) . 'GMT', false); } /** + * @param $request RequestParams + * @param $response Response + */ + public function setRequestAndResponse($request, $response) + { + $this->request = $request; + $this->response = $response; + } + + + + /** * Clear up after the work is done. */ private function clear() { @@ -318,7 +325,7 @@ class Dispatcher /** * Aufruf der Action-Methode. * - * @return array Vollständige Rückgabe aller Daten als assoziatives Array + * @return Response Vollständige Rückgabe aller Daten */ private function callActionMethod() { @@ -355,6 +362,7 @@ class Dispatcher $do = new $class; $do->request = $this->request; + $do->response = $this->response; $do->init(); $do->checkAccess(); @@ -397,8 +405,6 @@ class Dispatcher // The action is able to change its method name. $this->request = $do->request; $this->request->action = $action; - - return $do->getOutputData(); } /** diff --git a/modules/cms/action/Action.class.php b/modules/cms/action/Action.class.php @@ -40,14 +40,12 @@ abstract class Action abstract function checkAccess(); - protected $errors = []; - protected $notices = []; - protected $output = []; - protected $status = Action::NOTICE_OK; - protected $success = true; - - protected $templateVars = [ - ]; + /** + * The Response to the actual request. + * + * @var Response + */ + public $response; /** * Current user. @@ -57,7 +55,7 @@ abstract class Action public $currentUser; /** - * Request + * Request. * * @var RequestParams */ @@ -76,6 +74,7 @@ abstract class Action public function __construct() { $this->currentUser = Session::getUser(); + $this->response = new Response(); } @@ -88,7 +87,7 @@ abstract class Action */ protected function setTemplateVar($varName, $value) { - $this->output[ $varName ] = $value; + $this->response->addOutput( $varName, $value ); } @@ -99,11 +98,21 @@ abstract class Action */ protected function setTemplateVars($varList) { - $this->output += $varList; + $this->response->addOutputList( $varList ); } /** + * Adding a HTTP header. + * + * @param $name + * @param $value + */ + protected function addHeader( $name, $value ) { + $this->response->addHeader( $name, $value ); + } + + /** * F�gt einen Validierungsfehler hinzu. * * @param String $name Name des validierten Eingabefeldes @@ -114,7 +123,7 @@ abstract class Action if ( ! empty($message) ) $this->addErrorFor( null, $message, $vars ); - $this->errors[] = $name; + $this->response->addError( $name ); } @@ -173,58 +182,13 @@ abstract class Action $name = ''; } - $this->addNotice($type,$id,$name, $key, $noticeType, $vars, $message); + $this->response->addNotice($type,$id,$name, $key, $noticeType, $vars, $message); } - /** - * F�gt ein Meldung hinzu. - * - * @param String $type Typ des Objektes, zu dem diese Meldung geh�rt. - * @param $id - * @param String $name Name des Objektes, zu dem diese Meldung geh�rt. - * @param String $text Textschl�ssel der Fehlermeldung (optional) - * @param String $status Einer der Werte Action::NOTICE_(OK|WARN|ERROR) - * @param array $vars Variablen f�r den Textschl�ssel - * @param string|array $log Weitere Hinweistexte f�r diese Meldung. - */ - private function addNotice($type, $id, $name, $text, $status = Action::NOTICE_OK, $vars = array(), $log = array()) - { - $this->status = ($status == Action::NOTICE_ERROR) ? Action::NOTICE_ERROR : $status; - $this->success = $this->success && $status != Action::NOTICE_ERROR; - - if ( is_array($log) ) - $log = implode("\n",$log); - - $vars = (array) $vars; - - $this->notices[] = [ - 'type' => $type, - 'id' => $id , - 'name' => $name, - 'key' => $text, - 'vars' => $vars, - 'text' => L::lang($text, $vars), - 'log' => $log , - 'status' => $status]; - } - - /** - * Getting the output data. - * - * @return array[] - */ - public function getOutputData() - { - return [ - 'output' => $this->output, // output data - 'notices' => $this->notices, // notices - 'errors' => $this->errors, // fieldnames with validation errors - 'status' => $this->status, // notice status - 'notice_status' => $this->status, // same as above, historical reasons - 'success' => $this->success, // success, true if there are no errors and no notices with status error. - ]; + public function getResponse() { + return $this->response; } @@ -298,18 +262,18 @@ abstract class Action $etag = '"' . base_convert($time, 10, 36) . '"'; // a short representation of the unix timestamp. // Header senden - header('Expires: ' . $expires); - header('Last-Modified: ' . $lastModified); - header('ETag: ' . $etag); + $this->addHeader('Expires' , $expires); + $this->addHeader('Last-Modified' , $lastModified); + $this->addHeader('ETag' , $etag); // Die vom Interpreter sonst automatisch gesetzten // Header uebersteuern - header('Cache-Control: must-revalidate'); - header('Pragma:'); + $this->addHeader('Cache-Control','must-revalidate'); + $this->addHeader('Pragma' ,''); // See if the client has provided the required headers $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false; - $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : false; + $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH'] ) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH' ]) : false; // Bug in Apache 2.2, mod_deflat adds '-gzip' to E-Tag if (substr($if_none_match, -6) == '-gzip"') @@ -326,27 +290,12 @@ abstract class Action return; // Der entfernte Browser bzw. Proxy holt die Seite nun aus seinem Cache - header('HTTP/1.0 304 Not Modified'); + $this->addHeader('HTTP/1.0 304 Not Modified'); exit; // Sofortiges Skript-Ende } /** - * @param $max int max Anzahl der Sekunden, die die Seite im Browsercache bleiben darf - */ - protected function maxAge($max = 3600) - { - // Die Header "Last-Modified" und "ETag" wurden bereits in der - // Methode "lastModified()" gesetzt. - - header('Expires: ' . substr(date('r', time() - date('Z') + $max), 0, -5) . 'GMT'); - header('Pragma: '); // 'Pragma' ist Bullshit und - // wird von den meisten Browsern ignoriert. - header('Cache-Control: public, max-age=' . $max . ", s-maxage=" . $max); - } - - - /** * Language ISO code. */ const COOKIE_LANGUAGE = 'or_language'; diff --git a/modules/cms/action/Response.class.php b/modules/cms/action/Response.class.php @@ -0,0 +1,122 @@ +<?php + +namespace cms\action; + +use cms\base\Language as L; +use cms\base\Startup; +use util\Session; + +/** + * Response. + */ +class Response +{ + protected $header = []; + + protected $errors = []; + protected $notices = []; + protected $output = []; + protected $status = Action::NOTICE_OK; + public $success = true; + + public function addHeader( $name, $value ) { + $this->header[$name] = $value; + } + + + public function addOutput( $name, $value ) { + $this->output[$name] = $value; + } + public function addOutputList( $list ) { + $this->output += $list; + } + + + /** + * Getting the response data as an array. + * + * @return array + */ + public function getOutputData() + { + return [ + 'output' => $this->output + [ + '_token' => Session::token(), + //'_id' => $this->request->id, + ], + 'notices' => $this->notices, // notices + 'errors' => $this->errors, // fieldnames with validation errors + 'status' => $this->status, // notice status + 'notice_status' => $this->status, // same as above, historical reasons + 'success' => $this->success, // success, true if there are no errors and no notices with status error. + 'session' => [ + 'name' => session_name(), + 'id' => session_id(), + 'token' => Session::token() + ], + 'version' => Startup::VERSION, + 'api' => Startup::API_LEVEL, + ]; + } + + + public function __toString() + { + return print_r( $this->getOutputData(),true); + } + + /** + * Outputs all HTTP reponse headers. + */ + public function setHTTPHeader() { + foreach( $this->header as $name=>$value ) { + header( $name.': '.$value ); + } + } + + + /** + * F�gt ein Meldung hinzu. + * + * @param String $type Typ des Objektes, zu dem diese Meldung geh�rt. + * @param $id + * @param String $name Name des Objektes, zu dem diese Meldung geh�rt. + * @param String $text Textschl�ssel der Fehlermeldung (optional) + * @param String $status Einer der Werte Action::NOTICE_(OK|WARN|ERROR) + * @param array $vars Variablen f�r den Textschl�ssel + * @param string|array $log Weitere Hinweistexte f�r diese Meldung. + */ + public function addNotice($type, $id, $name, $text, $status = Action::NOTICE_OK, $vars = array(), $log = array()) + { + $this->status = ($status == Action::NOTICE_ERROR) ? Action::NOTICE_ERROR : $status; + $this->success = $this->success && $status != Action::NOTICE_ERROR; + + if ( is_array($log) ) + $log = implode("\n",$log); + + $vars = (array) $vars; + + $this->notices[] = [ + 'type' => $type, + 'id' => $id , + 'name' => $name, + 'key' => $text, + 'vars' => $vars, + 'text' => L::lang($text, $vars), + 'log' => $log , + 'status' => $status]; + } + + + + public function addError( $errorField ) { + $this->errors[] = $errorField; + } + + + public function hasHeader($string) + { + return array_key_exists($string , $this->header ); + } + +} +\ No newline at end of file diff --git a/modules/cms/action/file/FileShowAction.class.php b/modules/cms/action/file/FileShowAction.class.php @@ -47,28 +47,28 @@ class FileShowAction extends FileAction implements Method { $mime_type = File::$MIME_TYPES[$ext]; - header('Content-Type: '.$mime_type ); - header('Content-Encoding: gzip' ); + $this->addHeader('Content-Type',$mime_type ); + $this->addHeader('Content-Encoding','gzip' ); } else { // Angabe Content-Type - header('Content-Type: '.$generator->getMimeType() ); + $this->addHeader('Content-Type',$generator->getMimeType() ); } - header('X-File-Id: ' .$this->file->fileid ); - header('X-Id: ' .$this->file->objectid ); + $this->addHeader('X-File-Id',$this->file->fileid ); + $this->addHeader('X-Id' ,$this->file->objectid ); // Image should be displayed inline. // Filename is used if the user agent is saving the file. - header('Content-Disposition: inline; filename='.$this->file->filename() ); - header('Content-Transfer-Encoding: binary' ); - header('Content-Description: '.$this->file->filename() ); + $this->addHeader('Content-Disposition' ,'inline; filename='.$this->file->filename() ); + $this->addHeader('Content-Transfer-Encoding','binary' ); + $this->addHeader('Content-Description' ,$this->file->filename() ); // Groesse des Bildes in Bytes // Der Browser hat so die Moeglichkeit, einen Fortschrittsbalken zu zeigen - header('Content-Length: '.$this->file->size ); + $this->addHeader('Content-Length',$this->file->size ); if ( $this->request->getAlphanum('encoding') == 'base64') diff --git a/modules/cms/action/folder/FolderShowAction.class.php b/modules/cms/action/folder/FolderShowAction.class.php @@ -11,11 +11,11 @@ class FolderShowAction extends FolderAction implements Method { public function view() { // Angabe Content-Type - header('Content-Type: text/html' ); + $this->addHeader('Content-Type','text/html' ); - header('X-Folder-Id: ' .$this->folder->folderid ); - header('X-Id: ' .$this->folder->objectid ); - header('Content-Description: '.$this->folder->filename() ); + $this->addHeader('X-Folder-Id' ,$this->folder->folderid ); + $this->addHeader('X-Id' ,$this->folder->objectid ); + $this->addHeader('Content-Description',$this->folder->filename() ); echo '<html><body>'; echo '<h1>'.$this->folder->filename.'</h1>'; diff --git a/modules/cms/action/link/LinkShowAction.class.php b/modules/cms/action/link/LinkShowAction.class.php @@ -9,11 +9,11 @@ use util\Html; class LinkShowAction extends LinkAction implements Method { public function view() { - header('Content-Type: text/html' ); + $this->addHeader('Content-Type','text/html' ); - header('X-Link-Id: ' .$this->link->linkid ); - header('X-Id: ' .$this->link->objectid ); - header('Content-Description: '.$this->link->filename() ); + $this->addHeader('X-Link-Id' ,$this->link->linkid ); + $this->addHeader('X-Id' ,$this->link->objectid ); + $this->addHeader('Content-Description',$this->link->filename() ); echo '<html><body>'; echo '<h1>'.$this->link->filename.'</h1>'; diff --git a/modules/cms/action/login/LoginOidcAction.class.php b/modules/cms/action/login/LoginOidcAction.class.php @@ -66,7 +66,7 @@ class LoginOidcAction extends LoginAction implements Method { throw new \RuntimeException('OpenId-Connect authentication failed',0,$e); } - header( 'Location: ./'); + $this->addHeader( 'Location','./'); } diff --git a/modules/cms/action/page/PageShowAction.class.php b/modules/cms/action/page/PageShowAction.class.php @@ -16,7 +16,7 @@ class PageShowAction extends PageAction implements Method { // The output is only shown in an iframe, so there is no security impact to the CMS. // But if the template is using inline JS or CSS, we would break this with a CSP-header. $pageSettingsConfig = new Config( $this->page->getTotalSettings() ); - header('Content-Security-Policy: '.$pageSettingsConfig->get('content-security-policy','') ); + $this->addHeader('Content-Security-Policy',$pageSettingsConfig->get('content-security-policy','') ); $this->page->load(); @@ -28,11 +28,11 @@ class PageShowAction extends PageAction implements Method { // HTTP-Header mit Sprachinformation setzen. $language = new Language( $pageContext->languageId); $language->load(); - header('Content-Language: '.$language->isoCode); + $this->addHeader('Content-Language',$language->isoCode); $generator = new PageGenerator( $pageContext ); - header('Content-Type: '.$generator->getMimeType().'; charset=UTF-8' ); + $this->addHeader('Content-Type',$generator->getMimeType().'; charset=UTF-8' ); $template = new Template( $this->page->templateid ); diff --git a/modules/cms/action/template/TemplateShowAction.class.php b/modules/cms/action/template/TemplateShowAction.class.php @@ -17,7 +17,7 @@ class TemplateShowAction extends TemplateAction implements Method { $templatemodel = new TemplateModel($this->template->templateid, $modelId); $templatemodel->load(); - header('Content-Type: '.$templatemodel->mimeType().'; charset=UTF-8' ); + $this->addHeader('Content-Type',$templatemodel->mimeType().'; charset=UTF-8' ); $text = $templatemodel->src; foreach( $this->template->getElementIds() as $elid ) diff --git a/modules/cms/action/url/UrlShowAction.class.php b/modules/cms/action/url/UrlShowAction.class.php @@ -9,11 +9,11 @@ class UrlShowAction extends UrlAction implements Method { public function view() { // Angabe Content-Type - header('Content-Type: text/html' ); + $this->addHeader('Content-Type','text/html' ); - header('X-Url-Id: ' .$this->url->urlid ); - header('X-Id: ' .$this->url->objectid ); - header('Content-Description: '.$this->url->filename() ); + $this->addHeader('X-Url-Id' ,$this->url->urlid ); + $this->addHeader('X-Id' ,$this->url->objectid ); + $this->addHeader('Content-Description',$this->url->filename() ); echo '<html><body>'; echo '<h1>'.$this->url->filename.'</h1>'; diff --git a/modules/cms/output/BaseOutput.class.php b/modules/cms/output/BaseOutput.class.php @@ -4,6 +4,7 @@ namespace cms\output; use BadMethodCallException; use cms\action\RequestParams; +use cms\action\Response; use cms\base\Language as L; use cms\Dispatcher; use Exception; @@ -19,6 +20,13 @@ use util\exception\SecurityException; */ abstract class BaseOutput implements Output { + /** + * Outputting the data to the client. + * Must be overwritten by subclasses. + * @param $request Request + * @param $data data data array + * @return void + */ abstract protected function outputData($request, $data); /** @@ -26,7 +34,8 @@ abstract class BaseOutput implements Output */ public function execute() { - $request = new RequestParams(); + $request = new RequestParams(); + $response = new Response(); try { $this->beforeAction( $request ); @@ -36,11 +45,12 @@ abstract class BaseOutput implements Output $request->isUIAction = true; $dispatcher = new Dispatcher(); - $dispatcher->request = $request; + $dispatcher->setRequestAndResponse( $request,$response ); - $data = $dispatcher->doAction(); // calling the action ... + $dispatcher->doAction(); // calling the action ... + $response->setHTTPHeader(); - $this->outputData( $request,$data ); // ... and output the data + $this->outputData( $request,$response->getOutputData() ); // ... and output the data } catch (BadMethodCallException $e) { // Action-Method does not exist. diff --git a/modules/cms/ui/action/index/IndexShowAction.class.php b/modules/cms/ui/action/index/IndexShowAction.class.php @@ -75,7 +75,7 @@ class IndexShowAction extends IndexAction implements Method { $this->setTemplateVar('favicon_url', C::subset('theme')->get('favicon','modules/cms/ui/themes/default/images/openrat-logo.ico') ); - $vars = $this->getOutputData(); + $vars = $this->getResponse()->getOutputData(); $this->setTemplateVar( 'notices',$vars['notices'] ); // will be extracted in the included template file. $this->setTemplateVar( 'charset','UTF-8' );