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:
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' );