├── Slim ├── Exception │ ├── NotFoundException.php │ ├── ContainerException.php │ ├── ContainerValueNotFoundException.php │ ├── InvalidMethodException.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 │ ├── StatusCode.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 ├── CODE_OF_CONDUCT.md ├── LICENSE.md └── composer.json /Slim/Exception/NotFoundException.php: -------------------------------------------------------------------------------- 1 | request = $request; 20 | parent::__construct(sprintf('Unsupported HTTP method "%s" provided', $method)); 21 | } 22 | 23 | public function getRequest() 24 | { 25 | return $this->request; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Slim/Interfaces/CollectionInterface.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 instance to bind/pass to the group callable 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($app); 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 | "autoload-dev": { 51 | "files": [ 52 | "tests/Assets/HeaderFunctions.php" 53 | ] 54 | }, 55 | "scripts": { 56 | "test": [ 57 | "phpunit", 58 | "phpcs" 59 | ] 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /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/Http/Environment.php: -------------------------------------------------------------------------------- 1 | 'HTTP/1.1', 44 | 'REQUEST_METHOD' => 'GET', 45 | 'REQUEST_SCHEME' => $defscheme, 46 | 'SCRIPT_NAME' => '', 47 | 'REQUEST_URI' => '', 48 | 'QUERY_STRING' => '', 49 | 'SERVER_NAME' => 'localhost', 50 | 'SERVER_PORT' => $defport, 51 | 'HTTP_HOST' => 'localhost', 52 | 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 53 | 'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', 54 | 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 55 | 'HTTP_USER_AGENT' => 'Slim Framework', 56 | 'REMOTE_ADDR' => '127.0.0.1', 57 | 'REQUEST_TIME' => time(), 58 | 'REQUEST_TIME_FLOAT' => microtime(true), 59 | ], $userData); 60 | 61 | return new static($data); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /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/Http/StatusCode.php: -------------------------------------------------------------------------------- 1 | container = $container; 34 | } 35 | 36 | /** 37 | * Resolve toResolve into a closure so 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 | middlewareLock) { 56 | throw new RuntimeException('Middleware can’t be added once the stack is dequeuing'); 57 | } 58 | 59 | if (is_null($this->tip)) { 60 | $this->seedMiddlewareStack(); 61 | } 62 | $next = $this->tip; 63 | $this->tip = function ( 64 | ServerRequestInterface $request, 65 | ResponseInterface $response 66 | ) use ( 67 | $callable, 68 | $next 69 | ) { 70 | $result = call_user_func($callable, $request, $response, $next); 71 | if ($result instanceof ResponseInterface === false) { 72 | throw new UnexpectedValueException( 73 | 'Middleware must return instance of \Psr\Http\Message\ResponseInterface' 74 | ); 75 | } 76 | 77 | return $result; 78 | }; 79 | 80 | return $this; 81 | } 82 | 83 | /** 84 | * Seed middleware stack with first callable 85 | * 86 | * @param callable $kernel The last item to run as middleware 87 | * 88 | * @throws RuntimeException if the stack is seeded more than once 89 | */ 90 | protected function seedMiddlewareStack(callable $kernel = null) 91 | { 92 | if (!is_null($this->tip)) { 93 | throw new RuntimeException('MiddlewareStack can only be seeded once.'); 94 | } 95 | if ($kernel === null) { 96 | $kernel = $this; 97 | } 98 | $this->tip = $kernel; 99 | } 100 | 101 | /** 102 | * Call middleware stack 103 | * 104 | * @param ServerRequestInterface $request A request object 105 | * @param ResponseInterface $response A response object 106 | * 107 | * @return ResponseInterface 108 | */ 109 | public function callMiddlewareStack(ServerRequestInterface $request, ResponseInterface $response) 110 | { 111 | if (is_null($this->tip)) { 112 | $this->seedMiddlewareStack(); 113 | } 114 | /** @var callable $start */ 115 | $start = $this->tip; 116 | $this->middlewareLock = true; 117 | $response = $start($request, $response); 118 | $this->middlewareLock = false; 119 | return $response; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Slim/Handlers/NotFound.php: -------------------------------------------------------------------------------- 1 | getMethod() === 'OPTIONS') { 36 | $contentType = 'text/plain'; 37 | $output = $this->renderPlainNotFoundOutput(); 38 | } else { 39 | $contentType = $this->determineContentType($request); 40 | switch ($contentType) { 41 | case 'application/json': 42 | $output = $this->renderJsonNotFoundOutput(); 43 | break; 44 | 45 | case 'text/xml': 46 | case 'application/xml': 47 | $output = $this->renderXmlNotFoundOutput(); 48 | break; 49 | 50 | case 'text/html': 51 | $output = $this->renderHtmlNotFoundOutput($request); 52 | break; 53 | 54 | default: 55 | throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); 56 | } 57 | } 58 | 59 | $body = new Body(fopen('php://temp', 'r+')); 60 | $body->write($output); 61 | 62 | return $response->withStatus(404) 63 | ->withHeader('Content-Type', $contentType) 64 | ->withBody($body); 65 | } 66 | 67 | /** 68 | * Render plain not found message 69 | * 70 | * @return ResponseInterface 71 | */ 72 | protected function renderPlainNotFoundOutput() 73 | { 74 | return 'Not found'; 75 | } 76 | 77 | /** 78 | * Return a response for application/json content not found 79 | * 80 | * @return ResponseInterface 81 | */ 82 | protected function renderJsonNotFoundOutput() 83 | { 84 | return '{"message":"Not found"}'; 85 | } 86 | 87 | /** 88 | * Return a response for xml content not found 89 | * 90 | * @return ResponseInterface 91 | */ 92 | protected function renderXmlNotFoundOutput() 93 | { 94 | return 'Not found'; 95 | } 96 | 97 | /** 98 | * Return a response for text/html content not found 99 | * 100 | * @param ServerRequestInterface $request The most recent Request object 101 | * 102 | * @return ResponseInterface 103 | */ 104 | protected function renderHtmlNotFoundOutput(ServerRequestInterface $request) 105 | { 106 | $homeUrl = (string)($request->getUri()->withPath('')->withQuery('')->withFragment('')); 107 | return << 109 | 110 | Page Not Found 111 | 128 | 129 | 130 | Page Not Found 131 | 132 | The page you are looking for could not be found. Check the address bar 133 | to ensure your URL is spelled correctly. If all else fails, you can 134 | visit our home page at the link below. 135 | 136 | Visit the Home Page 137 | 138 |
132 | The page you are looking for could not be found. Check the address bar 133 | to ensure your URL is spelled correctly. If all else fails, you can 134 | visit our home page at the link below. 135 |