├── Log └── DateTimeFileWriter.php ├── Middleware ├── CsrfGuard.php ├── HttpBasicAuth.php ├── HttpDigestAuth.php ├── Jsonp.php ├── README.markdown └── StrongAuth.php ├── README.markdown ├── Views ├── Blitz.php ├── Dwoo.php ├── Extension │ ├── README.markdown │ ├── Smarty │ │ └── function.urlFor.php │ ├── Twig │ │ └── Extensions │ │ │ └── Slim.php │ └── TwigAutoloader.php ├── H2o.php ├── Haanga.php ├── Haml.php ├── Mustache.php ├── README.markdown ├── Rain.php ├── Savant.php ├── Smarty.php ├── Sugar.php └── Twig.php └── composer.json /Log/DateTimeFileWriter.php: -------------------------------------------------------------------------------- 1 | new \Slim\Extras\Log\DateTimeFileWriter() 14 | * )); 15 | * 16 | * SETTINGS 17 | * 18 | * You may customize this log writer by passing an array of 19 | * settings into the class constructor. Available options 20 | * are shown above the constructor method below. 21 | * 22 | * @author Josh Lockhart 23 | * @copyright 2012 Josh Lockhart 24 | * 25 | * MIT LICENSE 26 | * 27 | * Permission is hereby granted, free of charge, to any person obtaining 28 | * a copy of this software and associated documentation files (the 29 | * "Software"), to deal in the Software without restriction, including 30 | * without limitation the rights to use, copy, modify, merge, publish, 31 | * distribute, sublicense, and/or sell copies of the Software, and to 32 | * permit persons to whom the Software is furnished to do so, subject to 33 | * the following conditions: 34 | * 35 | * The above copyright notice and this permission notice shall be 36 | * included in all copies or substantial portions of the Software. 37 | * 38 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 39 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 40 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 41 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 42 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 43 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 44 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 45 | */ 46 | namespace Slim\Extras\Log; 47 | 48 | class DateTimeFileWriter 49 | { 50 | /** 51 | * @var resource 52 | */ 53 | protected $resource; 54 | 55 | /** 56 | * @var array 57 | */ 58 | protected $settings; 59 | 60 | /** 61 | * Constructor 62 | * 63 | * Prepare this log writer. Available settings are: 64 | * 65 | * path: 66 | * (string) The relative or absolute filesystem path to a writable directory. 67 | * 68 | * name_format: 69 | * (string) The log file name format; parsed with `date()`. 70 | * 71 | * extension: 72 | * (string) The file extention to append to the filename`. 73 | * 74 | * message_format: 75 | * (string) The log message format; available tokens are... 76 | * %label% Replaced with the log message level (e.g. FATAL, ERROR, WARN). 77 | * %date% Replaced with a ISO8601 date string for current timezone. 78 | * %message% Replaced with the log message, coerced to a string. 79 | * 80 | * @param array $settings 81 | * @return void 82 | */ 83 | public function __construct($settings = array()) 84 | { 85 | //Merge user settings 86 | $this->settings = array_merge(array( 87 | 'path' => './logs', 88 | 'name_format' => 'Y-m-d', 89 | 'extension' => 'log', 90 | 'message_format' => '%label% - %date% - %message%' 91 | ), $settings); 92 | 93 | //Remove trailing slash from log path 94 | $this->settings['path'] = rtrim($this->settings['path'], DIRECTORY_SEPARATOR); 95 | } 96 | 97 | /** 98 | * Write to log 99 | * 100 | * @param mixed $object 101 | * @param int $level 102 | * @return void 103 | */ 104 | public function write($object, $level) 105 | { 106 | //Determine label 107 | $label = 'DEBUG'; 108 | switch ($level) { 109 | case \Slim\Log::FATAL: 110 | $label = 'FATAL'; 111 | break; 112 | case \Slim\Log::ERROR: 113 | $label = 'ERROR'; 114 | break; 115 | case \Slim\Log::WARN: 116 | $label = 'WARN'; 117 | break; 118 | case \Slim\Log::INFO: 119 | $label = 'INFO'; 120 | break; 121 | } 122 | 123 | //Get formatted log message 124 | $message = str_replace(array( 125 | '%label%', 126 | '%date%', 127 | '%message%' 128 | ), array( 129 | $label, 130 | date('c'), 131 | (string)$object 132 | ), $this->settings['message_format']); 133 | 134 | //Open resource handle to log file 135 | if (!$this->resource) { 136 | $filename = date($this->settings['name_format']); 137 | if (! empty($this->settings['extension'])) { 138 | $filename .= '.' . $this->settings['extension']; 139 | } 140 | 141 | $this->resource = fopen($this->settings['path'] . DIRECTORY_SEPARATOR . $filename, 'a'); 142 | } 143 | 144 | //Output to resource 145 | fwrite($this->resource, $message . PHP_EOL); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /Middleware/CsrfGuard.php: -------------------------------------------------------------------------------- 1 | add(new \Slim\Extras\Middleware\CsrfGuard()); 12 | * 13 | */ 14 | namespace Slim\Extras\Middleware; 15 | 16 | class CsrfGuard extends \Slim\Middleware 17 | { 18 | /** 19 | * CSRF token key name. 20 | * 21 | * @var string 22 | */ 23 | protected $key; 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param string $key The CSRF token key name. 29 | * @return void 30 | */ 31 | public function __construct($key = 'csrf_token') 32 | { 33 | if (! is_string($key) || empty($key) || preg_match('/[^a-zA-Z0-9\-\_]/', $key)) { 34 | throw new \OutOfBoundsException('Invalid CSRF token key "' . $key . '"'); 35 | } 36 | 37 | $this->key = $key; 38 | } 39 | 40 | /** 41 | * Call middleware. 42 | * 43 | * @return void 44 | */ 45 | public function call() 46 | { 47 | // Attach as hook. 48 | $this->app->hook('slim.before', array($this, 'check')); 49 | 50 | // Call next middleware. 51 | $this->next->call(); 52 | } 53 | 54 | /** 55 | * Check CSRF token is valid. 56 | * Note: Also checks POST data to see if a Moneris RVAR CSRF token exists. 57 | * 58 | * @return void 59 | */ 60 | public function check() { 61 | // Check sessions are enabled. 62 | if (session_id() === '') { 63 | throw new \Exception('Sessions are required to use the CSRF Guard middleware.'); 64 | } 65 | 66 | if (! isset($_SESSION[$this->key])) { 67 | $_SESSION[$this->key] = sha1(serialize($_SERVER) . rand(0, 0xffffffff)); 68 | } 69 | 70 | $token = $_SESSION[$this->key]; 71 | 72 | // Validate the CSRF token. 73 | if (in_array($this->app->request()->getMethod(), array('POST', 'PUT', 'DELETE'))) { 74 | $userToken = $this->app->request()->post($this->key); 75 | if ($token !== $userToken) { 76 | $this->app->halt(400, 'Invalid or missing CSRF token.'); 77 | } 78 | } 79 | 80 | // Assign CSRF token key and value to view. 81 | $this->app->view()->appendData(array( 82 | 'csrf_key' => $this->key, 83 | 'csrf_token' => $token, 84 | )); 85 | } 86 | } -------------------------------------------------------------------------------- /Middleware/HttpBasicAuth.php: -------------------------------------------------------------------------------- 1 | 9 | * @version 1.0 10 | * @copyright 2012 Josh Lockhart 11 | * 12 | * USAGE 13 | * 14 | * $app = new \Slim\Slim(); 15 | * $app->add(new \Slim\Extras\Middleware\HttpBasicAuth('theUsername', 'thePassword')); 16 | * 17 | * MIT LICENSE 18 | * 19 | * Permission is hereby granted, free of charge, to any person obtaining 20 | * a copy of this software and associated documentation files (the 21 | * "Software"), to deal in the Software without restriction, including 22 | * without limitation the rights to use, copy, modify, merge, publish, 23 | * distribute, sublicense, and/or sell copies of the Software, and to 24 | * permit persons to whom the Software is furnished to do so, subject to 25 | * the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 34 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 35 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 36 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37 | */ 38 | namespace Slim\Extras\Middleware; 39 | 40 | class HttpBasicAuth extends \Slim\Middleware 41 | { 42 | /** 43 | * @var string 44 | */ 45 | protected $realm; 46 | 47 | /** 48 | * @var string 49 | */ 50 | protected $username; 51 | 52 | /** 53 | * @var string 54 | */ 55 | protected $password; 56 | 57 | /** 58 | * Constructor 59 | * 60 | * @param string $username The HTTP Authentication username 61 | * @param string $password The HTTP Authentication password 62 | * @param string $realm The HTTP Authentication realm 63 | */ 64 | public function __construct($username, $password, $realm = 'Protected Area') 65 | { 66 | $this->username = $username; 67 | $this->password = $password; 68 | $this->realm = $realm; 69 | } 70 | 71 | /** 72 | * Call 73 | * 74 | * This method will check the HTTP request headers for previous authentication. If 75 | * the request has already authenticated, the next middleware is called. Otherwise, 76 | * a 401 Authentication Required response is returned to the client. 77 | */ 78 | public function call() 79 | { 80 | $req = $this->app->request(); 81 | $res = $this->app->response(); 82 | $authUser = $req->headers('PHP_AUTH_USER'); 83 | $authPass = $req->headers('PHP_AUTH_PW'); 84 | if ($authUser && $authPass && $authUser === $this->username && $authPass === $this->password) { 85 | $this->next->call(); 86 | } else { 87 | $res->status(401); 88 | $res->header('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realm)); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Middleware/HttpDigestAuth.php: -------------------------------------------------------------------------------- 1 | 9 | * as a reference. I do not claim ownership or copyright on this code. This 10 | * derivative class is provided under the MIT public license. 11 | * 12 | * @author Josh Lockhart 13 | * @author Samer Bechara 14 | * @version 1.0 15 | * 16 | * USAGE 17 | * 18 | * $app = new \Slim\Slim(); 19 | * $app->add(new \Slim\Extras\Middleware\HttpDigestAuth(array('user1' => 'password1', 'user2' => 'password2'))); 20 | * 21 | * MIT LICENSE 22 | * 23 | * Permission is hereby granted, free of charge, to any person obtaining 24 | * a copy of this software and associated documentation files (the 25 | * "Software"), to deal in the Software without restriction, including 26 | * without limitation the rights to use, copy, modify, merge, publish, 27 | * distribute, sublicense, and/or sell copies of the Software, and to 28 | * permit persons to whom the Software is furnished to do so, subject to 29 | * the following conditions: 30 | * 31 | * The above copyright notice and this permission notice shall be 32 | * included in all copies or substantial portions of the Software. 33 | * 34 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 35 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 36 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 37 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 38 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 39 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 40 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 41 | */ 42 | namespace Slim\Extras\Middleware; 43 | 44 | class HttpDigestAuth extends \Slim\Middleware { 45 | /** 46 | * @var array 47 | */ 48 | protected $credentials; 49 | 50 | /** 51 | * @var string 52 | */ 53 | protected $realm; 54 | 55 | /** 56 | * Constructor 57 | * 58 | * @param array $credentials An array of usernames and passwords 59 | * @param string $realm The HTTP Authentication realm 60 | * @return void 61 | */ 62 | public function __construct( $credentials, $realm = 'Protected Area' ) { 63 | 64 | 65 | $this->credentials = $credentials; 66 | $this->realm = $realm; 67 | } 68 | 69 | /** 70 | * Call 71 | * 72 | * This method will check the HTTP request headers for previous authentication. If 73 | * the request has already authenticated, the next middleware is called. Otherwise, 74 | * a 401 Authentication Required response is returned to the client. 75 | * 76 | * @return void 77 | */ 78 | public function call() { 79 | //Check header and header username 80 | if ( empty($_SERVER['PHP_AUTH_DIGEST']) ) { 81 | $this->fail(); 82 | return; 83 | } else { 84 | $data = $this->parseHttpDigest($_SERVER['PHP_AUTH_DIGEST']); 85 | if ( !$data || !array_key_exists($data['username'], $this->credentials) ) { 86 | $this->fail(); 87 | return; 88 | } 89 | } 90 | 91 | //Check header response 92 | $A1 = md5($data['username'] . ':' . $this->realm . ':' . $this->credentials[$data['username']]); 93 | $A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $data['uri']); 94 | $validResponse = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' . $A2); 95 | if ( $data['response'] !== $validResponse ) { 96 | $this->fail(); 97 | return; 98 | } 99 | 100 | //By this point the request is authenticated 101 | $this->next->call(); 102 | } 103 | 104 | /** 105 | * Require Authentication from HTTP Client 106 | * 107 | * @return void 108 | */ 109 | protected function fail() { 110 | $this->app->response()->status(401); 111 | $this->app->response()->header('WWW-Authenticate', sprintf('Digest realm="%s",qop="auth",nonce="%s",opaque="%s"', $this->realm, uniqid(), md5($this->realm))); 112 | } 113 | 114 | /** 115 | * Parse HTTP Digest Authentication header 116 | * 117 | * @return array|false 118 | */ 119 | protected function parseHttpDigest( $headerValue ) { 120 | $needed_parts = array('nonce' => 1, 'nc' => 1, 'cnonce' => 1, 'qop' => 1, 'username' => 1, 'uri' => 1, 'response' => 1); 121 | $data = array(); 122 | $keys = implode('|', array_keys($needed_parts)); 123 | preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $headerValue, $matches, PREG_SET_ORDER); 124 | foreach ( $matches as $m ) { 125 | $data[$m[1]] = $m[3] ? $m[3] : $m[4]; 126 | unset($needed_parts[$m[1]]); 127 | } 128 | return $needed_parts ? false : $data; 129 | } 130 | } -------------------------------------------------------------------------------- /Middleware/Jsonp.php: -------------------------------------------------------------------------------- 1 | 6 | * @since 17-12-2012 7 | * 8 | * Simple class to wrap the response of the application in a JSONP callback function. 9 | * The class is triggered when a get parameter of callback is found 10 | * 11 | * Usage 12 | * ==== 13 | * 14 | * $app = new \Slim\Slim(); 15 | * $app->add(new \Slim\Extras\Middleware\JSONPMiddleware()); 16 | * 17 | */ 18 | 19 | namespace Slim\Extras\Middleware; 20 | 21 | class JSONPMiddleware extends \Slim\Middleware 22 | { 23 | public function call() 24 | { 25 | $callback = $this->app->request()->get('callback'); 26 | 27 | //Fetch the body first 28 | $this->next->call(); 29 | 30 | //If the JSONP callback parameter is set then wrap the response body in the original 31 | //callback string. 32 | if(!empty($callback)){ 33 | //The response becomes a javascript response 34 | $this->app->contentType('application/javascript'); 35 | 36 | $jsonp_response = htmlspecialchars($callback) . "(" .$this->app->response()->body() . ")"; 37 | $this->app->response()->body($jsonp_response); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Middleware/README.markdown: -------------------------------------------------------------------------------- 1 | # Slim Authentication and XSS Middlewares 2 | 3 | ## CsrfGuard 4 | 5 | This is used to protect your website from CSRF attacks. 6 | 7 | ### How to use 8 | 9 | use \Slim\Slim; 10 | use \Slim\Extras\Middleware\CsrfGuard; 11 | 12 | $app = new Slim(); 13 | $app->add(new CsrfGuard()); 14 | 15 | In your view template add this to any web forms you have created. 16 | 17 | 18 | 19 | ## HttpBasic 20 | 21 | This will provide you with basic user Authentication based on username and password set. 22 | 23 | ### How to use 24 | 25 | use \Slim\Slim; 26 | use \Slim\Extras\Middleware\HttpBasicAuth; 27 | 28 | $app = new Slim(); 29 | $app->add(new HttpBasicAuth('theUsername', 'thePassword')); 30 | 31 | 32 | ## Strong 33 | 34 | ### How to use 35 | 36 | You will need to pass Strong a config with all your secured routes and any information that is needed 37 | for your Provider. 38 | 39 | Here is some sample code for using PDO provider and securing some routes using regex. 40 | 41 | use \Slim\Slim; 42 | use \Slim\Extras\Middleware\StrongAuth; 43 | 44 | $app = new Slim(); 45 | $config = array( 46 | 'provider' => 'PDO', 47 | 'pdo' => new PDO('mysql:host=localhost;dbname=database_name', 'username', 'password'), 48 | 'auth.type' => 'form', 49 | 'login.url' => '/', 50 | 'security.urls' => array( 51 | array('path' => '/test'), 52 | array('path' => '/about/.+'), 53 | ), 54 | ); 55 | 56 | $app->add(new StrongAuth($config)); 57 | -------------------------------------------------------------------------------- /Middleware/StrongAuth.php: -------------------------------------------------------------------------------- 1 | 9 | * @version 1.0 10 | * @copyright 2012 Andrew Smith 11 | * 12 | * USAGE 13 | * 14 | * $app = new \Slim\Slim(); 15 | * $app->add(new \Slim\Extras\Middleware\StrongAuth(array('provider' => 'PDO', 'pdo' => new PDO('sqlite:memory')))); 16 | * 17 | * MIT LICENSE 18 | * 19 | * Permission is hereby granted, free of charge, to any person obtaining 20 | * a copy of this software and associated documentation files (the 21 | * "Software"), to deal in the Software without restriction, including 22 | * without limitation the rights to use, copy, modify, merge, publish, 23 | * distribute, sublicense, and/or sell copies of the Software, and to 24 | * permit persons to whom the Software is furnished to do so, subject to 25 | * the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 34 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 35 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 36 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37 | */ 38 | namespace Slim\Extras\Middleware; 39 | 40 | class StrongAuth extends \Slim\Middleware 41 | { 42 | /** 43 | * @var array 44 | */ 45 | protected $settings = array( 46 | 'login.url' => '/', 47 | 'auth.type' => 'http', 48 | 'realm' => 'Protected Area', 49 | ); 50 | 51 | /** 52 | * Constructor 53 | * 54 | * @param array $config Configuration for Strong and Login Details 55 | * @param \Strong\Strong $strong 56 | * @return void 57 | */ 58 | public function __construct(array $config = array(), \Strong\Strong $strong = null) 59 | { 60 | $this->config = array_merge($this->settings, $config); 61 | $this->auth = (!empty($strong)) ? $strong : \Strong\Strong::factory($this->config); 62 | } 63 | 64 | /** 65 | * Call 66 | * 67 | * @return void 68 | */ 69 | public function call() 70 | { 71 | $req = $this->app->request(); 72 | 73 | // Authentication Initialised 74 | switch ($this->config['auth.type']) { 75 | case 'form': 76 | $this->formAuth($this->auth, $req); 77 | break; 78 | default: 79 | $this->httpAuth($this->auth, $req); 80 | break; 81 | } 82 | } 83 | 84 | /** 85 | * Form based authentication 86 | * 87 | * @param \Strong\Strong $auth 88 | * @param object $req 89 | */ 90 | private function formAuth($auth, $req) 91 | { 92 | $app = $this->app; 93 | $config = $this->config; 94 | $this->app->hook('slim.before.router', function () use ($app, $auth, $req, $config) { 95 | $secured_urls = isset($config['security.urls']) && is_array($config['security.urls']) ? $config['security.urls'] : array(); 96 | foreach ($secured_urls as $surl) { 97 | $patternAsRegex = $surl['path']; 98 | if (substr($surl['path'], -1) === '/') { 99 | $patternAsRegex = $patternAsRegex . '?'; 100 | } 101 | $patternAsRegex = '@^' . $patternAsRegex . '$@'; 102 | 103 | if (preg_match($patternAsRegex, $req->getPathInfo())) { 104 | if (!$auth->loggedIn()) { 105 | if ($req->getPath() !== $config['login.url']) { 106 | $app->redirect($config['login.url']); 107 | } 108 | } 109 | } 110 | } 111 | }); 112 | 113 | $this->next->call(); 114 | } 115 | 116 | /** 117 | * HTTPAuth based authentication 118 | * 119 | * This method will check the HTTP request headers for previous authentication. If 120 | * the request has already authenticated, the next middleware is called. Otherwise, 121 | * a 401 Authentication Required response is returned to the client. 122 | * 123 | * @param \Strong\Strong $auth 124 | * @param object $req 125 | */ 126 | private function httpAuth($auth, $req) 127 | { 128 | $res = $this->app->response(); 129 | $authUser = $req->headers('PHP_AUTH_USER'); 130 | $authPass = $req->headers('PHP_AUTH_PW'); 131 | 132 | if ($authUser && $authPass && $auth->login($authUser, $authPass)) { 133 | $this->next->call(); 134 | } else { 135 | $res->status(401); 136 | $res->header('WWW-Authenticate', sprintf('Basic realm="%s"', $this->config['realm'])); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Slim Framework Extras 2 | 3 | This repository contains extra resources that complement the Slim Framework, a PHP micro framework that helps 4 | you quickly write simple yet powerful web applications. 5 | 6 | --- 7 | #### For custom views we are now recommending using the [Slim Views](https://github.com/codeguy/Slim-Views) repo instead. We are simplifying the amount of views we officially support and will be splitting up the Slim Extras repo into smaller chunks. 8 | 9 | #### For custom loggers we are now recommending using the [Slim Logger](https://github.com/codeguy/Slim-Logger) repo instead. 10 | --- 11 | 12 | ## Custom Views 13 | 14 | This repository contains custom views for your Slim Framework applications. Custom views let you easily 15 | use popular third-party templating frameworks, like [Twig](http://twig.sensiolabs.org/) or 16 | [Smarty](http://www.smarty.net/), with your Slim Framework application. 17 | 18 | * Smarty 19 | * Twig 20 | * Mustache 21 | * Haml 22 | * Haanga 23 | * Blitz 24 | * Dwoo 25 | * Sugar 26 | * Savant 27 | * Rain 28 | * H2o 29 | 30 | This example demonstrates how to use the custom Twig view in your Slim Framework application: 31 | 32 | $twigView 39 | )); 40 | 41 | This example assumes you are autoloading dependencies using [Composer](http://getcomposer.org/). If you are not 42 | using Composer, you must manually `require` the custom view class before instantiating it. 43 | 44 | Read the [Slim Framework documentation](http://docs.slimframework.com/pages/view-custom/) to learn how to write 45 | your own custom view. 46 | 47 | ## Middleware 48 | 49 | This repository also contains middleware for your Slim Framework application. This 50 | example demonstrates how to apply HTTP basic authentication to a Slim Framework application: 51 | 52 | add(new \Slim\Extras\Middleware\HttpBasicAuth('username', 'password')); 55 | 56 | This example assumes you are autoloading dependencies using [Composer](http://getcomposer.org/). If you are not 57 | using Composer, you must manually `require` the custom middleware class before instantiating it. 58 | 59 | ## Log Writers 60 | 61 | This repository also contains custom log writers for your Slim Framwork application. This example 62 | demonstrates how to use the custom `DateTimeLogWriter` to write rolling log files from your Slim Framework application: 63 | 64 | new \Slim\Extras\Log\DateTimeFileWriter(array( 67 | 'path' => './logs', 68 | 'name_format' => 'Y-m-d', 69 | 'message_format' => '%label% - %date% - %message%' 70 | )) 71 | )); 72 | 73 | This example assumes you are autoloading dependencies using [Composer](http://getcomposer.org/). If you are not 74 | using Composer, you must manually `require` the log writer class before instantiating it. 75 | 76 | ## Author 77 | 78 | The Slim Framework is created and maintained by [Josh Lockhart](https://www.joshlockhart.com). Josh is a senior 79 | web developer at [New Media Campaigns](http://www.newmediacampaigns.com/). Josh also created and maintains 80 | [PHP: The Right Way](http://www.phptherightway.com/), a popular movement in the PHP community to introduce new 81 | PHP programmers to best practices and good information. 82 | 83 | The Slim Framework Extras repository is maintained by [Andrew Smith](https://github.com/silentworks). 84 | 85 | ## License 86 | 87 | The Slim Framework is released under the MIT public license. 88 | 89 | 90 | -------------------------------------------------------------------------------- /Views/Blitz.php: -------------------------------------------------------------------------------- 1 | 40 | * 41 | * The xBlitz extended blitz class provides better block handling 42 | * (load assoc arrays correctly, one level) 43 | * 44 | * @author Tobias O. 45 | */ 46 | class xBlitz extends \Blitz 47 | { 48 | function xblock($k,$a) 49 | { 50 | foreach ($a as $v) { 51 | $this->block('/' . $k, $v, true); 52 | } 53 | } 54 | } 55 | 56 | class Blitz extends \Slim\View 57 | { 58 | private $blitzEnvironment = null; 59 | 60 | public function render($template) 61 | { 62 | $env = $this->getEnvironment($template); 63 | 64 | return $env->parse($this->getData()); 65 | } 66 | 67 | private function getEnvironment($template) 68 | { 69 | if (!$this->blitzEnvironment) { 70 | ini_set('blitz.path', $this->getTemplatesDirectory() . '/'); 71 | $this->blitzEnvironment = new xBlitz($template); 72 | } 73 | 74 | return $this->blitzEnvironment; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Views/Dwoo.php: -------------------------------------------------------------------------------- 1 | 44 | */ 45 | class Dwoo extends \Slim\View 46 | { 47 | /** 48 | * @var string The path to the directory containing the Dwoo folder without trailing slash. 49 | */ 50 | public static $dwooDirectory = null; 51 | 52 | /** 53 | * @var persistent instance of the Smarty object 54 | */ 55 | private static $dwooInstance = null; 56 | 57 | /** 58 | * @var string The path to the templates folder WITH the trailing slash 59 | */ 60 | public static $dwooTemplatesDirectory = 'templates'; 61 | 62 | /** 63 | * Renders a template using Dwoo.php. 64 | * 65 | * @see View::render() 66 | * @param string $template The template name specified in Slim::render() 67 | * @return string 68 | */ 69 | public function render($template) 70 | { 71 | $dwoo = $this->getInstance(); 72 | 73 | return $dwoo->get(self::$dwooTemplatesDirectory.$template, $this->data); 74 | } 75 | 76 | /** 77 | * Creates new Dwoo instance if it doesn't already exist, and returns it. 78 | * 79 | * @throws RuntimeException If Dwoo lib directory does not exist. 80 | * @return DwooInstance 81 | */ 82 | private function getInstance() 83 | { 84 | if (!self::$dwooInstance) { 85 | if (!is_dir(self::$dwooDirectory)) { 86 | throw new \RuntimeException('Cannot set the Dwoo lib directory : ' . self::$dwooDirectory . '. Directory does not exist.'); 87 | } 88 | require_once self::$dwooDirectory . '/dwooAutoload.php'; 89 | self::$dwooInstance = new \Dwoo(); 90 | } 91 | 92 | return self::$dwooInstance; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Views/Extension/README.markdown: -------------------------------------------------------------------------------- 1 | # View Extensions 2 | This is where you can define all you custom functions in the template parser method of choice, I have currently included 3 | Twig and Smarty to allow Slim's urlFor() funtion in the template(view). You can add additional functions, filters, plugins to 4 | the Extension directory under the template parser directory of choice. 5 | 6 | ## Twig 7 | ### How to use 8 | To use this in Twig just include the code below at the top of your Slim index.php file after including TwigView. 9 | 10 | TwigView::$twigExtensions = array( 11 | 'Twig_Extensions_Slim', 12 | ); 13 | 14 | Inside your Twig template you would write: 15 | 16 | {{ urlFor('hello', {"name": "Josh", "age": "19"}) }} 17 | 18 | You can easily pass variables that are objects or arrays by doing: 19 | 20 | Hello {{ name }} 21 | 22 | If you need to specify the appname for the getInstance method in the urlFor functions, set it as the third parameter of the function 23 | in your template: 24 | 25 | Hello {{ name }} 26 | 27 | The $twigExtensions take an array of extension class name which need to follow the naming convention starting with __Extension_Twig__, 28 | this might seem like a overkill to add Slim's urlFor but it makes organising your project easier as your project becomes larger. 29 | 30 | ## Smarty 31 | ### How to use 32 | To use this in Smarty just include the code below at the top of your Slim index.php after including SmartyView. 33 | 34 | SmartyView::$smartyExtensions = array( 35 | dirname(__FILE__) . '/Views/Extension/Smarty', 36 | ); 37 | 38 | Inside your Smarty template you would write: 39 | 40 | {urlFor name="hello" options="name.Josh|age.26"} 41 | 42 | You can easily pass variables that are arrays using the (.) or object using the (->) by doing: 43 | 44 | Hello {$name} 45 | 46 | If you need to specify the appname for the getInstance method in the urlFor functions, set the appname parameter in your function: 47 | 48 | Hello {$name} 49 | 50 | The $smartyExtensions take an array of extension directories, this follows the Smarty naming convention provided in the Smarty docs. 51 | -------------------------------------------------------------------------------- /Views/Extension/Smarty/function.urlFor.php: -------------------------------------------------------------------------------- 1 | urlFor($name); 17 | 18 | if (isset($params['options'])) 19 | { 20 | $options = explode('|', $params['options']); 21 | foreach ($options as $option) { 22 | list($key, $value) = explode('.', $option); 23 | $opts[$key] = $value; 24 | } 25 | 26 | $url = \Slim\Slim::getInstance($appName)->urlFor($name, $opts); 27 | } 28 | 29 | return $url; 30 | } 31 | -------------------------------------------------------------------------------- /Views/Extension/Twig/Extensions/Slim.php: -------------------------------------------------------------------------------- 1 | new \Twig_Function_Method($this, 'urlFor'), 14 | ); 15 | } 16 | 17 | public function urlFor($name, $params = array(), $appName = 'default') 18 | { 19 | return \Slim\Slim::getInstance($appName)->urlFor($name, $params); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Views/Extension/TwigAutoloader.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class Twig_Extensions_Autoloader 19 | { 20 | /** 21 | * Registers Twig_Extensions_Autoloader as an SPL autoloader. 22 | */ 23 | static public function register() 24 | { 25 | ini_set('unserialize_callback_func', 'spl_autoload_call'); 26 | spl_autoload_register(array(new self, 'autoload')); 27 | } 28 | 29 | /** 30 | * Handles autoloading of classes. 31 | * 32 | * @param string $class A class name. 33 | * 34 | * @return boolean Returns true if the class has been loaded 35 | */ 36 | static public function autoload($class) 37 | { 38 | if (0 !== strpos($class, 'Twig_Extensions')) { 39 | return; 40 | } 41 | 42 | if (file_exists($file = dirname(__FILE__) . '/' . str_replace('_', '/', $class).'.php')) { 43 | require $file; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Views/H2o.php: -------------------------------------------------------------------------------- 1 | 39 | */ 40 | class H2o extends \Slim\View 41 | { 42 | /** 43 | * @var string The path to the h2o.php WITH a trailing slash 44 | */ 45 | public static $h2o_directory = ''; 46 | 47 | /** 48 | * @var array H2o options, see H2o documentation for reference 49 | */ 50 | public static $h2o_options = array(); 51 | 52 | /** 53 | * Renders a template using h2o 54 | * 55 | * @param string $template template file name 56 | * @return string 57 | */ 58 | public function render($template) 59 | { 60 | if (!array_key_exists('searchpath', self::$h2o_options)) { 61 | self::$h2o_options['searchpath'] = $this->getTemplatesDirectory() . '/'; 62 | } 63 | $this->_load_h2o(); 64 | $h2o = new \H2o($template, self::$h2o_options); 65 | 66 | return $h2o->render($this->data); 67 | } 68 | 69 | /** 70 | * Loads H2o library if it is not already loaded 71 | * 72 | * @access private 73 | * @throws RuntimeException if h2o directory doesn't exist 74 | * @return void 75 | */ 76 | private function _load_h2o() 77 | { 78 | if (class_exists('\H2o')) { 79 | return; 80 | } 81 | if (!is_dir(self::$h2o_directory)) { 82 | throw new \RuntimeException('h2o directory is invalid'); 83 | } 84 | require_once self::$h2o_directory . 'h2o.php'; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Views/Haanga.php: -------------------------------------------------------------------------------- 1 | new HaangaView('/path/to/Haanga/dir', '/path/to/templates/dir', '/path/to/compiled/dir') 48 | * )); 49 | * }}} 50 | * 51 | * @package Slim 52 | * @author Isman Firmansyah 53 | */ 54 | class Haanga extends \Slim\View 55 | { 56 | /** 57 | * Configure Haanga environment 58 | */ 59 | public function __construct($haangaDir, $templatesDir, $compiledDir) 60 | { 61 | require_once $haangaDir . '/lib/Haanga.php'; 62 | \Haanga::configure(array( 63 | 'template_dir' => $templatesDir, 64 | 'cache_dir' => $compiledDir 65 | )); 66 | } 67 | 68 | /** 69 | * Render Haanga Template 70 | * 71 | * This method will output the rendered template content 72 | * 73 | * @param string $template The path to the Haanga template, relative to the Haanga templates directory. 74 | * @return string|NULL 75 | */ 76 | public function render($template) 77 | { 78 | return \Haanga::load($template, $this->data); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Views/Haml.php: -------------------------------------------------------------------------------- 1 | 46 | */ 47 | class Haml extends \Slim\View 48 | { 49 | /** 50 | * @var string The path to the directory containing the "HamlPHP" folder without trailing slash. 51 | */ 52 | public static $hamlDirectory = null; 53 | 54 | /** 55 | * @var string The path to the templates folder WITH the trailing slash 56 | */ 57 | public static $hamlTemplatesDirectory = 'templates/'; 58 | 59 | /** 60 | * @var string The path to the templates folder WITH the trailing slash 61 | */ 62 | public static $hamlCacheDirectory = null; 63 | 64 | /** 65 | * Renders a template using Haml.php. 66 | * 67 | * @see View::render() 68 | * @throws RuntimeException If Haml lib directory does not exist. 69 | * @param string $template The template name specified in Slim::render() 70 | * @return string 71 | */ 72 | public function render($template) 73 | { 74 | if (!is_dir(self::$hamlDirectory)) { 75 | throw new \RuntimeException('Cannot set the HamlPHP lib directory : ' . self::$hamlDirectory . '. Directory does not exist.'); 76 | } 77 | require_once self::$hamlDirectory . '/HamlPHP/HamlPHP.php'; 78 | require_once self::$hamlDirectory . '/HamlPHP/Storage/FileStorage.php'; 79 | $parser = new \HamlPHP(new \FileStorage(self::$hamlCacheDirectory)); 80 | 81 | $file = $parser->parseFile(self::$hamlTemplatesDirectory . $template); 82 | return $parser->evaluate($file, $this->data); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Views/Mustache.php: -------------------------------------------------------------------------------- 1 | 44 | */ 45 | class Mustache extends \Slim\View 46 | { 47 | /** 48 | * @var string The path to the directory containing Mustache.php 49 | */ 50 | public static $mustacheDirectory = null; 51 | 52 | /** 53 | * Renders a template using Mustache.php. 54 | * 55 | * @see View::render() 56 | * @param string $template The template name specified in Slim::render() 57 | * @return string 58 | */ 59 | public function render($template) 60 | { 61 | require_once self::$mustacheDirectory . '/Autoloader.php'; 62 | \Mustache_Autoloader::register(dirname(self::$mustacheDirectory)); 63 | $m = new \Mustache_Engine(); 64 | $contents = file_get_contents($this->getTemplatesDirectory() . '/' . ltrim($template, '/')); 65 | return $m->render($contents, $this->data); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Views/README.markdown: -------------------------------------------------------------------------------- 1 | # Custom Views 2 | 3 | The Slim Framework provides a default view class that uses PHP template files. This folder includes custom view classes 4 | that you may use with third-party template libraries, such as [Twig](http://www.twig-project.org/), 5 | [Smarty](http://www.smarty.net/), or [Mustache](http://mustache.github.com/). 6 | 7 | ## Twig 8 | 9 | The `\Slim\Extras\Views\Twig` custom view class provides support for the [Twig](http://twig.sensiolabs.org/) template 10 | library. You can use the Twig custom view in your Slim Framework application like this: 11 | 12 | new \Slim\Extras\Views\Twig() 15 | )); 16 | 17 | If you are not using Composer to autoload project dependencies, you must also set the Twig view's public static 18 | `$twigDirectory` property; this is the relative or absolute path to the directory that conatins the Twig library. 19 | 20 | ### Twig configuration 21 | 22 | There are several public static properties you can use to customize the Twig library behavior. 23 | 24 | ####$twigOptions 25 | 26 | An array of options to pass to the underlying Twig environment ([Twig docs](http://twig.sensiolabs.org/doc/api.html#environment-options)): 27 | 28 | \Slim\Extras\Views\Twig::$twigOptions = array( 29 | 'debug' => true 30 | ); 31 | 32 | 33 | ####$twigExtensions 34 | 35 | An array contianing Twig extensions to load ([Twig docs](http://twig.sensiolabs.org/doc/advanced.html)): 36 | 37 | \Slim\Extras\Views\Twig::$twigExtensions = array( 38 | new MyCustomExtension(), 39 | new ThirdPartyExtension() 40 | ); 41 | 42 | 43 | ####$twigTemplateDirs 44 | 45 | An array of paths to directories containing Twig templates ([Twig docs](http://twig.sensiolabs.org/doc/api.html#twig-loader-filesystem)): 46 | 47 | \Slim\Extras\Views\Twig::$twigTemplateDirs = array( 48 | realpath(PROJECT_DIR . '/templates'), 49 | realpath(PROJECT_DIR . '/some/other/templates') 50 | ); 51 | 52 | ## Mustache 53 | 54 | The `\Slim\Extras\Views\Mustache` custom view class provides support for the 55 | [Mustache template language](http://mustache.github.com/) and the [Mustache.php library](github.com/bobthecow/mustache.php). 56 | You can use the Mustache custom view in your Slim Framework application like this: 57 | 58 | new \Slim\Extras\Views\Mustache() 62 | )); 63 | 64 | Before you can use the Mustache view class, you must set its static public `$mustacheDirectory` property; this is the 65 | relative or absolute path to the Mustache library. 66 | 67 | ## SmartyView 68 | 69 | The `\Slim\Extras\Views\Smarty` custom view class provides support for the [Smarty](http://www.smarty.net/) template 70 | library. You can use the Smarty custom view in your Slim Framework application like this: 71 | 72 | new \Slim\Extras\Views\Smarty() 75 | )); 76 | 77 | You must configure the Smarty view's public static `$smartyDirectory`, `$smartyCompileDirectory` , `$smartyCacheDirectory` 78 | and optionally `$smartyTemplatesDirectory` properties before using the Smarty view class in your application. These 79 | properties are at the top of the `Views/Smarty.php` class definition. 80 | 81 | ## Blitz 82 | 83 | The `\Slim\Extras\Views\Blitz` custom view class provides support for the Blitz templating system. Blitz is written 84 | as C and is compiled to a PHP extension. This means it is FAST. You can learn more about Blitz at 85 | . You can use the Blitz custom view in your Slim Framework application like this: 86 | 87 | new \Slim\Extras\Views\Blitz() 90 | )); 91 | 92 | ## HaangaView 93 | 94 | The `\Slim\Extras\Views\Haanga` custom view class provides support for the Haanga templating system. Refer to 95 | the `Views/Haanga.php` file for further documentation. 96 | 97 | new \Slim\Extras\Views\Haanga( 100 | '/path/to/Haanga/dir', 101 | '/path/to/templates/dir', 102 | '/path/to/compiled/dir' 103 | ) 104 | )); 105 | 106 | ## H2o 107 | 108 | The `H2o` custom view class provides support for the [H2o templating system](http://www.h2o-template.org). You can 109 | use the H2o custom view in your Slim Framework application like this: 110 | 111 | new \Slim\Extras\Views\H2oView() 115 | )); 116 | 117 | Refer to the `Views/H2o.php` file for further documentation. 118 | 119 | -------------------------------------------------------------------------------- /Views/Rain.php: -------------------------------------------------------------------------------- 1 | 45 | */ 46 | class Rain extends \Slim\View 47 | { 48 | /** 49 | * @var string The path to the directory containing "rain.tpl.class.php" without trailing slash. 50 | */ 51 | public static $rainDirectory = null; 52 | 53 | /** 54 | * @var persistent instance of the Smarty object 55 | */ 56 | private static $rainInstance = null; 57 | 58 | /** 59 | * @var string The path to the templates folder WITH the trailing slash 60 | */ 61 | public static $rainTemplatesDirectory = 'templates/'; 62 | 63 | /** 64 | * @var string The path to the cache folder WITH the trailing slash 65 | */ 66 | public static $rainCacheDirectory = null; 67 | 68 | /** 69 | * Renders a template using Rain.php. 70 | * 71 | * @see View::render() 72 | * @param string $template The template name specified in Slim::render() 73 | * @return string 74 | */ 75 | public function render($template) 76 | { 77 | $rain = $this->getInstance(); 78 | $rain->assign($this->data); 79 | 80 | return $rain->draw($template, $return_string = true); 81 | } 82 | 83 | /** 84 | * Creates new Rain instance if it doesn't already exist, and returns it. 85 | * 86 | * @throws RuntimeException If Rain lib directory does not exist. 87 | * @return RainInstance 88 | */ 89 | private function getInstance() 90 | { 91 | if (!self::$rainInstance) { 92 | if (!is_dir(self::$rainDirectory)) { 93 | throw new \RuntimeException('Cannot set the Rain lib directory : ' . self::$rainDirectory . '. Directory does not exist.'); 94 | } 95 | require_once self::$rainDirectory . '/rain.tpl.class.php'; 96 | \raintpl::$tpl_dir = self::$rainTemplatesDirectory; 97 | \raintpl::$cache_dir = self::$rainCacheDirectory; 98 | self::$rainInstance = new \raintpl(); 99 | } 100 | 101 | return self::$rainInstance; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Views/Savant.php: -------------------------------------------------------------------------------- 1 | 44 | */ 45 | class Savant extends \Slim\View 46 | { 47 | /** 48 | * @var string The path to the directory containing Savant3.php and the Savant3 folder without trailing slash. 49 | */ 50 | public static $savantDirectory = null; 51 | 52 | /** 53 | * @var array The options for the Savant3 environment, see http://phpsavant.com/api/Savant3/ 54 | */ 55 | public static $savantOptions = array('template_path' => 'templates'); 56 | 57 | /** 58 | * @var persistent instance of the Savant object 59 | */ 60 | private static $savantInstance = null; 61 | 62 | /** 63 | * Renders a template using Savant3.php. 64 | * 65 | * @see View::render() 66 | * @param string $template The template name specified in Slim::render() 67 | * @return string 68 | */ 69 | public function render($template) 70 | { 71 | $savant = $this->getInstance(); 72 | $savant->assign($this->data); 73 | 74 | return $savant->fetch($template); 75 | } 76 | 77 | /** 78 | * Creates new Savant instance if it doesn't already exist, and returns it. 79 | * 80 | * @throws RuntimeException If Savant3 lib directory does not exist. 81 | * @return SavantInstance 82 | */ 83 | private function getInstance() 84 | { 85 | if (!self::$savantInstance) { 86 | if (!is_dir(self::$savantDirectory)) { 87 | throw new \RuntimeException('Cannot set the Savant lib directory : ' . self::$savantDirectory . '. Directory does not exist.'); 88 | } 89 | require_once self::$savantDirectory . '/Savant3.php'; 90 | self::$savantInstance = new \Savant3(self::$savantOptions); 91 | } 92 | 93 | return self::$savantInstance; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Views/Smarty.php: -------------------------------------------------------------------------------- 1 | 46 | */ 47 | class Smarty extends \Slim\View 48 | { 49 | /** 50 | * @var string The path to the Smarty code directory WITHOUT the trailing slash 51 | */ 52 | public static $smartyDirectory = null; 53 | 54 | /** 55 | * @var string The path to the Smarty compiled templates folder WITHOUT the trailing slash 56 | */ 57 | public static $smartyCompileDirectory = null; 58 | 59 | /** 60 | * @var string The path to the Smarty cache folder WITHOUT the trailing slash 61 | */ 62 | public static $smartyCacheDirectory = null; 63 | 64 | /** 65 | * @var string The path to the templates folder WITHOUT the trailing slash 66 | */ 67 | public static $smartyTemplatesDirectory = 'templates'; 68 | 69 | /** 70 | * @var SmartyExtensions The Smarty extensions directory you want to load plugins from 71 | */ 72 | public static $smartyExtensions = array(); 73 | 74 | /** 75 | * @var persistent instance of the Smarty object 76 | */ 77 | private static $smartyInstance = null; 78 | 79 | /** 80 | * Render Smarty Template 81 | * 82 | * This method will output the rendered template content 83 | * 84 | * @param string $template The path to the Smarty template, relative to the templates directory. 85 | * @return void 86 | */ 87 | 88 | public function render($template) 89 | { 90 | $instance = self::getInstance(); 91 | $instance->assign($this->data); 92 | 93 | return $instance->fetch($template); 94 | } 95 | 96 | /** 97 | * Creates new Smarty object instance if it doesn't already exist, and returns it. 98 | * 99 | * @throws RuntimeException If Smarty lib directory does not exist 100 | * @return Smarty Instance 101 | */ 102 | public static function getInstance() 103 | { 104 | if (!(self::$smartyInstance instanceof \Smarty)) { 105 | if (!is_dir(self::$smartyDirectory)) { 106 | throw new \RuntimeException('Cannot set the Smarty lib directory : ' . self::$smartyDirectory . '. Directory does not exist.'); 107 | } 108 | require_once self::$smartyDirectory . '/Smarty.class.php'; 109 | self::$smartyInstance = new \Smarty(); 110 | self::$smartyInstance->template_dir = is_null(self::$smartyTemplatesDirectory) ? $this->getTemplatesDirectory() : self::$smartyTemplatesDirectory; 111 | if (self::$smartyExtensions) { 112 | self::$smartyInstance->addPluginsDir(self::$smartyExtensions); 113 | } 114 | if (self::$smartyCompileDirectory) { 115 | self::$smartyInstance->compile_dir = self::$smartyCompileDirectory; 116 | } 117 | if (self::$smartyCacheDirectory) { 118 | self::$smartyInstance->cache_dir = self::$smartyCacheDirectory; 119 | } 120 | } 121 | 122 | return self::$smartyInstance; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Views/Sugar.php: -------------------------------------------------------------------------------- 1 | 45 | */ 46 | class Sugar extends \Slim\View 47 | { 48 | /** 49 | * @var string The path to the directory containing the Sugar folder without trailing slash. 50 | */ 51 | public static $sugarDirectory = null; 52 | 53 | /** 54 | * @var persistent instance of the Smarty object 55 | */ 56 | private static $sugarInstance = null; 57 | 58 | /** 59 | * @var string The path to the templates folder WITH the trailing slash 60 | */ 61 | public static $sugarTemplatesDirectory = 'templates/'; 62 | 63 | /** 64 | * @var string The path to the cache folder WITH the trailing slash 65 | */ 66 | public static $sugarCacheDirectory = null; 67 | 68 | /** 69 | * Renders a template using Sugar.php. 70 | * 71 | * @see View::render() 72 | * @param string $template The template name specified in Slim::render() 73 | * @return string 74 | */ 75 | public function render($template) 76 | { 77 | $sugar = $this->getInstance(); 78 | $template = $sugar->getTemplate($template); 79 | foreach ($this->data as $key => $value) { 80 | $template->set($key, $value); 81 | } 82 | 83 | return $template->fetch(); 84 | } 85 | 86 | /** 87 | * Creates new Sugar instance if it doesn't already exist, and returns it. 88 | * 89 | * @throws RuntimeException If Sugar lib directory does not exist. 90 | * @return SugarInstance 91 | */ 92 | private function getInstance() 93 | { 94 | if (!self::$sugarInstance) { 95 | if (!is_dir(self::$sugarDirectory)) { 96 | throw new \RuntimeException('Cannot set the Sugar lib directory : ' . self::$sugarDirectory . '. Directory does not exist.'); 97 | } 98 | require_once self::$sugarDirectory . '/Sugar.php'; 99 | self::$sugarInstance = new \Sugar(); 100 | self::$sugarInstance->templateDir = self::$sugarTemplatesDirectory; 101 | self::$sugarInstance->cacheDir = self::$sugarCacheDirectory; 102 | } 103 | 104 | return self::$sugarInstance; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Views/Twig.php: -------------------------------------------------------------------------------- 1 | getTemplatesDirectory()); 82 | } 83 | return self::$twigTemplateDirs; 84 | } 85 | 86 | /** 87 | * Render Twig Template 88 | * 89 | * This method will output the rendered template content 90 | * 91 | * @param string $template The path to the Twig template, relative to the Twig templates directory. 92 | * @return void 93 | */ 94 | public function render($template) 95 | { 96 | $env = $this->getEnvironment(); 97 | $template = $env->loadTemplate($template); 98 | 99 | return $template->render($this->data); 100 | } 101 | 102 | /** 103 | * Creates new TwigEnvironment if it doesn't already exist, and returns it. 104 | * 105 | * @return Twig_Environment 106 | */ 107 | public function getEnvironment() 108 | { 109 | if (!$this->twigEnvironment) { 110 | // Check for Composer Package Autoloader class loading 111 | if (!class_exists('\Twig_Autoloader')) { 112 | require_once self::$twigDirectory . '/Autoloader.php'; 113 | } 114 | 115 | \Twig_Autoloader::register(); 116 | $loader = new \Twig_Loader_Filesystem($this->getTemplateDirs()); 117 | $this->twigEnvironment = new \Twig_Environment( 118 | $loader, 119 | self::$twigOptions 120 | ); 121 | 122 | // Check for Composer Package Autoloader class loading 123 | if (!class_exists('\Twig_Extensions_Autoloader')) { 124 | $extension_autoloader = dirname(__FILE__) . '/Extension/TwigAutoloader.php'; 125 | if (file_exists($extension_autoloader)) require_once $extension_autoloader; 126 | } 127 | 128 | if (class_exists('\Twig_Extensions_Autoloader')) { 129 | \Twig_Extensions_Autoloader::register(); 130 | 131 | foreach (self::$twigExtensions as $ext) { 132 | $extension = is_object($ext) ? $ext : new $ext; 133 | $this->twigEnvironment->addExtension($extension); 134 | } 135 | } 136 | } 137 | 138 | return $this->twigEnvironment; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slim/extras", 3 | "type": "library", 4 | "description": "Extras package for the Slim Framework", 5 | "keywords": ["templating", "extensions", "middleware"], 6 | "homepage": "http://github.com/codeguy/Slim-Extras", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Josh Lockhart", 11 | "email": "info@joshlockhart.com", 12 | "homepage": "http://www.joshlockhart.com/" 13 | }, 14 | { 15 | "name": "Andrew Smith", 16 | "email": "a.smith@silentworks.co.uk" 17 | } 18 | ], 19 | "require": { 20 | "slim/slim": ">=2.0.0", 21 | "php": ">=5.3.0" 22 | }, 23 | "autoload": { 24 | "psr-0": { 25 | "Twig_Extensions_": "Views/Extension/", 26 | "Slim\\Extras": "." 27 | } 28 | }, 29 | "target-dir": "Slim/Extras" 30 | } 31 | --------------------------------------------------------------------------------