View.php (8403B)
1 <?php 2 /** 3 * Slim - a micro PHP 5 framework 4 * 5 * @author Josh Lockhart <info@slimframework.com> 6 * @copyright 2011 Josh Lockhart 7 * @link http://www.slimframework.com 8 * @license http://www.slimframework.com/license 9 * @version 2.4.2 10 * @package Slim 11 * 12 * MIT LICENSE 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining 15 * a copy of this software and associated documentation files (the 16 * "Software"), to deal in the Software without restriction, including 17 * without limitation the rights to use, copy, modify, merge, publish, 18 * distribute, sublicense, and/or sell copies of the Software, and to 19 * permit persons to whom the Software is furnished to do so, subject to 20 * the following conditions: 21 * 22 * The above copyright notice and this permission notice shall be 23 * included in all copies or substantial portions of the Software. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 */ 33 namespace Slim; 34 35 /** 36 * View 37 * 38 * The view is responsible for rendering a template. The view 39 * should subclass \Slim\View and implement this interface: 40 * 41 * public render(string $template); 42 * 43 * This method should render the specified template and return 44 * the resultant string. 45 * 46 * @package Slim 47 * @author Josh Lockhart 48 * @since 1.0.0 49 */ 50 class View 51 { 52 /** 53 * Data available to the view templates 54 * @var \Slim\Helper\Set 55 */ 56 protected $data; 57 58 /** 59 * Path to templates base directory (without trailing slash) 60 * @var string 61 */ 62 protected $templatesDirectory; 63 64 /** 65 * Constructor 66 */ 67 public function __construct() 68 { 69 $this->data = new \Slim\Helper\Set(); 70 } 71 72 /******************************************************************************** 73 * Data methods 74 *******************************************************************************/ 75 76 /** 77 * Does view data have value with key? 78 * @param string $key 79 * @return boolean 80 */ 81 public function has($key) 82 { 83 return $this->data->has($key); 84 } 85 86 /** 87 * Return view data value with key 88 * @param string $key 89 * @return mixed 90 */ 91 public function get($key) 92 { 93 return $this->data->get($key); 94 } 95 96 /** 97 * Set view data value with key 98 * @param string $key 99 * @param mixed $value 100 */ 101 public function set($key, $value) 102 { 103 $this->data->set($key, $value); 104 } 105 106 /** 107 * Set view data value as Closure with key 108 * @param string $key 109 * @param mixed $value 110 */ 111 public function keep($key, \Closure $value) 112 { 113 $this->data->keep($key, $value); 114 } 115 116 /** 117 * Return view data 118 * @return array 119 */ 120 public function all() 121 { 122 return $this->data->all(); 123 } 124 125 /** 126 * Replace view data 127 * @param array $data 128 */ 129 public function replace(array $data) 130 { 131 $this->data->replace($data); 132 } 133 134 /** 135 * Clear view data 136 */ 137 public function clear() 138 { 139 $this->data->clear(); 140 } 141 142 /******************************************************************************** 143 * Legacy data methods 144 *******************************************************************************/ 145 146 /** 147 * DEPRECATION WARNING! This method will be removed in the next major point release 148 * 149 * Get data from view 150 */ 151 public function getData($key = null) 152 { 153 if (!is_null($key)) { 154 return isset($this->data[$key]) ? $this->data[$key] : null; 155 } else { 156 return $this->data->all(); 157 } 158 } 159 160 /** 161 * DEPRECATION WARNING! This method will be removed in the next major point release 162 * 163 * Set data for view 164 */ 165 public function setData() 166 { 167 $args = func_get_args(); 168 if (count($args) === 1 && is_array($args[0])) { 169 $this->data->replace($args[0]); 170 } elseif (count($args) === 2) { 171 // Ensure original behavior is maintained. DO NOT invoke stored Closures. 172 if (is_object($args[1]) && method_exists($args[1], '__invoke')) { 173 $this->data->set($args[0], $this->data->protect($args[1])); 174 } else { 175 $this->data->set($args[0], $args[1]); 176 } 177 } else { 178 throw new \InvalidArgumentException('Cannot set View data with provided arguments. Usage: `View::setData( $key, $value );` or `View::setData([ key => value, ... ]);`'); 179 } 180 } 181 182 /** 183 * DEPRECATION WARNING! This method will be removed in the next major point release 184 * 185 * Append data to view 186 * @param array $data 187 */ 188 public function appendData($data) 189 { 190 if (!is_array($data)) { 191 throw new \InvalidArgumentException('Cannot append view data. Expected array argument.'); 192 } 193 $this->data->replace($data); 194 } 195 196 /******************************************************************************** 197 * Resolve template paths 198 *******************************************************************************/ 199 200 /** 201 * Set the base directory that contains view templates 202 * @param string $directory 203 * @throws \InvalidArgumentException If directory is not a directory 204 */ 205 public function setTemplatesDirectory($directory) 206 { 207 $this->templatesDirectory = rtrim($directory, DIRECTORY_SEPARATOR); 208 } 209 210 /** 211 * Get templates base directory 212 * @return string 213 */ 214 public function getTemplatesDirectory() 215 { 216 return $this->templatesDirectory; 217 } 218 219 /** 220 * Get fully qualified path to template file using templates base directory 221 * @param string $file The template file pathname relative to templates base directory 222 * @return string 223 */ 224 public function getTemplatePathname($file) 225 { 226 return $this->templatesDirectory . DIRECTORY_SEPARATOR . ltrim($file, DIRECTORY_SEPARATOR); 227 } 228 229 /******************************************************************************** 230 * Rendering 231 *******************************************************************************/ 232 233 /** 234 * Display template 235 * 236 * This method echoes the rendered template to the current output buffer 237 * 238 * @param string $template Pathname of template file relative to templates directory 239 * @param array $data Any additonal data to be passed to the template. 240 */ 241 public function display($template, $data = null) 242 { 243 echo $this->fetch($template, $data); 244 } 245 246 /** 247 * Return the contents of a rendered template file 248 * 249 * @param string $template The template pathname, relative to the template base directory 250 * @param array $data Any additonal data to be passed to the template. 251 * @return string The rendered template 252 */ 253 public function fetch($template, $data = null) 254 { 255 return $this->render($template, $data); 256 } 257 258 /** 259 * Render a template file 260 * 261 * NOTE: This method should be overridden by custom view subclasses 262 * 263 * @param string $template The template pathname, relative to the template base directory 264 * @param array $data Any additonal data to be passed to the template. 265 * @return string The rendered template 266 * @throws \RuntimeException If resolved template pathname is not a valid file 267 */ 268 protected function render($template, $data = null) 269 { 270 $templatePathname = $this->getTemplatePathname($template); 271 if (!is_file($templatePathname)) { 272 throw new \RuntimeException("View cannot render `$template` because the template does not exist"); 273 } 274 275 $data = array_merge($this->data->all(), (array) $data); 276 extract($data); 277 ob_start(); 278 require $templatePathname; 279 280 return ob_get_clean(); 281 } 282 }