├── .gitignore
├── .travis.yml
├── LICENSE
├── README.markdown
├── composer.json
├── phpunit.xml.dist
├── src
└── SlimController
│ ├── Slim.php
│ └── SlimController.php
└── tests
├── SlimController
└── Tests
│ ├── Fixtures
│ ├── Controller
│ │ └── TestController.php
│ └── templates
│ │ └── rendertest.php
│ ├── Integration
│ └── CanCreateApplicationTest.php
│ ├── Old
│ ├── ControllerTest.php
│ ├── ParamsTest.php
│ ├── RenderTest.php
│ └── RoutingTest.php
│ ├── SlimControllerTest.php
│ ├── SlimTest.php
│ └── TestCase.php
└── bootstrap.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | vendor/
3 | composer.lock
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.3
5 | - 5.4
6 | - 5.5
7 |
8 | before_script:
9 | - curl -s http://getcomposer.org/installer | php
10 | - php composer.phar install --dev
11 |
12 | script: phpunit
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT LICENSE
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 | The above copyright notice and this permission notice shall be
11 | included in all copies or substantial portions of the Software.
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | # SlimController
2 |
3 | SlimController is an extension for [the Slim Framework](http://www.slimframework.com/) providing the C of MVC.
4 |
5 | With Slim alone, you can create great applications very, very quickly. Sometimes things get out of hand an you just need a bit more structure - or at least I do. That's what SlimController is for.
6 |
7 | [](https://packagist.org/packages/slimcontroller/slimcontroller)
8 | [](https://packagist.org/packages/slimcontroller/slimcontroller)
9 |
10 | [](https://travis-ci.org/fortrabbit/slimcontroller)
11 |
12 | # Install via composer
13 |
14 | Create a `composer.json` file
15 |
16 | {
17 | "require": {
18 | "slimcontroller/slimcontroller": "0.4.3"
19 | },
20 | "autoload": {
21 | "psr-0": {
22 | "MyApp": "src/"
23 | }
24 | }
25 | }
26 |
27 | Run installation
28 |
29 | composer.phar install --dev
30 |
31 | # Mini HowTo
32 |
33 | If you know how [Slim works](http://docs.slimframework.com/), using SlimController shouldn't be a big deal.
34 |
35 | ## Example Structure
36 |
37 | Setup a structure for your controller and templates (just a suggestion, do as you like):
38 |
39 | mkdir -p src/MyApp/Controller templates/home
40 |
41 | ## Controller
42 |
43 | Create your first controller in `src/MyApp/Controller/Home.php`
44 |
45 | render('home/index', array(
55 | 'someVar' => date('c')
56 | ));
57 | }
58 |
59 | public function helloAction($name)
60 | {
61 | $this->render('home/hello', array(
62 | 'name' => $name
63 | ));
64 | }
65 | }
66 |
67 | ## Templates
68 |
69 | Here are the two corresponding demo templates:
70 |
71 | `templates/home/index.php`
72 |
73 | This is the SlimController extension @ = $someVar ?>
74 |
75 | `templates/home/hello.php`
76 |
77 | Hello = $name ?>
78 |
79 | ## Boostrap index.php
80 |
81 | Minimal bootstrap file for this example
82 |
83 | APP_PATH . '/templates',
94 | 'controller.class_prefix' => '\\MyApp\\Controller',
95 | 'controller.method_suffix' => 'Action',
96 | 'controller.template_suffix' => 'php',
97 | ));
98 |
99 | $app->addRoutes(array(
100 | '/' => 'Home:index',
101 | '/hello/:name' => 'Home:hello',
102 | ));
103 |
104 | $app->run();
105 |
106 | ## Run
107 |
108 | php -S localhost:8080
109 |
110 |
111 | # Controller
112 |
113 | ## Configuration
114 |
115 | ### controller.class_prefix
116 |
117 | Optional class prefix for controller classes. Will be prepended to routes.
118 |
119 | Using `\\MyApp\\Controller` as prefix with given routes:
120 |
121 | $app->addRoutes(array(
122 | '/' => 'Home:index',
123 | '/hello/:name' => 'Home:hello',
124 | ));
125 |
126 | Translates to
127 |
128 | $app->addRoutes(array(
129 | '/' => '\\MyApp\\Controller\\Home:index',
130 | '/hello/:name' => '\\MyApp\\Controller\\Home:hello',
131 | ));
132 |
133 | ### controller.class_suffix
134 |
135 | Optional class suffix for controller classes. Will be appended to routes.
136 |
137 | Using `Controller` as suffix with given routes:
138 |
139 | $app->addRoutes(array(
140 | '/' => 'Home:index',
141 | '/hello/:name' => 'Home:hello',
142 | ));
143 |
144 | Translates to
145 |
146 | $app->addRoutes(array(
147 | '/' => 'HomeController:index',
148 | '/hello/:name' => 'HomeController:hello',
149 | ));
150 |
151 | ### controller.method_suffix
152 |
153 | Optional method suffix. Appended to routes.
154 |
155 | Using `Action` as suffix with given routes:
156 |
157 | $app->addRoutes(array(
158 | '/' => 'Home:index',
159 | '/hello/:name' => 'Home:hello',
160 | ));
161 |
162 | Translates to
163 |
164 | $app->addRoutes(array(
165 | '/' => 'Home:indexAction',
166 | '/hello/:name' => 'Home:helloAction',
167 | ));
168 |
169 | ### controller.template_suffix
170 |
171 | Defaults to `twig`. Will be appended to template name given in `render()` method.
172 |
173 | ## Extended Examples
174 |
175 | ### Routes
176 |
177 | // how to integrate the Slim middleware
178 | $app->addRoutes(array(
179 | '/' => array('Home:index', function() {
180 | error_log("MIDDLEWARE FOR SINGLE ROUTE");
181 | },
182 | function() {
183 | error_log("ADDITIONAL MIDDLEWARE FOR SINGLE ROUTE");
184 | }
185 | ),
186 | '/hello/:name' => array('post' => array('Home:hello', function() {
187 | error_log("THIS ROUTE IS ONLY POST");
188 | }
189 | ))
190 | ), function() {
191 | error_log("APPENDED MIDDLEWARE FOR ALL ROUTES");
192 | });
193 |
194 | ### Controller
195 |
196 | app->response()->status(404);
211 |
212 |
213 | /**
214 | * Params
215 | */
216 |
217 | // reads "?data[foo]=some+value"
218 | $foo = $this->param('foo');
219 |
220 | // reads "data[bar][name]=some+value" only if POST!
221 | $bar = $this->param('bar.name', 'post');
222 |
223 | // all params of bar ("object attributes")
224 | // "?data[bar][name]=me&data[bar][mood]=happy" only if POST!
225 | $bar = $this->param('bar');
226 | //error_log($bar['name']. ' is '. $bar['mood']);
227 |
228 | // reads multiple params in array
229 | $params = $this->params(array('foo', 'bar.name1', 'bar.name1'));
230 | //error_log($params['bar.name1']);
231 |
232 | // reads multiple params only if they are POST
233 | $params = $this->params(array('foo', 'bar.name1', 'bar.name1'), 'post');
234 |
235 | // reads multiple params only if they are POST and all are given!
236 | $params = $this->params(array('foo', 'bar.name1', 'bar.name1'), 'post', true);
237 | if (!$params) {
238 | error_log("Not all params given.. maybe some. Don't care");
239 | }
240 |
241 | // reads multiple params only if they are POST and replaces non given with defaults!
242 | $params = $this->params(array('foo', 'bar.name1', 'bar.name1'), 'post', array(
243 | 'foo' => 'Some Default'
244 | ));
245 |
246 |
247 | /**
248 | * Redirect shortcut
249 | */
250 |
251 | if (false) {
252 | $this->redirect('/somewhere');
253 | }
254 |
255 |
256 | /**
257 | * Rendering
258 | */
259 |
260 | $this->render('folder/file', array(
261 | 'foo' => 'bar'
262 | ));
263 |
264 | }
265 | }
266 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "slimcontroller/slimcontroller",
3 | "version": "0.4.3",
4 | "type": "library",
5 | "description": "Controller extensions for the Slim Framework",
6 | "keywords": ["microframework", "controller"],
7 | "homepage": "http://github.com/fortrabbit/slimcontroller",
8 | "license": "MIT",
9 | "authors": [
10 | {
11 | "name": "Ulrich Kautz",
12 | "email": "uk@fortrabbit.de",
13 | "homepage": "http://fortrabbit.com/"
14 | }
15 | ],
16 | "require": {
17 | "php": ">=5.3.0",
18 | "slim/slim": "2.*"
19 | },
20 | "require-dev": {
21 | "phpunit/phpunit": "4.3.5",
22 | "mockery/mockery": "0.8.*"
23 | },
24 | "autoload": {
25 | "psr-0": {
26 | "SlimController": "src/"
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/SlimController/Tests
16 | ./tests/SlimController/Tests/Old/
17 |
18 |
19 |
20 |
21 | src
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/SlimController/Slim.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright 2012 Ulrich Kautz
8 | * @version 0.1.2
9 | * @package SlimController
10 | *
11 | * For the full copyright and license information, please view the LICENSE
12 | * file that was distributed with this source code.
13 | */
14 |
15 | namespace SlimController;
16 |
17 | /**
18 | * Extended Slim base
19 | */
20 | class Slim extends \Slim\Slim
21 | {
22 | /**
23 | * @var array
24 | */
25 | protected static $ALLOWED_HTTP_METHODS = array('ANY', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD');
26 |
27 | /**
28 | * @var array
29 | */
30 | protected $routeNames = array();
31 |
32 | /**
33 | * Add multiple controller based routes
34 | *
35 | * Simple Format
36 | *
37 | * $app->addRoutes(array(
38 | * '/some/path' => 'className:methodName'
39 | * ));
40 | *
41 | *
42 | * With explicit HTTP method
43 | *
44 | * $app->addRoutes(array(
45 | * '/some/path' => array('get' => 'className:methodName')
46 | * ));
47 | *
48 | *
49 | * With local middleware
50 | *
51 | * $app->addRoutes(array(
52 | * '/some/path' => array('get' => 'className:methodName', function() {})
53 | * '/other/path' => array('className:methodName', function() {})
54 | * ));
55 | *
56 | *
57 | * With global middleware
58 | *
59 | * $app->addRoutes(array(
60 | * '/some/path' => 'className:methodName',
61 | * ), function() {});
62 | *
63 | *
64 | * @param array $routes The route definitions
65 | * @param array $globalMiddlewares
66 | * @throws \InvalidArgumentException
67 | * @internal param $callable ,... $middlewares Optional callable used for all routes as middleware
68 | *
69 | * @return $this
70 | */
71 | public function addRoutes(array $routes, $globalMiddlewares = array())
72 | {
73 | if (!is_array($globalMiddlewares)) {
74 | if (func_num_args() > 2) {
75 | $args = func_get_args();
76 | $globalMiddlewares = array_slice($args, 1);
77 | } else {
78 | $globalMiddlewares = array($globalMiddlewares);
79 | }
80 | }
81 |
82 | foreach ($routes as $path => $routeArgs) {
83 | // create array for simple request
84 | $routeArgs = (is_array($routeArgs)) ? $routeArgs : array('any' => $routeArgs);
85 |
86 | if (array_keys($routeArgs) === range(0, count($routeArgs) - 1)) {
87 | // route args is a sequential array not associative
88 | $routeArgs = array('any' => array($routeArgs[0],
89 | isset($routeArgs[1]) && is_array($routeArgs[1]) ? $routeArgs[1] : array_slice($routeArgs, 1))
90 | );
91 | }
92 |
93 | foreach ($routeArgs as $httpMethod => $classArgs) {
94 | // assign vars if middleware callback exists
95 | if (is_array($classArgs)) {
96 | $classRoute = $classArgs[0];
97 | $localMiddlewares = is_array($classArgs[1]) ? $classArgs[1] : array_slice($classArgs, 1);
98 | } else {
99 | $classRoute = $classArgs;
100 | $localMiddlewares = array();
101 | }
102 |
103 | // specific HTTP method
104 | $httpMethod = strtoupper($httpMethod);
105 | if (!in_array($httpMethod, static::$ALLOWED_HTTP_METHODS)) {
106 | throw new \InvalidArgumentException("Http method '$httpMethod' is not supported.");
107 | }
108 |
109 | $routeMiddlewares = array_merge($localMiddlewares, $globalMiddlewares);
110 | $route = $this->addControllerRoute($path, $classRoute, $routeMiddlewares);
111 |
112 | if (!isset($this->routeNames[$classRoute])) {
113 | $route->name($classRoute);
114 | $this->routeNames[$classRoute] = 1;
115 | }
116 |
117 | if ('any' === $httpMethod) {
118 | call_user_func_array(array($route, 'via'), static::$ALLOWED_HTTP_METHODS);
119 | } else {
120 | $route->via($httpMethod);
121 | }
122 | }
123 | }
124 |
125 | return $this;
126 | }
127 |
128 | /**
129 | * Add a new controller route
130 | *
131 | *
132 | * $app->addControllerRoute("/the/path", "className:methodName", array(function () { doSome(); }))
133 | * ->via('GET')->condition(..);
134 | *
135 | * $app->addControllerRoute("/the/path", "className:methodName")
136 | * ->via('GET')->condition(..);
137 | *
138 | *
139 | * @param string $path
140 | * @param string $route
141 | * @param callable[] $middleware,...
142 | *
143 | * @return \Slim\Route
144 | */
145 | public function addControllerRoute($path, $route, array $middleware = array())
146 | {
147 | $callback = $this->buildCallbackFromControllerRoute($route);
148 |
149 | array_unshift($middleware, $path);
150 | array_push($middleware, $callback);
151 |
152 | $route = call_user_func_array(array($this, 'map'), $middleware);
153 |
154 | return $route;
155 | }
156 |
157 | /**
158 | * Builds closure callback from controller route
159 | *
160 | * @param $route
161 | *
162 | * @return \Closure
163 | */
164 | protected function buildCallbackFromControllerRoute($route)
165 | {
166 | list($controller, $methodName) = $this->determineClassAndMethod($route);
167 | $app = & $this;
168 | $callable = function () use ($app, $controller, $methodName) {
169 | // Get action arguments
170 | $args = func_get_args();
171 | // Try to fetch the instance from Slim's container, otherwise lazy-instantiate it
172 | $instance = $app->container->has($controller) ? $app->container->get($controller) : new $controller($app);
173 |
174 | return call_user_func_array(array($instance, $methodName), $args);
175 | };
176 |
177 | return $callable;
178 | }
179 |
180 | /**
181 | * @param string $classMethod
182 | *
183 | * @return array
184 | * @throws \InvalidArgumentException
185 | */
186 | protected function determineClassAndMethod($classMethod)
187 | {
188 | // determine class prefix (eg "\Vendor\Bundle\Controller") and suffix (eg "Controller")
189 | $classNamePrefix = $this->config('controller.class_prefix');
190 | if ($classNamePrefix && substr($classNamePrefix, -strlen($classNamePrefix) !== '\\')) {
191 | $classNamePrefix .= '\\';
192 | }
193 | $classNameSuffix = $this->config('controller.class_suffix') ? : '';
194 |
195 | // determine method suffix or default to "Action"
196 | $methodNameSuffix = $this->config('controller.method_suffix');
197 | if (is_null($methodNameSuffix)) {
198 | $methodNameSuffix = 'Action';
199 | }
200 | $realClassMethod = $classMethod;
201 | if (strpos($realClassMethod, '\\') !== 0) {
202 | $realClassMethod = $classNamePrefix . $classMethod;
203 | }
204 |
205 | // having :
206 | if (preg_match('/^([a-zA-Z0-9\\\\_]+):([a-zA-Z0-9_]+)$/', $realClassMethod, $match)) {
207 | $className = $match[1] . $classNameSuffix;
208 | $methodName = $match[2] . $methodNameSuffix;
209 | } // malformed
210 | else {
211 | throw new \InvalidArgumentException(
212 | "Malformed class action for '$classMethod'. Use 'className:methodName' format."
213 | );
214 | }
215 |
216 | return array($className, $methodName);
217 | }
218 | }
219 |
--------------------------------------------------------------------------------
/src/SlimController/SlimController.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright 2012 Ulrich Kautz
8 | * @version 0.1.2
9 | * @package SlimController
10 | *
11 | * For the full copyright and license information, please view the LICENSE
12 | * file that was distributed with this source code.
13 | */
14 |
15 | namespace SlimController;
16 |
17 | /**
18 | * Implements a basic controller functionallity.
19 | * It should not be instanciated directly but extended from.
20 | */
21 | abstract class SlimController
22 | {
23 | /**
24 | * @const string
25 | */
26 | const VERSION = '0.1.4';
27 |
28 | /**
29 | * @var Slim
30 | */
31 | protected $app;
32 |
33 | /**
34 | * @var bool Whether cleanup params or not
35 | */
36 | protected $paramCleanup = false;
37 |
38 | /**
39 | * @var string Prefix for params
40 | */
41 | private $paramPrefix = 'data.';
42 |
43 | /**
44 | * @var array Stash of GET & POST params
45 | */
46 | private $paramsParams = null;
47 |
48 | /**
49 | * @var array Stash of GET params
50 | */
51 | private $paramsGet = null;
52 |
53 | /**
54 | * @var array Stash of POST params
55 | */
56 | private $paramsPost = null;
57 |
58 | /**
59 | * Suffix was never specified and defaults to empty string
60 | *
61 | * @var string
62 | */
63 | protected $renderTemplateSuffix = 'twig';
64 |
65 | /**
66 | * Constructor for TodoQueue\Controller\Login
67 | *
68 | * @param \Slim\Slim $app Ref to slim app
69 | */
70 | public function __construct(\Slim\Slim &$app)
71 | {
72 | $this->app = $app;
73 | if ($renderTemplateSuffix = $app->config('controller.template_suffix')) {
74 | $this->renderTemplateSuffix = $renderTemplateSuffix;
75 | }
76 | if (!is_null($paramPrefix = $app->config('controller.param_prefix'))) {
77 | $this->paramPrefix = $paramPrefix;
78 | $prefixLength = strlen($this->paramPrefix);
79 | if ($prefixLength > 0 && substr($this->paramPrefix, -$prefixLength) !== '.') {
80 | $this->paramPrefix .= '.';
81 | }
82 | }
83 | if ($app->config('controller.cleanup_params')) {
84 | $this->paramCleanup = true;
85 | }
86 | }
87 |
88 | /**
89 | * Renders output with given template
90 | *
91 | * @param string $template Name of the template to be rendererd
92 | * @param array $args Args for view
93 | */
94 | protected function render($template, $args = array())
95 | {
96 | if (!is_null($this->renderTemplateSuffix)
97 | && !preg_match('/\.' . $this->renderTemplateSuffix . '$/', $template)
98 | ) {
99 | $template .= '.' . $this->renderTemplateSuffix;
100 | }
101 | $this->app->render($template, $args);
102 | }
103 |
104 | /**
105 | * Performs redirect
106 | *
107 | * @param string $path
108 | */
109 | protected function redirect($path)
110 | {
111 | $this->app->redirect($path);
112 | }
113 |
114 | /**
115 | * Slim's request object
116 | *
117 | * @return \Slim\Http\Request
118 | */
119 | protected function request()
120 | {
121 | return $this->app->request();
122 | }
123 |
124 | /**
125 | * Slim's response object
126 | *
127 | * @return \Slim\Http\Response
128 | */
129 | protected function response()
130 | {
131 | return $this->app->response();
132 | }
133 |
134 | /**
135 | * Returns a single parameter of the "data[Object][Key]" format.
136 | *
137 | *
138 | * $paramValue = $this->param('prefix.name'); // prefix[name] -> "string value"
139 | * $paramValue = $this->param('prefix.name', 'post'); // prefix[name] -> "string value"
140 | * $paramValue = $this->param('prefix.name', 'get'); // prefix[name] -> "string value"
141 | *
142 | *
143 | * @param mixed $name Name of the parameter
144 | * @param mixed $reqMode Optional mode. Either null (all params), true | "post"
145 | * (only POST params), false | "get" (only GET params)
146 | * @param mixed $cleanup Whether use simple cleanup
147 | *
148 | * @return mixed Either array or single string or null
149 | */
150 | protected function param($name, $reqMode = null, $cleanup = null)
151 | {
152 | $cleanup = is_null($cleanup) ? $this->paramCleanup : $cleanup;
153 | $name = $this->paramPrefix . $name;
154 | $reqMeth = $this->paramAccessorMeth($reqMode);
155 |
156 | // determine stash name
157 | $reqStashName = 'params' . ucfirst($reqMeth);
158 | if (is_null($this->$reqStashName)) {
159 | $this->$reqStashName = $this->request()->$reqMeth();
160 | }
161 | $params = $this->$reqStashName;
162 |
163 | // split of parts and go through
164 | $parts = preg_split('/\./', $name);
165 | while (isset($params[$parts[0]])) {
166 | $params = $params[$parts[0]];
167 | array_shift($parts);
168 | if (empty($parts)) {
169 | return $cleanup === true ? $this->cleanupParam($params) : $params;
170 | }
171 | }
172 |
173 | return null;
174 | }
175 |
176 | /**
177 | * Reads multiple params at once
178 | *
179 | *
180 | * $params = $this->params(['prefix.name', 'other.name']); // -> ["prefix.name" => "value", ..]
181 | * $params = $this->params(['prefix.name', 'other.name'], true); // -> null if not all found
182 | * $params = $this->params(['prefix.name', 'other.name'], ['other.name' => "Default Value"]);
183 | *
184 | *
185 | * @param mixed $names Name or names of parameters (GET or POST)
186 | * @param mixed $reqMode Optional mode. Either null (all params), true | "post"
187 | * (only POST params), false | "get" (only GET params)
188 | * @param mixed $defaults Either true (require ALL given or return null), array (defaults)
189 | *
190 | * @return mixed Either array or single string or null
191 | */
192 | protected function params($names = array(), $reqMode = null, $defaults = null)
193 | {
194 | // no names given -> get them all
195 | if (!$names) {
196 | $names = $this->getAllParamNames($reqMode);
197 | }
198 | $res = array();
199 | foreach ($names as $obj) {
200 | $name = is_array($obj) ? $obj[0] : $obj;
201 | $param = $this->param($name, $reqMode);
202 | if (!is_null($param) && (!is_array($param) || !empty($param))) {
203 | $res[$name] = $param;
204 | } // if in "need all" mode
205 | elseif ($defaults === true) {
206 | return null;
207 | } // if in default mode
208 | elseif (is_array($defaults) && isset($defaults[$name])) {
209 | $res[$name] = $defaults[$name];
210 | }
211 | }
212 |
213 | return $res;
214 | }
215 |
216 | /**
217 | * Cleans up a single or a list of params by stripping HTML encodings
218 | *
219 | * @param string $value
220 | *
221 | * @return string
222 | */
223 | protected function cleanupParam($value)
224 | {
225 | if (is_array($value)) {
226 | foreach ($value as $k => $v) {
227 | $clean = $this->cleanupParam($v);
228 | if (!is_null($clean)) {
229 | $value[$k] = $clean;
230 | }
231 | }
232 |
233 | return $value;
234 | } else {
235 | return preg_replace('/>/', '', preg_replace('/', '', $value));
236 | }
237 | }
238 |
239 | /**
240 | * Flattens an array by transforming the form ["a" => ["b" => ["c" => 1]]] to ["a.b.c" => 1]
241 | *
242 | * @param array $data
243 | *
244 | * @return array
245 | */
246 | protected function flatten(array $data)
247 | {
248 | return $this->flattenInner($data);
249 | }
250 |
251 | private function flattenInner(array $data, $prefix = '', &$flat = array())
252 | {
253 | foreach ($data as $key => $value) {
254 | // is array -> flatten deep
255 | if (is_array($value)) {
256 | $this->flattenInner($value, $prefix . $key . '.', $flat);
257 | } // scalar -> use
258 | else {
259 | $flat[$prefix . $key] = $value;
260 | }
261 | }
262 |
263 | return $flat;
264 | }
265 |
266 | private function paramAccessorMeth($reqMode = null)
267 | {
268 | return $reqMode === true || $reqMode === 'post' // POST
269 | ? 'post'
270 | : ($reqMode === false || $reqMode === 'get' // GET
271 | ? 'get'
272 | : 'params' // ALL
273 | );
274 | }
275 |
276 | private function getAllParamNames($reqMode)
277 | {
278 | $reqMeth = $this->paramAccessorMeth($reqMode);
279 | $params = $this->request()->$reqMeth();
280 | $namesPre = $this->flatten($params);
281 | $names = array_keys($namesPre);
282 | if ($prefix = $this->paramPrefix) {
283 | $prefixLen = strlen($prefix);
284 | $names = array_map(function ($key) use ($prefixLen) {
285 | return substr($key, $prefixLen);
286 | }, array_filter($names, function ($in) use ($prefix) {
287 | return strpos($in, $prefix) === 0;
288 | }));
289 | }
290 |
291 | return $names;
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/Fixtures/Controller/TestController.php:
--------------------------------------------------------------------------------
1 | param('Some.param');
23 | }
24 |
25 | public function paramSingleArrayAction()
26 | {
27 | $obj = $this->param('Some');
28 | echo "Param is " . $obj['attrib1'] . $obj['attrib2'] . $obj['attrib3'];
29 | }
30 |
31 | public function paramMultiAction()
32 | {
33 | $params = $this->params(array('Some.param', 'Other.param', 'Other.missing'));
34 | echo json_encode($params);
35 | }
36 |
37 | public function paramMultiMissingReqAction()
38 | {
39 | $params = $this->params(array('Some.param', 'Other.param'), 'get', true);
40 | echo json_encode($params);
41 | }
42 |
43 | public function paramMultiDefaultAction()
44 | {
45 | $params = $this->params(array('Some.param', 'Other.param', 'Other.bla'), 'get', array('Other.bla' => 'great'));
46 | echo json_encode($params);
47 | }
48 |
49 | public function paramGetAllAction()
50 | {
51 | $params = $this->params();
52 | echo json_encode($params);
53 | }
54 |
55 | public function paramCleanupAction()
56 | {
57 | $messedUp = array('foo', 'Notgood');
58 | echo json_encode($this->cleanupParam($messedUp));
59 | }
60 |
61 | public function renderAction()
62 | {
63 | $this->render('rendertest', array('foo' => 'orotound', 'bar' => 'grandios'));
64 | }
65 |
66 | public function redirectAction()
67 | {
68 | $this->redirect('/here');
69 | }
70 |
71 | public function notSuffixedMethod()
72 | {
73 | echo "Yes, I was called";
74 | }
75 |
76 | }
--------------------------------------------------------------------------------
/tests/SlimController/Tests/Fixtures/templates/rendertest.php:
--------------------------------------------------------------------------------
1 | This is and
--------------------------------------------------------------------------------
/tests/SlimController/Tests/Integration/CanCreateApplicationTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(true); // if we got this far then creating the application worked
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/Old/ControllerTest.php:
--------------------------------------------------------------------------------
1 | expectOutputString('What is up?');
11 | $this->setUrl('/');
12 | $this->app->addRoutes(array(
13 | '/' => 'Test:index',
14 | ));
15 |
16 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
17 | //$this->app->router()->dispatch($route);
18 | $route->dispatch();
19 | }
20 |
21 | public function testControllerExtended()
22 | {
23 | $this->expectOutputString('What is up YOU?');
24 | $this->setUrl('/hello/YOU');
25 | $this->app->addRoutes(array(
26 | '/hello/:name' => 'Test:hello',
27 | ));
28 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
29 | //$this->app->router()->dispatch($route);
30 | $route->dispatch();
31 | }
32 |
33 | public function testControllerAbsPath()
34 | {
35 | $this->expectOutputString('What is up YOU?');
36 | $this->setUrl('/hello/YOU');
37 | $this->app->addRoutes(array(
38 | '/hello/:name' => 'Test:hello',
39 | ));
40 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
41 | //$this->app->router()->dispatch($route);
42 | $route->dispatch();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/Old/ParamsTest.php:
--------------------------------------------------------------------------------
1 | expectOutputString('Param is 123');
12 | $this->setUrl('/', 'data[Some][param]=123');
13 | $this->app->addRoutes(array(
14 | '/' => 'Test:paramSingle',
15 | ));
16 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
17 | //$this->app->router()->dispatch($route);
18 | $route->dispatch();
19 | }
20 |
21 |
22 | public function testParamsSingleObject()
23 | {
24 | $this->expectOutputString('Param is 123123123');
25 | $this->setUrl('/', 'data[Some][attrib1]=123&data[Some][attrib2]=123&data[Some][attrib3]=123');
26 | $this->app->addRoutes(array(
27 | '/' => 'Test:paramSingleObject',
28 | ));
29 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
30 | //$this->app->router()->dispatch($route);
31 | $route->dispatch();
32 | }
33 |
34 | public function testParamsMulti()
35 | {
36 | $this->expectOutputString('All is foo bar');
37 | $this->setUrl('/', 'data[Some][param]=foo&data[Other][param]=bar');
38 | $this->app->addRoutes(array(
39 | '/' => 'Test:paramMulti',
40 | ));
41 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
42 | //$this->app->router()->dispatch($route);
43 | $route->dispatch();
44 | }
45 |
46 | public function testParamsMultiMissing()
47 | {
48 | $this->expectOutputString('All is foo bar');
49 | $this->setUrl('/', 'data[Some][param]=foo&data[Other][param]=bar');
50 | $this->app->addRoutes(array(
51 | '/' => 'Test:paramMultiMissing',
52 | ));
53 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
54 | //$this->app->router()->dispatch($route);
55 | $route->dispatch();
56 | }
57 |
58 | public function testParamsMultiMissingReq()
59 | {
60 | $this->expectOutputString('OK');
61 | $this->setUrl('/', 'data[Some][param]=foo&data[Other][param]=bar');
62 | $this->app->addRoutes(array(
63 | '/' => 'Test:paramMultiMissingReq',
64 | ));
65 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
66 | //$this->app->router()->dispatch($route);
67 | $route->dispatch();
68 | }
69 |
70 | public function testParamsMultiDefault()
71 | {
72 | $this->expectOutputString('All is foo bar and great');
73 | $this->setUrl('/', 'data[Some][param]=foo&data[Other][param]=bar');
74 | $this->app->addRoutes(array(
75 | '/' => 'Test:paramMultiDefault',
76 | ));
77 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
78 | //$this->app->router()->dispatch($route);
79 | $route->dispatch();
80 | }
81 |
82 | public function testParamsDifferentPrefix()
83 | {
84 | $this->expectOutputString('GOT OK');
85 | $this->setUrl('/', 'data[Foo]=bar&other[Foo]=bar', array(
86 | 'controller.param_prefix' => 'other.'
87 | ));
88 | $this->app->addRoutes(array(
89 | '/' => 'Test:paramDifferentPrefix',
90 | ));
91 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
92 | //$this->app->router()->dispatch($route);
93 | $route->dispatch();
94 | }
95 |
96 | public function testParamsNoPrefix()
97 | {
98 | $this->expectOutputString('All params: data.Foo=bar - other.Foo=bar');
99 | $this->setUrl('/', 'data[Foo]=bar&other[Foo]=bar', array(
100 | 'controller.param_prefix' => ''
101 | ));
102 | $this->app->addRoutes(array(
103 | '/' => 'Test:paramNoPrefix',
104 | ));
105 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
106 | //$this->app->router()->dispatch($route);
107 | $route->dispatch();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/Old/RenderTest.php:
--------------------------------------------------------------------------------
1 | expectOutputString('This is orotound and grandios');
11 | $this->setUrl('/', 'data[Some][param]=foo&data[Other][param]=bar');
12 | $this->app->addRoutes(array(
13 | '/' => 'Test:render',
14 | ));
15 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
16 | //$this->app->router()->dispatch($route);
17 | $route->dispatch();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/Old/RoutingTest.php:
--------------------------------------------------------------------------------
1 | setUrl('/');
11 | $this->app->addRoutes(array(
12 | '/' => 'Controller:index',
13 | ));
14 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
15 |
16 | $this->setUrl('/foo');
17 | $this->assertEquals(0, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
18 |
19 | $this->setUrl('/other');
20 |
21 | $this->app->addRoutes(array(
22 | '/other' => 'Controller:other',
23 | ));
24 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
25 | }
26 |
27 | public function testRoutesWithVariables()
28 | {
29 | $this->setUrl('/hello/you');
30 | $this->app->addRoutes(array(
31 | '/hello/:name' => 'Controller:index',
32 | ));
33 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
34 | }
35 |
36 | public function testRoutesWithExtendedFormat()
37 | {
38 | $this->setUrl('/bla');
39 | $this->app->addRoutes(array(
40 | '/bla' => array('Controller:index', 'get')
41 | ));
42 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/SlimControllerTest.php:
--------------------------------------------------------------------------------
1 | slim = m::mock('\Slim\Slim');
22 | parent::setUp();
23 | }
24 |
25 | public function tearDown()
26 | {
27 | $this->addToAssertionCount($this->slim->mockery_getExpectationCount());
28 | m::close();
29 | parent::tearDown();
30 | }
31 |
32 | public function testControllerConfigParamsAreUsed()
33 | {
34 | $this->slim->shouldReceive('config')
35 | ->once()
36 | ->with('controller.template_suffix')
37 | ->andReturnNull();
38 | $this->slim->shouldReceive('config')
39 | ->once()
40 | ->with('controller.param_prefix')
41 | ->andReturnNull();
42 | $this->slim->shouldReceive('config')
43 | ->once()
44 | ->with('controller.cleanup_params')
45 | ->andReturnNull();
46 | $controller = new TestController($this->slim);
47 | $this->assertTrue(true);
48 | }
49 |
50 | public function testRenderingWorksFine()
51 | {
52 | $this->assertDefaultConstruction();
53 | $this->slim->shouldReceive('render')
54 | ->once()
55 | ->with('rendertest.Suffix', array('foo' => 'orotound', 'bar' => 'grandios'));
56 |
57 | $controller = new TestController($this->slim);
58 | $controller->renderAction();
59 | }
60 |
61 | public function testRedirectWorksFine()
62 | {
63 | $this->assertDefaultConstruction();
64 | $this->slim->shouldReceive('redirect')
65 | ->once()
66 | ->with('/here');
67 |
68 | $controller = new TestController($this->slim);
69 | $controller->redirectAction();
70 | }
71 |
72 | public function testSingleParamLeafAccessWorks()
73 | {
74 | $this->expectOutputString("Param is foo");
75 | $this->assertDefaultConstruction();
76 | $request = m::mock();
77 | $this->slim->shouldReceive('request')
78 | ->once()
79 | ->withNoArgs()
80 | ->andReturn($request);
81 | $request->shouldReceive('params')
82 | ->once()
83 | ->withNoArgs()
84 | ->andReturn(array('Some' => array('param' => 'foo')));
85 |
86 | $controller = new TestController($this->slim);
87 | $controller->paramSingleAction();
88 | }
89 |
90 | public function testSingleParamArrayAccessWorks()
91 | {
92 | $this->expectOutputString("Param is foobarbaz");
93 | $this->assertDefaultConstruction();
94 | $request = m::mock();
95 | $this->slim->shouldReceive('request')
96 | ->once()
97 | ->withNoArgs()
98 | ->andReturn($request);
99 | $request->shouldReceive('params')
100 | ->once()
101 | ->withNoArgs()
102 | ->andReturn(array('Some' => array('attrib1' => 'foo', 'attrib2' => 'bar', 'attrib3' => 'baz')));
103 |
104 | $controller = new TestController($this->slim);
105 | $controller->paramSingleArrayAction();
106 | }
107 |
108 | public function testMultiParamAccessWorks()
109 | {
110 | $this->expectOutputString('{"Some.param":"foo","Other.param":"bar"}');
111 | $this->assertDefaultConstruction();
112 | $request = m::mock();
113 | $this->slim->shouldReceive('request')
114 | ->once()
115 | ->withNoArgs()
116 | ->andReturn($request);
117 | $request->shouldReceive('params')
118 | ->once()
119 | ->withNoArgs()
120 | ->andReturn(array('Some' => array('param' => 'foo'), 'Other' => array('param' => 'bar')));
121 |
122 | $controller = new TestController($this->slim);
123 | $controller->paramMultiAction();
124 | }
125 |
126 | public function testMultiParamAccessWithRequiredParams()
127 | {
128 | $this->expectOutputString('{"Some.param":"foo","Other.param":"bar"}');
129 | $this->assertDefaultConstruction();
130 | $request = m::mock();
131 | $this->slim->shouldReceive('request')
132 | ->once()
133 | ->withNoArgs()
134 | ->andReturn($request);
135 | $request->shouldReceive('get')
136 | ->once()
137 | ->withNoArgs()
138 | ->andReturn(array('Some' => array('param' => 'foo'), 'Other' => array('param' => 'bar')));
139 |
140 | $controller = new TestController($this->slim);
141 | $controller->paramMultiMissingReqAction();
142 | }
143 |
144 | public function testMultiParamAccessWithRequiredParamsWhichAreMissing()
145 | {
146 | $this->expectOutputString('null');
147 | $this->assertDefaultConstruction();
148 | $request = m::mock();
149 | $this->slim->shouldReceive('request')
150 | ->once()
151 | ->withNoArgs()
152 | ->andReturn($request);
153 | $request->shouldReceive('get')
154 | ->once()
155 | ->withNoArgs()
156 | ->andReturn(array('Some' => array('param' => 'foo')));
157 |
158 | $controller = new TestController($this->slim);
159 | $controller->paramMultiMissingReqAction();
160 | }
161 |
162 | public function testMultiParamAccessWithDefaultValues()
163 | {
164 | $this->expectOutputString('{"Some.param":"foo","Other.bla":"great"}');
165 | $this->assertDefaultConstruction();
166 | $request = m::mock();
167 | $this->slim->shouldReceive('request')
168 | ->once()
169 | ->withNoArgs()
170 | ->andReturn($request);
171 | $request->shouldReceive('get')
172 | ->once()
173 | ->withNoArgs()
174 | ->andReturn(array('Some' => array('param' => 'foo')));
175 |
176 | $controller = new TestController($this->slim);
177 | $controller->paramMultiDefaultAction();
178 | }
179 |
180 | public function testGetAllAvailableParams()
181 | {
182 | $this->expectOutputString('{"Some.param":"foo","Other":"bar"}');
183 | $this->assertDefaultConstruction();
184 | $request = m::mock();
185 | $this->slim->shouldReceive('request')
186 | ->twice()
187 | ->withNoArgs()
188 | ->andReturn($request);
189 | $request->shouldReceive('params')
190 | ->twice()
191 | ->withNoArgs()
192 | ->andReturn(array('Some' => array('param' => 'foo'), 'Other' => 'bar'));
193 |
194 | $controller = new TestController($this->slim);
195 | $controller->paramGetAllAction();
196 | }
197 |
198 | public function testGetAllAvailableParamsWithPrefix()
199 | {
200 | $this->expectOutputString('{"Some.param":"foo"}');
201 | $this->assertDefaultConstruction('Suffix', 'data');
202 | $request = m::mock();
203 | $this->slim->shouldReceive('request')
204 | ->twice()
205 | ->withNoArgs()
206 | ->andReturn($request);
207 | $request->shouldReceive('params')
208 | ->twice()
209 | ->withNoArgs()
210 | ->andReturn(array('data' => array('Some' => array('param' => 'foo')), 'Other' => 'bar'));
211 |
212 | $controller = new TestController($this->slim);
213 | $controller->paramGetAllAction();
214 | }
215 |
216 | public function testUseSimpleNoCleanup()
217 | {
218 | $this->expectOutputString('{"Some.param":"foo","Other":"bar"}');
219 | $this->assertDefaultConstruction('Suffix', '', false);
220 | $request = m::mock();
221 | $this->slim->shouldReceive('request')
222 | ->twice()
223 | ->withNoArgs()
224 | ->andReturn($request);
225 | $request->shouldReceive('params')
226 | ->twice()
227 | ->withNoArgs()
228 | ->andReturn(array('Some' => array('param' => 'foo'), 'Other' => 'bar'));
229 |
230 | $controller = new TestController($this->slim);
231 | $controller->paramGetAllAction();
232 | }
233 |
234 | public function testUseSimpleCleanup()
235 | {
236 | $this->expectOutputString('{"Some.param":"foobla","Other":"bar"}');
237 | $this->assertDefaultConstruction('Suffix', '', true);
238 | $request = m::mock();
239 | $this->slim->shouldReceive('request')
240 | ->twice()
241 | ->withNoArgs()
242 | ->andReturn($request);
243 | $request->shouldReceive('params')
244 | ->twice()
245 | ->withNoArgs()
246 | ->andReturn(array('Some' => array('param' => 'foo'), 'Other' => 'bar'));
247 |
248 | $controller = new TestController($this->slim);
249 | $controller->paramGetAllAction();
250 | }
251 |
252 | public function testArrayCleanup()
253 | {
254 | $this->expectOutputString('["foobar","otherNotgood"]');
255 | $this->assertDefaultConstruction('Suffix', '', true);
256 | $controller = new TestController($this->slim);
257 | $controller->paramCleanupAction();
258 | }
259 |
260 |
261 | protected function assertDefaultConstruction($suffix = 'Suffix', $paramPrefix = '', $cleanupParams = false)
262 | {
263 | $this->slim->shouldReceive('config')
264 | ->once()
265 | ->with('controller.template_suffix')
266 | ->andReturn($suffix);
267 | $this->slim->shouldReceive('config')
268 | ->once()
269 | ->with('controller.param_prefix')
270 | ->andReturn($paramPrefix);
271 | $this->slim->shouldReceive('config')
272 | ->once()
273 | ->with('controller.cleanup_params')
274 | ->andReturn($cleanupParams);
275 | }
276 |
277 | }
278 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/SlimTest.php:
--------------------------------------------------------------------------------
1 | setUrl('/bla');
18 | $this->app->addRoutes(array(
19 | '/bla' => array('get' => 'Controller:index'),
20 | '/alb' => array('get' => 'Controller:index')
21 | ));
22 |
23 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
24 | // $this->assertTrue($this->app->router->hasNamedRoute('Controller:index'));
25 | $this->assertEquals('/bla', $this->app->urlFor('Controller:index'));
26 | }
27 |
28 | public function testAddingroutesWithOldSyntaxWithoutMiddlewares()
29 | {
30 | $this->setUrl('/bla');
31 | $this->app->addRoutes(array(
32 | '/bla' => array('Controller:index'),
33 | ));
34 |
35 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
36 | }
37 |
38 | public function testAddRoutesWithOldSyntaxWithoutMiddlewareArray()
39 | {
40 | $this->setUrl('/');
41 | $this->app->addRoutes(array(
42 | '/' => array('Home:index', function() {
43 | //
44 | })
45 | ));
46 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
47 | }
48 |
49 | public function testAddRoutesWithOldSyntaxWithMiddlewareArray()
50 | {
51 | $this->setUrl('/');
52 | $this->app->addRoutes(array(
53 | '/' => array('Home:index', array(function() {
54 | //
55 | }))
56 | ));
57 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
58 | }
59 |
60 | public function testAddSimpleRoutes()
61 | {
62 | $this->setUrl('/');
63 | $this->app->addRoutes(array(
64 | '/' => 'Controller:index',
65 | ));
66 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
67 |
68 | $this->setUrl('/foo');
69 | $this->assertEquals(0, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
70 |
71 | $this->setUrl('/other');
72 |
73 | $this->app->addRoutes(array(
74 | '/other' => 'Controller:other',
75 | ));
76 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
77 | }
78 |
79 | public function testAddRoutesWithVariables()
80 | {
81 | $this->setUrl('/hello/you');
82 | $this->app->addRoutes(array(
83 | '/hello/:name' => 'Controller:index',
84 | ));
85 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
86 | }
87 |
88 | public function testAddRoutesInExtendedFormat()
89 | {
90 | $this->setUrl('/bla');
91 | $this->app->addRoutes(array(
92 | '/bla' => array('get' => 'Controller:index')
93 | ));
94 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
95 | }
96 |
97 | /**
98 | * @expectedException \InvalidArgumentException
99 | * @expectedExceptionMessage Malformed class action for 'Controller:index:foo'. Use 'className:methodName' format.
100 | */
101 | public function testFailToAddInvalidClassMethodFormat()
102 | {
103 | $this->setUrl('/bla');
104 | $this->app->addRoutes(array(
105 | '/bla' => 'Controller:index:foo'
106 | ));
107 | }
108 |
109 | public function testGlobalMiddlewareIsAddedToRoute()
110 | {
111 | $this->setUrl('/bla');
112 | $this->app->addRoutes(array(
113 | '/bla' => 'Controller:index'
114 | ), function() {
115 | return false;
116 | });
117 |
118 | /** @var \Slim\Route[] $routes */
119 | $routes = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
120 | $this->assertEquals(1, count($routes));
121 |
122 | $middleware = $routes[0]->getMiddleware();
123 | $this->assertInternalType('array', $middleware);
124 | $this->assertSame(1, count($middleware));
125 | }
126 |
127 | public function testGlobalMiddlewareIsAddedToRouteAsArray()
128 | {
129 | $middlewares = array(
130 | function() { return false; },
131 | function() { return false; }
132 | );
133 |
134 | $this->setUrl('/bla');
135 | $this->app->addRoutes(array(
136 | '/bla' => 'Controller:index'
137 | ), $middlewares);
138 |
139 | /** @var \Slim\Route[] $routes */
140 | $routes = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
141 | $this->assertEquals(1, count($routes));
142 |
143 | $middleware = $routes[0]->getMiddleware();
144 | $this->assertInternalType('array', $middleware);
145 | $this->assertSame(2, count($middleware));
146 | }
147 |
148 | public function testLocalMiddlewareIsAddedToRoute()
149 | {
150 | $this->setUrl('/bla');
151 | $this->app->addRoutes(array(
152 | '/bla' => array('get' => array('Controller:index', function() {
153 | return false;
154 | }))
155 | ));
156 |
157 | /** @var \Slim\Route[] $routes */
158 | $routes = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
159 | $this->assertEquals(1, count($routes));
160 |
161 | $middleware = $routes[0]->getMiddleware();
162 | $this->assertInternalType('array', $middleware);
163 | $this->assertSame(1, count($middleware));
164 | }
165 |
166 | public function testArrayOfLocalMiddlewareIsAddedToRoute()
167 | {
168 | $middlewares = array(
169 | function() { return false; },
170 | function() { return false; }
171 | );
172 |
173 | $this->setUrl('/bla');
174 | $this->app->addRoutes(array(
175 | '/bla' => array('get' => array('Controller:index', $middlewares))
176 | ));
177 |
178 | /** @var \Slim\Route[] $routes */
179 | $routes = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
180 | $this->assertEquals(1, count($routes));
181 |
182 | $middleware = $routes[0]->getMiddleware();
183 | $this->assertInternalType('array', $middleware);
184 | $this->assertSame(2, count($middleware));
185 | }
186 |
187 | public function testLocalMiddlewaresAreAddedToRoute()
188 | {
189 | $middlewares = array(
190 | function() { return false; },
191 | function() { return false; }
192 | );
193 |
194 | $this->setUrl('/bla');
195 | $this->app->addRoutes(array(
196 | '/bla' => array('get' => array('Controller:index', $middlewares[0], $middlewares[1]))
197 | ));
198 |
199 | /** @var \Slim\Route[] $routes */
200 | $routes = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
201 | $this->assertEquals(1, count($routes));
202 |
203 | $middleware = $routes[0]->getMiddleware();
204 | $this->assertInternalType('array', $middleware);
205 | $this->assertSame(2, count($middleware));
206 | }
207 |
208 | public function testGlobalAndLocalMiddlewareIsAddedToRoute()
209 | {
210 | $this->setUrl('/bla');
211 | $this->app->addRoutes(array(
212 | '/bla' => array('get' => array('Controller:index', function() {
213 | return false;
214 | }))
215 | ), array(function() {
216 | return false;
217 | }, function() {
218 | return false;
219 | }));
220 |
221 | /** @var \Slim\Route[] $routes */
222 | $routes = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
223 | $this->assertEquals(1, count($routes));
224 |
225 | $middleware = $routes[0]->getMiddleware();
226 | $this->assertInternalType('array', $middleware);
227 | $this->assertSame(3, count($middleware));
228 | }
229 |
230 | /**
231 | * @expectedException \InvalidArgumentException
232 | * @expectedExceptionMessage Http method 'FOO' is not supported.
233 | */
234 | public function testFailToAddRouteForUnsupportedHttpMethod()
235 | {
236 | $this->setUrl('/bla');
237 | $this->app->addRoutes(array(
238 | '/bla' => array('foo' => 'Controller:index')
239 | ));
240 | }
241 |
242 | public function testRouteCallbacksAreFiredOnDispatch()
243 | {
244 | $this->expectOutputString('What is up?');
245 | $this->setUrl('/bla');
246 | $this->app->addRoutes(array(
247 | '/bla' => 'Test:index'
248 | ));
249 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
250 | $route->dispatch();
251 | }
252 |
253 | public function testEmptyButNotNullMethodSuffixAccepted()
254 | {
255 | $this->expectOutputString('Yes, I was called');
256 | $this->setUrl('/bla', '', array(
257 | 'controller.method_suffix' => ''
258 | ));
259 | $this->app->addRoutes(array(
260 | '/bla' => 'Test:notSuffixedMethod'
261 | ));
262 | list($route) = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
263 | $route->dispatch();
264 | }
265 |
266 | public function testAddControllerRoute()
267 | {
268 | $this->setUrl('/');
269 | $this->app->addControllerRoute(
270 | '/', 'Controller:index'
271 | )->via('GET');
272 |
273 | $this->assertEquals(1, count($this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
274 | }
275 |
276 | public function testAddControllerRouteWithMiddleware()
277 | {
278 | $this->setUrl('/');
279 | $this->app->addControllerRoute(
280 | '/', 'Controller:index', array(
281 | function() {
282 | return false;
283 | },
284 | )
285 | )->via('GET');
286 |
287 | /** @var \Slim\Route[] $routes */
288 | $routes = $this->app->router()->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri());
289 | $this->assertEquals(1, count($routes));
290 |
291 | $middleware = $routes[0]->getMiddleware();
292 | $this->assertInternalType('array', $middleware);
293 | $this->assertSame(1, count($middleware));
294 | }
295 |
296 | public function testNamedRoutes()
297 | {
298 | $this->setUrl('/');
299 | $this->app->addRoutes(array(
300 | '/' => 'Controller:index',
301 | '/bla' => 'Bla:Index',
302 | '/something/:id' => 'Something:show'
303 | ));
304 |
305 | $this->assertEquals('/', $this->app->urlFor('Controller:index'));
306 | $this->assertEquals('/bla', $this->app->urlFor('Bla:Index'));
307 | $this->assertEquals('/something/:id', $this->app->urlFor('Something:show'));
308 | }
309 |
310 | /**
311 | * @expectedException \RuntimeException
312 | * @expectedExceptionMessage Named route not found for name: this is not a named route
313 | */
314 | public function testNamedRoutesThrowsExceptionIfLookingForARouteThatDoesNotExist()
315 | {
316 | $this->setUrl('/');
317 | $this->app->addRoutes(array(
318 | '/' => 'Controller:index',
319 | '/bla' => 'Bla:Index',
320 | '/something/:id' => 'Something:show'
321 | ));
322 |
323 | $this->assertEquals('/', $this->app->urlFor('this is not a named route'));
324 | }
325 |
326 | public function testServiceControllersAreFetched()
327 | {
328 | $this->expectOutputString("What is up?");
329 |
330 | $config = array(
331 | 'controller.class_prefix' => '',
332 | 'controller.class_suffix' => '',
333 | );
334 | $this->setUrl('/', '', $config);
335 | $app = $this->app;
336 | $app->container->singleton('TestController', function () use ($app) {
337 | return new TestController($app);
338 | });
339 |
340 | $route = $this->app->addControllerRoute(
341 | '/', 'TestController:index'
342 | )->via('GET');
343 |
344 | // If the route could be dispatched, then the service was found
345 | $result = $route->dispatch();
346 | $this->assertTrue($result);
347 | }
348 |
349 | public function testServiceControllersAreFetchedWithParams()
350 | {
351 | $this->expectOutputString("What is up foo?");
352 |
353 | $config = array(
354 | 'controller.class_prefix' => '',
355 | 'controller.class_suffix' => '',
356 | );
357 | $this->setUrl('/', '', $config);
358 | $app = $this->app;
359 | $app->container->singleton('TestController', function () use ($app) {
360 | return new TestController($app);
361 | });
362 |
363 | $app->addRoutes(array(
364 | '/another/:name' => 'TestController:hello'
365 | ));
366 | $route = $app->router()->getNamedRoute('TestController:hello');
367 | $route->setParams(array('name' => 'foo'));
368 | $this->assertTrue($route->dispatch());
369 | }
370 |
371 | public function testServiceControllersAreFetchedEvenIfTheirNameIsAnInvalidPHPClassName()
372 | {
373 | $this->expectOutputString("What is up?");
374 |
375 | $config = array(
376 | 'controller.class_prefix' => '',
377 | 'controller.class_suffix' => '',
378 | );
379 | $this->setUrl('/', '', $config);
380 | $app = $this->app;
381 | $app->container->singleton('String\\Controller', function () use ($app) {
382 | return new TestController($app);
383 | });
384 |
385 | $route = $this->app->addControllerRoute(
386 | '/', 'String\\Controller:index'
387 | )->via('GET');
388 |
389 | // If the route could be dispatched, then the service was found
390 | $result = $route->dispatch();
391 | $this->assertTrue($result);
392 | }
393 |
394 | }
395 |
--------------------------------------------------------------------------------
/tests/SlimController/Tests/TestCase.php:
--------------------------------------------------------------------------------
1 | 'GET',
38 | 'REMOTE_ADDR' => '127.0.0.1',
39 | 'SCRIPT_NAME' => '', //<-- Physical
40 | 'PATH_INFO' => $path, //<-- Virtual
41 | 'QUERY_STRING' => $params,
42 | 'SERVER_NAME' => 'slim',
43 | 'SERVER_PORT' => 80,
44 | 'slim.url_scheme' => 'http',
45 | 'slim.input' => '',
46 | 'slim.errors' => fopen('php://stderr', 'w'),
47 | 'HTTP_HOST' => 'slim'
48 | ));
49 | $this->env = Environment::getInstance();
50 | $this->req = new Request($this->env);
51 | $this->res = new Response();
52 | $this->app = new Slim(array_merge(array(
53 | 'controller.class_prefix' => '\\SlimController\\Tests\\Fixtures\\Controller',
54 | 'controller.class_suffix' => 'Controller',
55 | 'controller.method_suffix' => 'Action',
56 | 'controller.template_suffix' => 'php',
57 | 'templates.path' => __DIR__ . '/Fixtures/templates'
58 | ), $config));
59 | }
60 | }
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | add('SlimController\\Tests\\', __DIR__);
6 | $loader->register();
7 |
8 | /*include 'SlimControllerUnitTestCase.php';
9 | include 'Controller/Test.php';*/
--------------------------------------------------------------------------------