1. sfViewConfigHandler.class.php
  2. /** * sfViewConfigHandler allows you to configure views. * * @package symfony * @subpackage config * @author Fabien Potencier * @version SVN: $Id: sfViewConfigHandler.class.php 23810 2009-11-12 11:07:44Z Kris.Wallsmith $ */
  3. class sfViewConfigHandler extends sfYamlConfigHandler
  4. {
  5. /**
  6. * Executes this configuration handler.
  7. *
  8. * @param array $configFiles An array of absolute filesystem path to a configuration file
  9. *
  10. * @return string Data to be written to a cache file
  11. *
  12. * @throws <b>sfConfigurationException</b> If a requested configuration file does not exist or is not readable
  13. * @throws <b>sfParseException</b> If a requested configuration file is improperly formatted
  14. * @throws <b>sfInitializationException</b> If a view.yml key check fails
  15. */
  16. public function execute($configFiles)
  17. {
  18. // parse the yaml
  19. $this->yamlConfig = self::getConfiguration($configFiles);
  20. // init our data array
  21. $data = array();
  22. $data[] = "\$response = \$this->context->getResponse();\n\n";
  23. // first pass: iterate through all view names to determine the real view name
  24. $first = true;
  25. foreach ($this->yamlConfig as $viewName => $values)
  26. {
  27. if ($viewName == 'all')
  28. {
  29. continue;
  30. }
  31. $data[] = ($first ? '' : 'else ')."if (\$this->actionName.\$this->viewName == '$viewName')\n".
  32. "{\n";
  33. $data[] = $this->addTemplate($viewName);
  34. $data[] = "}\n";
  35. $first = false;
  36. }
  37. // general view configuration
  38. $data[] = ($first ? '' : "else\n{")."\n";
  39. $data[] = $this->addTemplate($viewName);
  40. $data[] = ($first ? '' : "}")."\n\n";
  41. // second pass: iterate through all real view names
  42. $first = true;
  43. foreach ($this->yamlConfig as $viewName => $values)
  44. {
  45. if ($viewName == 'all')
  46. {
  47. continue;
  48. }
  49. $data[] = ($first ? '' : 'else ')."if (\$templateName.\$this->viewName == '$viewName')\n".
  50. "{\n";
  51. $data[] = $this->addLayout($viewName);
  52. $data[] = $this->addComponentSlots($viewName);
  53. $data[] = $this->addHtmlHead($viewName);
  54. $data[] = $this->addEscaping($viewName);
  55. $data[] = $this->addHtmlAsset($viewName);
  56. $data[] = "}\n";
  57. $first = false;
  58. }
  59. // general view configuration
  60. $data[] = ($first ? '' : "else\n{")."\n";
  61. $data[] = $this->addLayout();
  62. $data[] = $this->addComponentSlots();
  63. $data[] = $this->addHtmlHead();
  64. $data[] = $this->addEscaping();
  65. $data[] = $this->addHtmlAsset();
  66. $data[] = ($first ? '' : "}")."\n";
  67. // compile data
  68. $retval = sprintf("<?php\n".
  69. "// auto-generated by sfViewConfigHandler\n".
  70. "// date: %s\n%s\n",
  71. date('Y/m/d H:i:s'), implode('', $data));
  72. return $retval;
  73. }
  74. /**
  75. * Adds a component slot statement to the data.
  76. *
  77. * @param string $viewName The view name
  78. *
  79. * @return string The PHP statement
  80. */
  81. protected function addComponentSlots($viewName = '')
  82. {
  83. $data = '';
  84. $components = $this->mergeConfigValue('components', $viewName);
  85. foreach ($components as $name => $component)
  86. {
  87. if (!is_array($component) || count($component) < 1)
  88. {
  89. $component = array(null, null);
  90. }
  91. $data .= " \$this->setComponentSlot('$name', '{$component[0]}', '{$component[1]}');\n";
  92. $data .= " if (sfConfig::get('sf_logging_enabled')) \$this->context->getEventDispatcher()->notify(new sfEvent(\$this, 'application.log', array(sprintf('Set component \"%s\" (%s/%s)', '$name', '{$component[0]}', '{$component[1]}'))));\n";
  93. }
  94. return $data;
  95. }
  96. /**
  97. * Adds a template setting statement to the data.
  98. *
  99. * @param string $viewName The view name
  100. *
  101. * @return string The PHP statement
  102. */
  103. protected function addTemplate($viewName = '')
  104. {
  105. $data = '';
  106. $templateName = $this->getConfigValue('template', $viewName);
  107. $defaultTemplateName = $templateName ? "'$templateName'" : '$this->actionName';
  108. $data .= " \$templateName = sfConfig::get('symfony.view.'.\$this->moduleName.'_'.\$this->actionName.'_template', $defaultTemplateName);\n";
  109. $data .= " \$this->setTemplate(\$templateName.\$this->viewName.\$this->getExtension());\n";
  110. return $data;
  111. }
  112. /**
  113. * Adds a layout statement statement to the data.
  114. *
  115. * @param string $viewName The view name
  116. *
  117. * @return string The PHP statement
  118. */
  119. protected function addLayout($viewName = '')
  120. {
  121. // true if the user set 'has_layout' to true or set a 'layout' name for this specific action
  122. $hasLocalLayout = isset($this->yamlConfig[$viewName]['layout']) || (isset($this->yamlConfig[$viewName]) && array_key_exists('has_layout', $this->yamlConfig[$viewName]));
  123. // the layout value
  124. $layout = $this->getConfigValue('has_layout', $viewName) ? $this->getConfigValue('layout', $viewName) : false;
  125. // the user set a decorator in the action
  126. $data = <<<EOF
  127. if (null !== \$layout = sfConfig::get('symfony.view.'.\$this->moduleName.'_'.\$this->actionName.'_layout'))
  128. {
  129. \$this->setDecoratorTemplate(false === \$layout ? false : \$layout.\$this->getExtension());
  130. }
  131. EOF;
  132. if ($hasLocalLayout)
  133. {
  134. // the user set a decorator in view.yml for this action
  135. $data .= <<<EOF
  136. else
  137. {
  138. \$this->setDecoratorTemplate('' == '$layout' ? false : '$layout'.\$this->getExtension());
  139. }
  140. EOF;
  141. }
  142. else
  143. {
  144. // no specific configuration
  145. // set the layout to the 'all' view.yml value except if:
  146. // * the decorator template has already been set by "someone" (via view.configure_format for example)
  147. // * the request is an XMLHttpRequest request
  148. $data .= <<<EOF
  149. else if (null === \$this->getDecoratorTemplate() && !\$this->context->getRequest()->isXmlHttpRequest())
  150. {
  151. \$this->setDecoratorTemplate('' == '$layout' ? false : '$layout'.\$this->getExtension());
  152. }
  153. EOF;
  154. }
  155. return $data;
  156. }
  157. /**
  158. * Adds http metas and metas statements to the data.
  159. *
  160. * @param string $viewName The view name
  161. *
  162. * @return string The PHP statement
  163. */
  164. protected function addHtmlHead($viewName = '')
  165. {
  166. $data = array();
  167. foreach ($this->mergeConfigValue('http_metas', $viewName) as $httpequiv => $content)
  168. {
  169. $data[] = sprintf(" \$response->addHttpMeta('%s', '%s', false);", $httpequiv, str_replace('\'', '\\\'', $content));
  170. }
  171. foreach ($this->mergeConfigValue('metas', $viewName) as $name => $content)
  172. {
  173. $data[] = sprintf(" \$response->addMeta('%s', '%s', false, false);", $name, str_replace('\'', '\\\'', preg_replace('/&amp;(?=\w+;)/', '&', htmlspecialchars($content, ENT_QUOTES, sfConfig::get('sf_charset')))));
  174. }
  175. return implode("\n", $data)."\n";
  176. }
  177. /**
  178. * Adds stylesheets and javascripts statements to the data.
  179. *
  180. * @param string $viewName The view name
  181. *
  182. * @return string The PHP statement
  183. */
  184. protected function addHtmlAsset($viewName = '')
  185. {
  186. // Merge the current view's stylesheets with the app's default stylesheets
  187. $stylesheets = $this->mergeConfigValue('stylesheets', $viewName);
  188. $css = $this->addAssets('Stylesheet', $stylesheets);
  189. // Merge the current view's javascripts with the app's default javascripts
  190. $javascripts = $this->mergeConfigValue('javascripts', $viewName);
  191. $js = $this->addAssets('Javascript', $javascripts);
  192. return implode("\n", array_merge($css, $js))."\n";
  193. }
  194. /**
  195. * Creates a list of add$Type PHP statements for the given type and config.
  196. *
  197. * @param string $type of asset. Requires an sfWebResponse->add$Type(string, string, array) method
  198. *
  199. * @return array ist of add$Type PHP statements
  200. */
  201. private function addAssets($type, $assets){
  202. $tmp = array();
  203. foreach ((array) $assets as $asset)
  204. {
  205. $position = '';
  206. if (is_array($asset))
  207. {
  208. $key = key($asset);
  209. $options = $asset[$key];
  210. if (isset($options['position']))
  211. {
  212. $position = $options['position'];
  213. unset($options['position']);
  214. }
  215. }
  216. else
  217. {
  218. $key = $asset;
  219. $options = array();
  220. }
  221. if ('-*' == $key)
  222. {
  223. $tmp = array();
  224. }
  225. else if ('-' == $key[0])
  226. {
  227. unset($tmp[substr($key, 1)]);
  228. }
  229. else
  230. {
  231. $tmp[$key] = sprintf(" \$response->add%s('%s', '%s', %s);", $type, $key, $position, str_replace("\n", '', var_export($options, true)));
  232. }
  233. }
  234. return array_values($tmp);
  235. }
  236. /**
  237. * Adds an escaping statement to the data.
  238. *
  239. * @param string $viewName The view name
  240. *
  241. * @return string The PHP statement
  242. */
  243. protected function addEscaping($viewName = '')
  244. {
  245. $data = array();
  246. $escaping = $this->getConfigValue('escaping', $viewName);
  247. if (isset($escaping['method']))
  248. {
  249. $data[] = sprintf(" \$this->getAttributeHolder()->setEscapingMethod(%s);", var_export($escaping['method'], true));
  250. }
  251. return implode("\n", $data)."\n";
  252. }
  253. /**
  254. * @see sfConfigHandler
  255. */
  256. static public function getConfiguration(array $configFiles)
  257. {
  258. return self::mergeConfig(self::parseYamls($configFiles));
  259. }
  260. static protected function mergeConfig($config)
  261. {
  262. // merge javascripts and stylesheets
  263. $config['all']['stylesheets'] = array_merge(isset($config['default']['stylesheets']) && is_array($config['default']['stylesheets']) ? $config['default']['stylesheets'] : array(), isset($config['all']['stylesheets']) && is_array($config['all']['stylesheets']) ? $config['all']['stylesheets'] : array());
  264. unset($config['default']['stylesheets']);
  265. $config['all']['javascripts'] = array_merge(isset($config['default']['javascripts']) && is_array($config['default']['javascripts']) ? $config['default']['javascripts'] : array(), isset($config['all']['javascripts']) && is_array($config['all']['javascripts']) ? $config['all']['javascripts'] : array());
  266. unset($config['default']['javascripts']);
  267. // merge default and all
  268. $config['all'] = sfToolkit::arrayDeepMerge(
  269. isset($config['default']) && is_array($config['default']) ? $config['default'] : array(),
  270. isset($config['all']) && is_array($config['all']) ? $config['all'] : array()
  271. );
  272. unset($config['default']);
  273. return self::replaceConstants($config);
  274. }
  275. }

Debug toolbar