HtmlFormat.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2020 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
12 
19 use wcmf\lib\util\StringUtil;
20 
21 /**
22  * HtmlFormat implements the HTML request/response format. Since all data
23  * from the external representation arrives in form fields, grouping of values
24  * has to be done via the field names. So Nodes are represented by their values
25  * whose field names are of the form value-`language`-`name`-`oid`. All of these
26  * values will be removed from the request and replaced by Node instances
27  * representing the data. Each node is stored under its object id in the data array.
28  *
29  * HtmlFormat serializes the response to a template, which will be rendered
30  * by the View implementation defined in the configuration section 'view'.
31  * The template is determined by the current action key. The response property
32  * 'html_tpl_format' allows to select a specific version of that template file. E.g.
33  * if the template would be home.tpl, setting the 'html_tpl_format' property
34  * to 'mobile' would select the template home-mobile.tpl. If a version does
35  * not exist, it is ignored and the default template is used.
36  *
37  * @author ingo herwig <ingo@wemove.com>
38  */
39 class HtmlFormat extends AbstractFormat {
40 
41  private static $inputFieldNameDelimiter = '-';
42  private static $sharedView = null;
43 
44  /**
45  * @see Format::getMimeType()
46  */
47  public function getMimeType(Response $response=null) {
48  return 'text/html';
49  }
50 
51  /**
52  * @see Format::isCached()
53  */
54  public function isCached(Response $response) {
55  if (self::$sharedView == null) {
56  self::$sharedView = ObjectFactory::getInstance('view');
57  }
58  $templateFile = $this->getTemplateFile($response);
59  $cacheId = $response->getCacheId();
60  return self::$sharedView->isCached($templateFile, $cacheId);
61  }
62 
63  /**
64  * @see Format::getCacheDate()
65  */
66  public function getCacheDate(Response $response) {
67  if (self::$sharedView == null) {
68  self::$sharedView = ObjectFactory::getInstance('view');
69  }
70  $templateFile = $this->getTemplateFile($response);
71  $cacheId = $response->getCacheId();
72  return self::$sharedView->getCacheDate($templateFile, $cacheId);
73  }
74 
75  /**
76  * @see AbstractFormat::deserializeValues()
77  */
78  protected function deserializeValues(Request $request) {
79  // construct nodes from values serialized as form fields
80  // nodes are encoded in separated fields with names value-<language>-<name>-<oid>
81  $values = $request->getValues();
82  foreach ($values as $key => $value) {
83  $valueDef = self::getValueDefFromInputControlName($key);
84  if ($valueDef != null) {
85  // fix oid parameter (PHP replaces dots by underscore)
86  $oidStr = preg_replace('/_/', '.', $valueDef['oid']);
87  $oid = ObjectId::parse($oidStr);
88  if ($oid) {
89  $node = &$this->getNode($oid);
90  $mapper = $node->getMapper();
91  $pkNames = $mapper->getPkNames();
92  $valueName = $valueDef['name'];
93  if ($mapper->hasAttribute($valueName) && !in_array($valueName, $pkNames)) {
94  $node->setValue($valueName, $value);
95  }
96  unset($values[$key]);
97  $values[$oidStr] = $node;
98  }
99  }
100  }
101  return $values;
102  }
103 
104  /**
105  * @see AbstractFormat::serializeValues()
106  */
107  protected function serializeValues(Response $response) {
108  // create the view
109  $view = ObjectFactory::getInstance('view');
110 
111  // assign the response data to the view
112  $values = $response->getValues();
113  foreach ($values as $key => $value) {
114  $view->setValue($key, $value);
115  }
116 
117  // display the view
118  $templateFile = $this->getTemplateFile($response);
119  $view->render($templateFile, $response->getCacheId(), $response->getCacheLifetime());
120 
121  return $values;
122  }
123 
124  /**
125  * Get the object value definition from a HTML input field name.
126  * @param $name The name of input field in the format value-`language`-`name`-`oid`, where name is the name
127  * of the attribute belonging to the node defined by oid
128  * @return An associative array with keys 'oid', 'language', 'name' or null if the name is not valid
129  */
130  protected static function getValueDefFromInputControlName($name) {
131  if (strpos($name, 'value') !== 0) {
132  return null;
133  }
134  $def = [];
135  $fieldDelimiter = StringUtil::escapeForRegex(self::$inputFieldNameDelimiter);
136  $pieces = preg_split('/'.$fieldDelimiter.'/', $name);
137  if (sizeof($pieces) != 4) {
138  return null;
139  }
140  array_shift($pieces);
141  $def['language'] = array_shift($pieces);
142  $def['name'] = array_shift($pieces);
143  $def['oid'] = array_shift($pieces);
144 
145  return $def;
146  }
147 
148  /**
149  * Get the template file for the given response
150  * @param $response
151  */
152  protected function getTemplateFile(Response $response) {
153  if (self::$sharedView == null) {
154  self::$sharedView = ObjectFactory::getInstance('view');
155  }
156  // check if a view template is defined, prefer template property over configuration
157  $viewTpl = $response->getProperty('html_tpl_file') !== null ? $response->getProperty('html_tpl_file') :
158  self::$sharedView->getTemplate($response->getSender(),
159  $response->getContext(), $response->getAction());
160  if (!$viewTpl) {
161  throw new ConfigurationException("View definition missing for ".
162  "response: ".$response->__toString());
163  }
164 
165  // check for html_format property in response
166  // and add the suffix if existing
167  $viewTplFile = WCMF_BASE.$viewTpl;
168  $format = $response->getProperty('html_tpl_format');
169  if (isset($format)) {
170  $ext = pathinfo($viewTplFile, PATHINFO_EXTENSION);
171  $formatViewTplFile = dirname($viewTplFile).'/'.basename($viewTplFile, ".$ext").'-'.$format.'.'.$ext;
172  }
173 
174  // give precedence to format specific file
175  $finalTplFile = isset($formatViewTplFile) && file_exists($formatViewTplFile) ?
176  $formatViewTplFile : $viewTplFile;
177  $response->setProperty('html_tpl', $finalTplFile);
178  return $finalTplFile;
179  }
180 }
181 ?>
Response holds the response values that are used as output from Controller instances.
Definition: Response.php:20
Request holds the request values that are used as input to Controller instances.
Definition: Request.php:18
HtmlFormat implements the HTML request/response format.
Definition: HtmlFormat.php:39
getSender()
Get the name of the sending Controller.
getCacheId()
Get the cache id.
getValues()
Get all key value pairs.
getContext()
Get the name of the context.
ObjectId is the unique identifier of an object.
Definition: ObjectId.php:27
getAction()
Get the name of the action.
ConfigurationException signals an exception in the configuration.
static getValueDefFromInputControlName($name)
Get the object value definition from a HTML input field name.
Definition: HtmlFormat.php:130
static parse($oid)
Parse a serialized object id string into an ObjectId instance.
Definition: ObjectId.php:134
getTemplateFile(Response $response)
Get the template file for the given response.
Definition: HtmlFormat.php:152
setProperty($name, $value)
Set a property.
static getInstance($name, $dynamicConfiguration=[])
getCacheLifetime()
Get the lifetime of a cached response.
ObjectFactory implements the service locator pattern by wrapping a Factory instance and providing sta...
AbstractFormat is used as base class for specialized formats.