├── Slim ├── Exception │ ├── NotFoundException.php │ ├── InvalidMethodException.php │ ├── ContainerException.php │ ├── ContainerValueNotFoundException.php │ ├── MethodNotAllowedException.php │ └── SlimException.php ├── Interfaces │ ├── Http │ │ ├── EnvironmentInterface.php │ │ ├── HeadersInterface.php │ │ └── CookiesInterface.php │ ├── CallableResolverInterface.php │ ├── CollectionInterface.php │ ├── RouteGroupInterface.php │ ├── InvocationStrategyInterface.php │ ├── RouterInterface.php │ └── RouteInterface.php ├── Http │ ├── Body.php │ ├── RequestBody.php │ ├── Environment.php │ ├── Cookies.php │ ├── Headers.php │ ├── Message.php │ ├── UploadedFile.php │ ├── Stream.php │ └── Response.php ├── DeferredCallable.php ├── RouteGroup.php ├── Handlers │ ├── Strategies │ │ ├── RequestResponseArgs.php │ │ └── RequestResponse.php │ ├── AbstractHandler.php │ ├── AbstractError.php │ ├── NotFound.php │ ├── NotAllowed.php │ ├── PhpError.php │ └── Error.php ├── CallableResolverAwareTrait.php ├── Routable.php ├── CallableResolver.php ├── MiddlewareAwareTrait.php ├── Collection.php ├── Container.php ├── DefaultServicesProvider.php ├── Route.php ├── Router.php └── App.php ├── LICENSE.md └── composer.json /Slim/Exception/NotFoundException.php: -------------------------------------------------------------------------------- 1 | request = $request; 14 | parent::__construct(sprintf('Unsupported HTTP method "%s" provided', $method)); 15 | } 16 | 17 | public function getRequest() 18 | { 19 | return $this->request; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Slim/Exception/ContainerException.php: -------------------------------------------------------------------------------- 1 | callable = $callable; 31 | $this->container = $container; 32 | } 33 | 34 | public function __invoke() 35 | { 36 | $callable = $this->resolveCallable($this->callable); 37 | if ($callable instanceof Closure) { 38 | $callable = $callable->bindTo($this->container); 39 | } 40 | 41 | $args = func_get_args(); 42 | 43 | return call_user_func_array($callable, $args); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Slim/Exception/MethodNotAllowedException.php: -------------------------------------------------------------------------------- 1 | allowedMethods = $allowedMethods; 34 | } 35 | 36 | /** 37 | * Get allowed methods 38 | * 39 | * @return string[] 40 | */ 41 | public function getAllowedMethods() 42 | { 43 | return $this->allowedMethods; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Slim/RouteGroup.php: -------------------------------------------------------------------------------- 1 | pattern = $pattern; 30 | $this->callable = $callable; 31 | } 32 | 33 | /** 34 | * Invoke the group to register any Routable objects within it. 35 | * 36 | * @param App $app The App to bind the callable to. 37 | */ 38 | public function __invoke(App $app = null) 39 | { 40 | $callable = $this->resolveCallable($this->callable); 41 | if ($callable instanceof Closure && $app !== null) { 42 | $callable = $callable->bindTo($app); 43 | } 44 | 45 | $callable(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Slim/Handlers/Strategies/RequestResponseArgs.php: -------------------------------------------------------------------------------- 1 | container instanceof ContainerInterface) { 39 | return $callable; 40 | } 41 | 42 | /** @var CallableResolverInterface $resolver */ 43 | $resolver = $this->container->get('callableResolver'); 44 | 45 | return $resolver->resolve($callable); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Slim/Handlers/Strategies/RequestResponse.php: -------------------------------------------------------------------------------- 1 | $v) { 38 | $request = $request->withAttribute($k, $v); 39 | } 40 | 41 | return call_user_func($callable, $request, $response, $routeArguments); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Slim/Exception/SlimException.php: -------------------------------------------------------------------------------- 1 | request = $request; 47 | $this->response = $response; 48 | } 49 | 50 | /** 51 | * Get request 52 | * 53 | * @return ServerRequestInterface 54 | */ 55 | public function getRequest() 56 | { 57 | return $this->request; 58 | } 59 | 60 | /** 61 | * Get response 62 | * 63 | * @return ResponseInterface 64 | */ 65 | public function getResponse() 66 | { 67 | return $this->response; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slim/slim", 3 | "type": "library", 4 | "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", 5 | "keywords": ["framework","micro","api","router"], 6 | "homepage": "https://slimframework.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Josh Lockhart", 11 | "email": "hello@joshlockhart.com", 12 | "homepage": "https://joshlockhart.com" 13 | }, 14 | { 15 | "name": "Andrew Smith", 16 | "email": "a.smith@silentworks.co.uk", 17 | "homepage": "http://silentworks.co.uk" 18 | }, 19 | { 20 | "name": "Rob Allen", 21 | "email": "rob@akrabat.com", 22 | "homepage": "http://akrabat.com" 23 | }, 24 | { 25 | "name": "Gabriel Manricks", 26 | "email": "gmanricks@me.com", 27 | "homepage": "http://gabrielmanricks.com" 28 | } 29 | ], 30 | "require": { 31 | "php": ">=5.5.0", 32 | "pimple/pimple": "^3.0", 33 | "psr/http-message": "^1.0", 34 | "nikic/fast-route": "^1.0", 35 | "container-interop/container-interop": "^1.2", 36 | "psr/container": "^1.0" 37 | }, 38 | "require-dev": { 39 | "squizlabs/php_codesniffer": "^2.5", 40 | "phpunit/phpunit": "^4.0" 41 | }, 42 | "provide": { 43 | "psr/http-message-implementation": "1.0" 44 | }, 45 | "autoload": { 46 | "psr-4": { 47 | "Slim\\": "Slim" 48 | } 49 | }, 50 | "scripts": { 51 | "test": [ 52 | "@phpunit", 53 | "@phpcs" 54 | ], 55 | "phpunit": "php vendor/bin/phpunit", 56 | "phpcs": "php vendor/bin/phpcs" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Slim/Http/Environment.php: -------------------------------------------------------------------------------- 1 | 'HTTP/1.1', 34 | 'REQUEST_METHOD' => 'GET', 35 | 'SCRIPT_NAME' => '', 36 | 'REQUEST_URI' => '', 37 | 'QUERY_STRING' => '', 38 | 'SERVER_NAME' => 'localhost', 39 | 'SERVER_PORT' => 80, 40 | 'HTTP_HOST' => 'localhost', 41 | 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 42 | 'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', 43 | 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 44 | 'HTTP_USER_AGENT' => 'Slim Framework', 45 | 'REMOTE_ADDR' => '127.0.0.1', 46 | 'REQUEST_TIME' => time(), 47 | 'REQUEST_TIME_FLOAT' => microtime(true), 48 | ], $userData); 49 | 50 | return new static($data); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Slim/Handlers/AbstractHandler.php: -------------------------------------------------------------------------------- 1 | getHeaderLine('Accept'); 43 | $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes); 44 | 45 | if (count($selectedContentTypes)) { 46 | return current($selectedContentTypes); 47 | } 48 | 49 | // handle +json and +xml specially 50 | if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) { 51 | $mediaType = 'application/' . $matches[1]; 52 | if (in_array($mediaType, $this->knownContentTypes)) { 53 | return $mediaType; 54 | } 55 | } 56 | 57 | return 'text/html'; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Slim/Routable.php: -------------------------------------------------------------------------------- 1 | middleware; 59 | } 60 | 61 | /** 62 | * Get the route pattern 63 | * 64 | * @return string 65 | */ 66 | public function getPattern() 67 | { 68 | return $this->pattern; 69 | } 70 | 71 | /** 72 | * Set container for use with resolveCallable 73 | * 74 | * @param ContainerInterface $container 75 | * 76 | * @return self 77 | */ 78 | public function setContainer(ContainerInterface $container) 79 | { 80 | $this->container = $container; 81 | return $this; 82 | } 83 | 84 | /** 85 | * Prepend middleware to the middleware collection 86 | * 87 | * @param callable|string $callable The callback routine 88 | * 89 | * @return static 90 | */ 91 | public function add($callable) 92 | { 93 | $this->middleware[] = new DeferredCallable($callable, $this->container); 94 | return $this; 95 | } 96 | 97 | /** 98 | * Set the route pattern 99 | * 100 | * @param string $newPattern 101 | */ 102 | public function setPattern($newPattern) 103 | { 104 | $this->pattern = $newPattern; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Slim/Handlers/AbstractError.php: -------------------------------------------------------------------------------- 1 | displayErrorDetails = (bool) $displayErrorDetails; 29 | } 30 | 31 | /** 32 | * Write to the error log if displayErrorDetails is false 33 | * 34 | * @param \Exception|\Throwable $throwable 35 | * 36 | * @return void 37 | */ 38 | protected function writeToErrorLog($throwable) 39 | { 40 | if ($this->displayErrorDetails) { 41 | return; 42 | } 43 | 44 | $message = 'Slim Application Error:' . PHP_EOL; 45 | $message .= $this->renderThrowableAsText($throwable); 46 | while ($throwable = $throwable->getPrevious()) { 47 | $message .= PHP_EOL . 'Previous error:' . PHP_EOL; 48 | $message .= $this->renderThrowableAsText($throwable); 49 | } 50 | 51 | $message .= PHP_EOL . 'View in rendered output by enabling the "displayErrorDetails" setting.' . PHP_EOL; 52 | 53 | $this->logError($message); 54 | } 55 | 56 | /** 57 | * Render error as Text. 58 | * 59 | * @param \Exception|\Throwable $throwable 60 | * 61 | * @return string 62 | */ 63 | protected function renderThrowableAsText($throwable) 64 | { 65 | $text = sprintf('Type: %s' . PHP_EOL, get_class($throwable)); 66 | 67 | if ($code = $throwable->getCode()) { 68 | $text .= sprintf('Code: %s' . PHP_EOL, $code); 69 | } 70 | 71 | if ($message = $throwable->getMessage()) { 72 | $text .= sprintf('Message: %s' . PHP_EOL, htmlentities($message)); 73 | } 74 | 75 | if ($file = $throwable->getFile()) { 76 | $text .= sprintf('File: %s' . PHP_EOL, $file); 77 | } 78 | 79 | if ($line = $throwable->getLine()) { 80 | $text .= sprintf('Line: %s' . PHP_EOL, $line); 81 | } 82 | 83 | if ($trace = $throwable->getTraceAsString()) { 84 | $text .= sprintf('Trace: %s', $trace); 85 | } 86 | 87 | return $text; 88 | } 89 | 90 | /** 91 | * Wraps the error_log function so that this can be easily tested 92 | * 93 | * @param $message 94 | */ 95 | protected function logError($message) 96 | { 97 | error_log($message); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Slim/Interfaces/RouterInterface.php: -------------------------------------------------------------------------------- 1 | container = $container; 34 | } 35 | 36 | /** 37 | * Resolve toResolve into a closure that that the router can dispatch. 38 | * 39 | * If toResolve is of the format 'class:method', then try to extract 'class' 40 | * from the container otherwise instantiate it and then dispatch 'method'. 41 | * 42 | * @param mixed $toResolve 43 | * 44 | * @return callable 45 | * 46 | * @throws RuntimeException if the callable does not exist 47 | * @throws RuntimeException if the callable is not resolvable 48 | */ 49 | public function resolve($toResolve) 50 | { 51 | if (is_callable($toResolve)) { 52 | return $toResolve; 53 | } 54 | 55 | if (!is_string($toResolve)) { 56 | $this->assertCallable($toResolve); 57 | } 58 | 59 | // check for slim callable as "class:method" 60 | if (preg_match(self::CALLABLE_PATTERN, $toResolve, $matches)) { 61 | $resolved = $this->resolveCallable($matches[1], $matches[2]); 62 | $this->assertCallable($resolved); 63 | 64 | return $resolved; 65 | } 66 | 67 | $resolved = $this->resolveCallable($toResolve); 68 | $this->assertCallable($resolved); 69 | 70 | return $resolved; 71 | } 72 | 73 | /** 74 | * Check if string is something in the DIC 75 | * that's callable or is a class name which has an __invoke() method. 76 | * 77 | * @param string $class 78 | * @param string $method 79 | * @return callable 80 | * 81 | * @throws \RuntimeException if the callable does not exist 82 | */ 83 | protected function resolveCallable($class, $method = '__invoke') 84 | { 85 | if ($this->container->has($class)) { 86 | return [$this->container->get($class), $method]; 87 | } 88 | 89 | if (!class_exists($class)) { 90 | throw new RuntimeException(sprintf('Callable %s does not exist', $class)); 91 | } 92 | 93 | return [new $class($this->container), $method]; 94 | } 95 | 96 | /** 97 | * @param Callable $callable 98 | * 99 | * @throws \RuntimeException if the callable is not resolvable 100 | */ 101 | protected function assertCallable($callable) 102 | { 103 | if (!is_callable($callable)) { 104 | throw new RuntimeException(sprintf( 105 | '%s is not resolvable', 106 | is_array($callable) || is_object($callable) ? json_encode($callable) : $callable 107 | )); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Slim/Interfaces/RouteInterface.php: -------------------------------------------------------------------------------- 1 | determineContentType($request); 36 | switch ($contentType) { 37 | case 'application/json': 38 | $output = $this->renderJsonNotFoundOutput(); 39 | break; 40 | 41 | case 'text/xml': 42 | case 'application/xml': 43 | $output = $this->renderXmlNotFoundOutput(); 44 | break; 45 | 46 | case 'text/html': 47 | $output = $this->renderHtmlNotFoundOutput($request); 48 | break; 49 | 50 | default: 51 | throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); 52 | } 53 | 54 | $body = new Body(fopen('php://temp', 'r+')); 55 | $body->write($output); 56 | 57 | return $response->withStatus(404) 58 | ->withHeader('Content-Type', $contentType) 59 | ->withBody($body); 60 | } 61 | 62 | /** 63 | * Return a response for application/json content not found 64 | * 65 | * @return ResponseInterface 66 | */ 67 | protected function renderJsonNotFoundOutput() 68 | { 69 | return '{"message":"Not found"}'; 70 | } 71 | 72 | /** 73 | * Return a response for xml content not found 74 | * 75 | * @return ResponseInterface 76 | */ 77 | protected function renderXmlNotFoundOutput() 78 | { 79 | return 'Not found'; 80 | } 81 | 82 | /** 83 | * Return a response for text/html content not found 84 | * 85 | * @param ServerRequestInterface $request The most recent Request object 86 | * 87 | * @return ResponseInterface 88 | */ 89 | protected function renderHtmlNotFoundOutput(ServerRequestInterface $request) 90 | { 91 | $homeUrl = (string)($request->getUri()->withPath('')->withQuery('')->withFragment('')); 92 | return << 94 | 95 | Page Not Found 96 | 113 | 114 | 115 | Page Not Found 116 | 117 | The page you are looking for could not be found. Check the address bar 118 | to ensure your URL is spelled correctly. If all else fails, you can 119 | visit our home page at the link below. 120 | 121 | Visit the Home Page 122 | 123 |
117 | The page you are looking for could not be found. Check the address bar 118 | to ensure your URL is spelled correctly. If all else fails, you can 119 | visit our home page at the link below. 120 |