87 changed files with 10207 additions and 5294 deletions
+5
View File
@@ -0,0 +1,5 @@
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ serviceapp.php [QSA,L]
</ifModule>
+33
View File
@@ -0,0 +1,33 @@
<?php
class CheckFromMW
{
/**
* Example middleware invokable class
*
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke($request, $response, $next)
{
$currentRefererRequest = $request->getHost();
$currentRefererRequest = substr($currentRefererRequest, 7); //Senza http://
$indexDoublePoint = strpos($currentRefererRequest, ':');
$indexFirstSlash = strpos($currentRefererRequest, '/');
$currentRefererRequest = substr($currentRefererRequest, 0, $indexDoublePoint > 0 && $indexDoublePoint < $indexFirstSlash ? $indexDoublePoint : $indexFirstSlash );
if(!in_array($currentRefererRequest, $allowedHost))
{
return $response->withStatus(500)->write('Generic error occurred');
}
*/
$currentHostRequest = $app->request()->getHost();
if(!in_array($currentHostRequest, $allowedHost))
{
return $response->withStatus(403)->write('Request arrive from host not allowed');
}
return $next($request, $response);
}
}
+89
View File
@@ -0,0 +1,89 @@
<?php
class MysqlClass
{
// parametri per la connessione al database
/*private $nomehost = "mysql.hostinger.it";
private $nomeuser = "u766568765_lpm";
private $password = "8zX2gTIjfwXEdEgaSaWe";
private $mydb = "u766568765_lpm";
*/
private $nomehost = "sql.gruppolapastamadre.it";
private $nomeuser = "w18092_ricuser";
private $password = "RTvg0o6IESoqQyx8CCJn";
private $mydb = "w18092_ricettario";
// controllo sulle connessioni attive
private $attiva = false;
private $connessione = null;
// funzione per la connessione a MySQL
public function connetti()
{
if(!$this->attiva)
{
$this->connessione = mysql_connect($this->nomehost,$this->nomeuser,$this->password);
if ($this->connessione == FALSE)
die(mysql_error());
mysql_select_db($this->mydb, $this->connessione) or die ("Errore nella selezione del database. Verificare i parametri nel file config.inc.php");
$this->attiva = true;
}
else{
return true;
}
}
public function executeQuery($queryStr)
{
$this->connetti();
if (!$res = mysql_query($queryStr, $this->connessione)) die(mysql_error());
return true;
return false;
}
public function insertRecord($queryStr)
{
$this->connetti();
if (!$res = mysql_query($queryStr, $this->connessione)) die(mysql_error());
return mysql_insert_id();
}
public function queryToObject($queryStr)
{
$this->connetti();
$sth = mysql_query($queryStr, $this->connessione) or die(mysql_error());
$rows = array();
while($r = mysql_fetch_assoc($sth)) {
array_push($rows,array_map('utf8_encode', $r));
}
mysql_free_result($sth);
return $rows;
}
// funzione per la chiusura della connessione
public function disconnetti()
{
if($this->attiva)
{
if(mysql_close($this->connessione))
{
$this->attiva = false;
return true;
}
else
{
return false;
}
}
}
public function __destruct()
{
$this->disconnetti();
}
}
?>
+5 -4
View File
@@ -1,8 +1,9 @@
<?php <?php
class MysqlClass
{ class MysqlClass {
// parametri per la connessione al database
private $nomehost = "localhost"; // parametri per la connessione al database
private $nomehost = "localhost";
private $nomeuser = "root"; private $nomeuser = "root";
private $password = "root"; private $password = "root";
private $mydb = "w18092_ricettario"; private $mydb = "w18092_ricettario";
@@ -5,7 +5,7 @@ namespace PHPImageWorkshop\Core\Exception;
use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException; use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException;
// If no autoloader, uncomment these lines: // If no autoloader, uncomment these lines:
//require_once(__DIR__.'/../../Exception/ImageWorkshopBaseException.php'); require_once(__DIR__.'/../../Exception/ImageWorkshopBaseException.php');
/** /**
* ImageWorkshopLayerException * ImageWorkshopLayerException
@@ -5,7 +5,7 @@ namespace PHPImageWorkshop\Core\Exception;
use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException; use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException;
// If no autoloader, uncomment these lines: // If no autoloader, uncomment these lines:
//require_once(__DIR__.'/../../Exception/ImageWorkshopBaseException.php'); require_once(__DIR__.'/../../Exception/ImageWorkshopBaseException.php');
/** /**
* ImageWorkshopLibException * ImageWorkshopLibException
+3 -3
View File
@@ -7,9 +7,9 @@ use PHPImageWorkshop\Core\ImageWorkshopLib as ImageWorkshopLib;
use PHPImageWorkshop\Core\Exception\ImageWorkshopLayerException as ImageWorkshopLayerException; use PHPImageWorkshop\Core\Exception\ImageWorkshopLayerException as ImageWorkshopLayerException;
// If no autoloader, uncomment these lines: // If no autoloader, uncomment these lines:
//require_once(__DIR__.'/../ImageWorkshop.php'); require_once(__DIR__.'/../ImageWorkshop.php');
//require_once(__DIR__.'/ImageWorkshopLib.php'); require_once(__DIR__.'/ImageWorkshopLib.php');
//require_once(__DIR__.'/Exception/ImageWorkshopLayerException.php'); require_once(__DIR__.'/Exception/ImageWorkshopLayerException.php');
/** /**
* ImageWorkshopLayer class * ImageWorkshopLayer class
+1 -1
View File
@@ -5,7 +5,7 @@ namespace PHPImageWorkshop\Core;
use PHPImageWorkshop\Core\Exception\ImageWorkshopLibException as ImageWorkshopLibException; use PHPImageWorkshop\Core\Exception\ImageWorkshopLibException as ImageWorkshopLibException;
// If no autoloader, uncomment these lines: // If no autoloader, uncomment these lines:
//require_once(__DIR__.'/Exception/ImageWorkshopLibException.php'); require_once(__DIR__.'/Exception/ImageWorkshopLibException.php');
/** /**
* ImageWorkshopLib class * ImageWorkshopLib class
@@ -5,7 +5,7 @@ namespace PHPImageWorkshop\Exception;
use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException; use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException;
// If no autoloader, uncomment these lines: // If no autoloader, uncomment these lines:
//require_once(__DIR__.'/ImageWorkshopBaseException.php'); require_once(__DIR__.'/ImageWorkshopBaseException.php');
/** /**
* ImageWorkshopException * ImageWorkshopException
+2 -2
View File
@@ -7,8 +7,8 @@ use PHPImageWorkshop\Core\ImageWorkshopLib as ImageWorkshopLib;
use PHPImageWorkshop\Exception\ImageWorkshopException as ImageWorkshopException; use PHPImageWorkshop\Exception\ImageWorkshopException as ImageWorkshopException;
// If no autoloader, uncomment these lines: // If no autoloader, uncomment these lines:
//require_once(__DIR__.'/Core/ImageWorkshopLayer.php'); require_once(__DIR__.'/Core/ImageWorkshopLayer.php');
//require_once(__DIR__.'/Exception/ImageWorkshopException.php'); require_once(__DIR__.'/Exception/ImageWorkshopException.php');
/** /**
* ImageWorkshop class * ImageWorkshop class
BIN
View File
Binary file not shown.
+104
View File
@@ -0,0 +1,104 @@
<?php
class SimpleImage {
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if ($this->image_type == IMAGETYPE_JPEG) {
$this->image = imagecreatefromjpeg($filename);
} elseif ($this->image_type == IMAGETYPE_GIF) {
$this->image = imagecreatefromgif($filename);
} elseif ($this->image_type == IMAGETYPE_PNG) {
$this->image = imagecreatefrompng($filename);
}
}
function saveas($filename, $image_type = IMAGETYPE_JPEG, $compression = 75, $permissions = null) {
if ($image_type == IMAGETYPE_JPEG) {
imagejpeg($this->image, $filename, $compression);
} elseif ($image_type == IMAGETYPE_GIF) {
imagegif($this->image, $filename);
} elseif ($image_type == IMAGETYPE_PNG) {
imagepng($this->image, $filename);
} if ($permissions != null) {
chmod($filename, $permissions);
}
}
function save($filename) {
if ($this->image_type == IMAGETYPE_JPEG) {
imagejpeg($this->image, $filename);
} elseif ($this->image_type == IMAGETYPE_GIF) {
imagegif($this->image, $filename);
} elseif ($this->image_type == IMAGETYPE_PNG) {
imagepng($this->image, $filename);
}
}
function output($image_type = IMAGETYPE_JPEG) {
if ($image_type == IMAGETYPE_JPEG) {
imagejpeg($this->image);
} elseif ($image_type == IMAGETYPE_GIF) {
imagegif($this->image);
} elseif ($image_type == IMAGETYPE_PNG) {
imagepng($this->image);
}
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width, $height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width, $height);
}
function scale($scale) {
$width = $this->getWidth() * $scale / 100;
$height = $this->getheight() * $scale / 100;
$this->resize($width, $height);
}
function resize($width, $height) {
$new_image = imagecreatetruecolor($width, $height);
if ($this->image_type == IMAGETYPE_GIF || $this->image_type == IMAGETYPE_PNG) {
$current_transparent = imagecolortransparent($this->image);
if ($current_transparent != -1) {
$transparent_color = imagecolorsforindex($this->image, $current_transparent);
$current_transparent = imagecolorallocate($new_image, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
imagefill($new_image, 0, 0, $current_transparent);
imagecolortransparent($new_image, $current_transparent);
} elseif ($this->image_type == IMAGETYPE_PNG) {
imagealphablending($new_image, false);
$color = imagecolorallocatealpha($new_image, 0, 0, 0, 127);
imagefill($new_image, 0, 0, $color);
imagesavealpha($new_image, true);
}
}
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
function close()
{
imagedestroy($this->image);
}
}
?>
+555
View File
@@ -0,0 +1,555 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use Exception;
use Closure;
use InvalidArgumentException;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Interop\Container\ContainerInterface;
use FastRoute\Dispatcher;
use Slim\Exception\SlimException;
use Slim\Exception\MethodNotAllowedException;
use Slim\Exception\NotFoundException;
use Slim\Http\Uri;
use Slim\Http\Headers;
use Slim\Http\Body;
use Slim\Http\Request;
use Slim\Interfaces\Http\EnvironmentInterface;
use Slim\Interfaces\RouteGroupInterface;
use Slim\Interfaces\RouteInterface;
use Slim\Interfaces\RouterInterface;
/**
* App
*
* This is the primary class with which you instantiate,
* configure, and run a Slim Framework application.
* The \Slim\App class also accepts Slim Framework middleware.
*
* @property-read array $settings App settings
* @property-read EnvironmentInterface $environment
* @property-read RequestInterface $request
* @property-read ResponseInterface $response
* @property-read RouterInterface $router
* @property-read callable $errorHandler
* @property-read callable $notFoundHandler function($request, $response)
* @property-read callable $notAllowedHandler function($request, $response, $allowedHttpMethods)
*/
class App
{
use CallableResolverAwareTrait;
use MiddlewareAwareTrait;
/**
* Current version
*
* @var string
*/
const VERSION = '3.0.0';
/**
* Container
*
* @var ContainerInterface
*/
private $container;
/********************************************************************************
* Constructor
*******************************************************************************/
/**
* Create new application
*
* @param ContainerInterface|array $container Either a ContainerInterface or an associative array of application settings
* @throws InvalidArgumentException when no container is provided that implements ContainerInterface
*/
public function __construct($container = [])
{
if (is_array($container)) {
$container = new Container($container);
}
if (!$container instanceof ContainerInterface) {
throw new InvalidArgumentException('Expected a ContainerInterface');
}
$this->container = $container;
}
/**
* Enable access to the DI container by consumers of $app
*
* @return ContainerInterface
*/
public function getContainer()
{
return $this->container;
}
/**
* Add middleware
*
* This method prepends new middleware to the app's middleware stack.
*
* @param mixed $callable The callback routine
*
* @return static
*/
public function add($callable)
{
$callable = $this->resolveCallable($callable);
if ($callable instanceof Closure) {
$callable = $callable->bindTo($this->container);
}
return $this->addMiddleware($callable);
}
/**
* Calling a non-existant method on App checks to see if there's an item
* in the container than is callable and if so, calls it.
*
* @param string $method
* @param array $args
* @return mixed
*/
public function __call($method, $args)
{
if ($this->container->has($method)) {
$obj = $this->container->get($method);
if (is_callable($obj)) {
return call_user_func_array($obj, $args);
}
}
}
/********************************************************************************
* Router proxy methods
*******************************************************************************/
/**
* Add GET route
*
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return \Slim\Interfaces\RouteInterface
*/
public function get($pattern, $callable)
{
return $this->map(['GET'], $pattern, $callable);
}
/**
* Add POST route
*
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return \Slim\Interfaces\RouteInterface
*/
public function post($pattern, $callable)
{
return $this->map(['POST'], $pattern, $callable);
}
/**
* Add PUT route
*
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return \Slim\Interfaces\RouteInterface
*/
public function put($pattern, $callable)
{
return $this->map(['PUT'], $pattern, $callable);
}
/**
* Add PATCH route
*
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return \Slim\Interfaces\RouteInterface
*/
public function patch($pattern, $callable)
{
return $this->map(['PATCH'], $pattern, $callable);
}
/**
* Add DELETE route
*
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return \Slim\Interfaces\RouteInterface
*/
public function delete($pattern, $callable)
{
return $this->map(['DELETE'], $pattern, $callable);
}
/**
* Add OPTIONS route
*
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return \Slim\Interfaces\RouteInterface
*/
public function options($pattern, $callable)
{
return $this->map(['OPTIONS'], $pattern, $callable);
}
/**
* Add route for any HTTP method
*
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return \Slim\Interfaces\RouteInterface
*/
public function any($pattern, $callable)
{
return $this->map(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], $pattern, $callable);
}
/**
* Add route with multiple methods
*
* @param string[] $methods Numeric array of HTTP method names
* @param string $pattern The route URI pattern
* @param mixed $callable The route callback routine
*
* @return RouteInterface
*/
public function map(array $methods, $pattern, $callable)
{
if ($callable instanceof Closure) {
$callable = $callable->bindTo($this->container);
}
$route = $this->container->get('router')->map($methods, $pattern, $callable);
if (is_callable([$route, 'setContainer'])) {
$route->setContainer($this->container);
}
if (is_callable([$route, 'setOutputBuffering'])) {
$route->setOutputBuffering($this->container->get('settings')['outputBuffering']);
}
return $route;
}
/**
* Route Groups
*
* This method accepts a route pattern and a callback. All route
* declarations in the callback will be prepended by the group(s)
* that it is in.
*
* @param string $pattern
* @param callable $callable
*
* @return RouteGroupInterface
*/
public function group($pattern, $callable)
{
/** @var RouteGroup $group */
$group = $this->container->get('router')->pushGroup($pattern, $callable);
$group->setContainer($this->container);
$group($this);
$this->container->get('router')->popGroup();
return $group;
}
/********************************************************************************
* Runner
*******************************************************************************/
/**
* Run application
*
* This method traverses the application middleware stack and then sends the
* resultant Response object to the HTTP client.
*
* @param bool|false $silent
* @return ResponseInterface
*
* @throws Exception
* @throws MethodNotAllowedException
* @throws NotFoundException
*/
public function run($silent = false)
{
$request = $this->container->get('request');
$response = $this->container->get('response');
// Ensure basePath is set
$router = $this->container->get('router');
if (is_callable([$request->getUri(), 'getBasePath']) && is_callable([$router, 'setBasePath'])) {
$router->setBasePath($request->getUri()->getBasePath());
}
// Dispatch the Router first if the setting for this is on
if ($this->container->get('settings')['determineRouteBeforeAppMiddleware'] === true) {
// Dispatch router (note: you won't be able to alter routes after this)
$request = $this->dispatchRouterAndPrepareRoute($request, $router);
}
// Traverse middleware stack
try {
$response = $this->callMiddlewareStack($request, $response);
} catch (MethodNotAllowedException $e) {
if (!$this->container->has('notAllowedHandler')) {
throw $e;
}
/** @var callable $notAllowedHandler */
$notAllowedHandler = $this->container->get('notAllowedHandler');
$response = $notAllowedHandler($e->getRequest(), $e->getResponse(), $e->getAllowedMethods());
} catch (NotFoundException $e) {
if (!$this->container->has('notFoundHandler')) {
throw $e;
}
/** @var callable $notFoundHandler */
$notFoundHandler = $this->container->get('notFoundHandler');
$response = $notFoundHandler($e->getRequest(), $e->getResponse());
} catch (SlimException $e) {
$response = $e->getResponse();
} catch (Exception $e) {
if (!$this->container->has('errorHandler')) {
throw $e;
}
/** @var callable $errorHandler */
$errorHandler = $this->container->get('errorHandler');
$response = $errorHandler($request, $response, $e);
}
$response = $this->finalize($response);
if (!$silent) {
$this->respond($response);
}
return $response;
}
/**
* Send the response the client
*
* @param ResponseInterface $response
*/
public function respond(ResponseInterface $response)
{
// Send response
if (!headers_sent()) {
// Status
header(sprintf(
'HTTP/%s %s %s',
$response->getProtocolVersion(),
$response->getStatusCode(),
$response->getReasonPhrase()
));
// Headers
foreach ($response->getHeaders() as $name => $values) {
foreach ($values as $value) {
header(sprintf('%s: %s', $name, $value), false);
}
}
}
// Body
if (!$this->isEmptyResponse($response)) {
$body = $response->getBody();
if ($body->isSeekable()) {
$body->rewind();
}
$settings = $this->container->get('settings');
$chunkSize = $settings['responseChunkSize'];
$contentLength = $response->getHeaderLine('Content-Length');
if (!$contentLength) {
$contentLength = $body->getSize();
}
$totalChunks = ceil($contentLength / $chunkSize);
$lastChunkSize = $contentLength % $chunkSize;
$currentChunk = 0;
while (!$body->eof() && $currentChunk < $totalChunks) {
if (++$currentChunk == $totalChunks && $lastChunkSize > 0) {
$chunkSize = $lastChunkSize;
}
echo $body->read($chunkSize);
if (connection_status() != CONNECTION_NORMAL) {
break;
}
}
}
}
/**
* Invoke application
*
* This method implements the middleware interface. It receives
* Request and Response objects, and it returns a Response object
* after compiling the routes registered in the Router and dispatching
* the Request object to the appropriate Route callback routine.
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
* @throws MethodNotAllowedException
* @throws NotFoundException
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
{
// Get the route info
$routeInfo = $request->getAttribute('routeInfo');
/** @var \Slim\Interfaces\RouterInterface $router */
$router = $this->container->get('router');
// If router hasn't been dispatched or the URI changed then dispatch
if (null === $routeInfo || ($routeInfo['request'] !== [$request->getMethod(), (string) $request->getUri()])) {
$request = $this->dispatchRouterAndPrepareRoute($request, $router);
$routeInfo = $request->getAttribute('routeInfo');
}
if ($routeInfo[0] === Dispatcher::FOUND) {
$route = $router->lookupRoute($routeInfo[1]);
return $route->run($request, $response);
} elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) {
if (!$this->container->has('notAllowedHandler')) {
throw new MethodNotAllowedException($request, $response, $routeInfo[1]);
}
/** @var callable $notAllowedHandler */
$notAllowedHandler = $this->container->get('notAllowedHandler');
return $notAllowedHandler($request, $response, $routeInfo[1]);
}
if (!$this->container->has('notFoundHandler')) {
throw new NotFoundException($request, $response);
}
/** @var callable $notFoundHandler */
$notFoundHandler = $this->container->get('notFoundHandler');
return $notFoundHandler($request, $response);
}
/**
* Perform a sub-request from within an application route
*
* This method allows you to prepare and initiate a sub-request, run within
* the context of the current request. This WILL NOT issue a remote HTTP
* request. Instead, it will route the provided URL, method, headers,
* cookies, body, and server variables against the set of registered
* application routes. The result response object is returned.
*
* @param string $method The request method (e.g., GET, POST, PUT, etc.)
* @param string $path The request URI path
* @param string $query The request URI query string
* @param array $headers The request headers (key-value array)
* @param array $cookies The request cookies (key-value array)
* @param string $bodyContent The request body
* @param ResponseInterface $response The response object (optional)
* @return ResponseInterface
*/
public function subRequest($method, $path, $query = '', array $headers = [], array $cookies = [], $bodyContent = '', ResponseInterface $response = null)
{
$env = $this->container->get('environment');
$uri = Uri::createFromEnvironment($env)->withPath($path)->withQuery($query);
$headers = new Headers($headers);
$serverParams = $env->all();
$body = new Body(fopen('php://temp', 'r+'));
$body->write($bodyContent);
$body->rewind();
$request = new Request($method, $uri, $headers, $cookies, $serverParams, $body);
if (!$response) {
$response = $this->container->get('response');
}
return $this($request, $response);
}
/**
* Dispatch the router to find the route. Prepare the route for use.
*
* @param ServerRequestInterface $request
* @param RouterInterface $router
* @return ServerRequestInterface
*/
protected function dispatchRouterAndPrepareRoute(ServerRequestInterface $request, RouterInterface $router)
{
$routeInfo = $router->dispatch($request);
if ($routeInfo[0] === Dispatcher::FOUND) {
$routeArguments = [];
foreach ($routeInfo[2] as $k => $v) {
$routeArguments[$k] = urldecode($v);
}
$route = $router->lookupRoute($routeInfo[1]);
$route->prepare($request, $routeArguments);
// add route to the request's attributes in case a middleware or handler needs access to the route
$request = $request->withAttribute('route', $route);
}
$routeInfo['request'] = [$request->getMethod(), (string) $request->getUri()];
return $request->withAttribute('routeInfo', $routeInfo);
}
/**
* Finalize response
*
* @param ResponseInterface $response
* @return ResponseInterface
*/
protected function finalize(ResponseInterface $response)
{
// stop PHP sending a Content-Type automatically
ini_set('default_mimetype', '');
if ($this->isEmptyResponse($response)) {
return $response->withoutHeader('Content-Type')->withoutHeader('Content-Length');
}
$size = $response->getBody()->getSize();
if ($size !== null && !$response->hasHeader('Content-Length')) {
$response = $response->withHeader('Content-Length', (string) $size);
}
return $response;
}
/**
* Helper method, which returns true if the provided response must not output a body and false
* if the response could have a body.
*
* @see https://tools.ietf.org/html/rfc7231
*
* @param ResponseInterface $response
* @return bool
*/
protected function isEmptyResponse(ResponseInterface $response)
{
if (method_exists($response, 'isEmpty')) {
return $response->isEmpty();
}
return in_array($response->getStatusCode(), [204, 205, 304]);
}
}
+87
View File
@@ -0,0 +1,87 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use RuntimeException;
use Interop\Container\ContainerInterface;
use Slim\Interfaces\CallableResolverInterface;
/**
* This class resolves a string of the format 'class:method' into a closure
* that can be dispatched.
*/
final class CallableResolver implements CallableResolverInterface
{
/**
* @var ContainerInterface
*/
private $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* Resolve toResolve into a closure that that the router can dispatch.
*
* If toResolve is of the format 'class:method', then try to extract 'class'
* from the container otherwise instantiate it and then dispatch 'method'.
*
* @param mixed $toResolve
*
* @return callable
*
* @throws RuntimeException if the callable does not exist
* @throws RuntimeException if the callable is not resolvable
*/
public function resolve($toResolve)
{
$resolved = $toResolve;
if (!is_callable($toResolve) && is_string($toResolve)) {
// check for slim callable as "class:method"
$callablePattern = '!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!';
if (preg_match($callablePattern, $toResolve, $matches)) {
$class = $matches[1];
$method = $matches[2];
if ($this->container->has($class)) {
$resolved = [$this->container->get($class), $method];
} else {
if (!class_exists($class)) {
throw new RuntimeException(sprintf('Callable %s does not exist', $class));
}
$resolved = [new $class($this->container), $method];
}
} else {
// check if string is something in the DIC that's callable or is a class name which
// has an __invoke() method
$class = $toResolve;
if ($this->container->has($class)) {
$resolved = $this->container->get($class);
} else {
if (!class_exists($class)) {
throw new RuntimeException(sprintf('Callable %s does not exist', $class));
}
$resolved = new $class($this->container);
}
}
}
if (!is_callable($resolved)) {
throw new RuntimeException(sprintf('%s is not resolvable', $toResolve));
}
return $resolved;
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use RuntimeException;
use Interop\Container\ContainerInterface;
use Slim\Interfaces\CallableResolverInterface;
/**
* ResolveCallable
*
* This is an internal class that enables resolution of 'class:method' strings
* into a closure. This class is an implementation detail and is used only inside
* of the Slim application.
*
* @property ContainerInterface $container
*/
trait CallableResolverAwareTrait
{
/**
* Resolve a string of the format 'class:method' into a closure that the
* router can dispatch.
*
* @param mixed $callable
*
* @return \Closure
*
* @throws RuntimeException If the string cannot be resolved as a callable
*/
protected function resolveCallable($callable)
{
if (!$this->container instanceof ContainerInterface) {
return $callable;
}
/** @var CallableResolverInterface $resolver */
$resolver = $this->container->get('callableResolver');
return $resolver->resolve($callable);
}
}
+204
View File
@@ -0,0 +1,204 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use ArrayIterator;
use Slim\Interfaces\CollectionInterface;
/**
* Collection
*
* This class provides a common interface used by many other
* classes in a Slim application that manage "collections"
* of data that must be inspected and/or manipulated
*/
class Collection implements CollectionInterface
{
/**
* The source data
*
* @var array
*/
protected $data = [];
/**
* Create new collection
*
* @param array $items Pre-populate collection with this key-value array
*/
public function __construct(array $items = [])
{
foreach ($items as $key => $value) {
$this->set($key, $value);
}
}
/********************************************************************************
* Collection interface
*******************************************************************************/
/**
* Set collection item
*
* @param string $key The data key
* @param mixed $value The data value
*/
public function set($key, $value)
{
$this->data[$key] = $value;
}
/**
* Get collection item for key
*
* @param string $key The data key
* @param mixed $default The default value to return if data key does not exist
*
* @return mixed The key's value, or the default value
*/
public function get($key, $default = null)
{
return $this->has($key) ? $this->data[$key] : $default;
}
/**
* Add item to collection
*
* @param array $items Key-value array of data to append to this collection
*/
public function replace(array $items)
{
foreach ($items as $key => $value) {
$this->set($key, $value);
}
}
/**
* Get all items in collection
*
* @return array The collection's source data
*/
public function all()
{
return $this->data;
}
/**
* Get collection keys
*
* @return array The collection's source data keys
*/
public function keys()
{
return array_keys($this->data);
}
/**
* Does this collection have a given key?
*
* @param string $key The data key
*
* @return bool
*/
public function has($key)
{
return array_key_exists($key, $this->data);
}
/**
* Remove item from collection
*
* @param string $key The data key
*/
public function remove($key)
{
unset($this->data[$key]);
}
/**
* Remove all items from collection
*/
public function clear()
{
$this->data = [];
}
/********************************************************************************
* ArrayAccess interface
*******************************************************************************/
/**
* Does this collection have a given key?
*
* @param string $key The data key
*
* @return bool
*/
public function offsetExists($key)
{
return $this->has($key);
}
/**
* Get collection item for key
*
* @param string $key The data key
*
* @return mixed The key's value, or the default value
*/
public function offsetGet($key)
{
return $this->get($key);
}
/**
* Set collection item
*
* @param string $key The data key
* @param mixed $value The data value
*/
public function offsetSet($key, $value)
{
$this->set($key, $value);
}
/**
* Remove item from collection
*
* @param string $key The data key
*/
public function offsetUnset($key)
{
$this->remove($key);
}
/**
* Get number of items in collection
*
* @return int
*/
public function count()
{
return count($this->data);
}
/********************************************************************************
* IteratorAggregate interface
*******************************************************************************/
/**
* Get collection iterator
*
* @return \ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->data);
}
}
+296
View File
@@ -0,0 +1,296 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException;
use Pimple\Container as PimpleContainer;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\ContainerValueNotFoundException;
use Slim\Handlers\Error;
use Slim\Handlers\NotFound;
use Slim\Handlers\NotAllowed;
use Slim\Handlers\Strategies\RequestResponse;
use Slim\Http\Environment;
use Slim\Http\Headers;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Interfaces\CallableResolverInterface;
use Slim\Interfaces\Http\EnvironmentInterface;
use Slim\Interfaces\InvocationStrategyInterface;
use Slim\Interfaces\RouterInterface;
/**
* Slim's default DI container is Pimple.
*
* Slim\App expects a container that implements Interop\Container\ContainerInterface
* with these service keys configured and ready for use:
*
* - settings: an array or instance of \ArrayAccess
* - environment: an instance of \Slim\Interfaces\Http\EnvironmentInterface
* - request: an instance of \Psr\Http\Message\ServerRequestInterface
* - response: an instance of \Psr\Http\Message\ResponseInterface
* - router: an instance of \Slim\Interfaces\RouterInterface
* - foundHandler: an instance of \Slim\Interfaces\InvocationStrategyInterface
* - errorHandler: a callable with the signature: function($request, $response, $exception)
* - notFoundHandler: a callable with the signature: function($request, $response)
* - notAllowedHandler: a callable with the signature: function($request, $response, $allowedHttpMethods)
* - callableResolver: an instance of callableResolver
*
* @property-read array settings
* @property-read \Slim\Interfaces\Http\EnvironmentInterface environment
* @property-read \Psr\Http\Message\ServerRequestInterface request
* @property-read \Psr\Http\Message\ResponseInterface response
* @property-read \Slim\Interfaces\RouterInterface router
* @property-read \Slim\Interfaces\InvocationStrategyInterface foundHandler
* @property-read callable errorHandler
* @property-read callable notFoundHandler
* @property-read callable notAllowedHandler
* @property-read \Slim\Interfaces\CallableResolverInterface callableResolver
*/
final class Container extends PimpleContainer implements ContainerInterface
{
/**
* Default settings
*
* @var array
*/
private $defaultSettings = [
'httpVersion' => '1.1',
'responseChunkSize' => 4096,
'outputBuffering' => 'append',
'determineRouteBeforeAppMiddleware' => false,
'displayErrorDetails' => false,
];
/**
* Create new container
*
* @param array $values The parameters or objects.
*/
public function __construct(array $values = [])
{
parent::__construct($values);
$userSettings = isset($values['settings']) ? $values['settings'] : [];
$this->registerDefaultServices($userSettings);
}
/**
* This function registers the default services that Slim needs to work.
*
* All services are shared - that is, they are registered such that the
* same instance is returned on subsequent calls.
*
* @param array $userSettings Associative array of application settings
*
* @return void
*/
private function registerDefaultServices($userSettings)
{
$defaultSettings = $this->defaultSettings;
/**
* This service MUST return an array or an
* instance of \ArrayAccess.
*
* @return array|\ArrayAccess
*/
$this['settings'] = function () use ($userSettings, $defaultSettings) {
return new Collection(array_merge($defaultSettings, $userSettings));
};
if (!isset($this['environment'])) {
/**
* This service MUST return a shared instance
* of \Slim\Interfaces\Http\EnvironmentInterface.
*
* @return EnvironmentInterface
*/
$this['environment'] = function () {
return new Environment($_SERVER);
};
}
if (!isset($this['request'])) {
/**
* PSR-7 Request object
*
* @param Container $c
*
* @return ServerRequestInterface
*/
$this['request'] = function ($c) {
return Request::createFromEnvironment($c->get('environment'));
};
}
if (!isset($this['response'])) {
/**
* PSR-7 Response object
*
* @param Container $c
*
* @return ResponseInterface
*/
$this['response'] = function ($c) {
$headers = new Headers(['Content-Type' => 'text/html; charset=UTF-8']);
$response = new Response(200, $headers);
return $response->withProtocolVersion($c->get('settings')['httpVersion']);
};
}
if (!isset($this['router'])) {
/**
* This service MUST return a SHARED instance
* of \Slim\Interfaces\RouterInterface.
*
* @return RouterInterface
*/
$this['router'] = function () {
return new Router;
};
}
if (!isset($this['foundHandler'])) {
/**
* This service MUST return a SHARED instance
* of \Slim\Interfaces\InvocationStrategyInterface.
*
* @return InvocationStrategyInterface
*/
$this['foundHandler'] = function () {
return new RequestResponse;
};
}
if (!isset($this['errorHandler'])) {
/**
* This service MUST return a callable
* that accepts three arguments:
*
* 1. Instance of \Psr\Http\Message\ServerRequestInterface
* 2. Instance of \Psr\Http\Message\ResponseInterface
* 3. Instance of \Exception
*
* The callable MUST return an instance of
* \Psr\Http\Message\ResponseInterface.
*
* @param Container $c
*
* @return callable
*/
$this['errorHandler'] = function ($c) {
return new Error($c->get('settings')['displayErrorDetails']);
};
}
if (!isset($this['notFoundHandler'])) {
/**
* This service MUST return a callable
* that accepts two arguments:
*
* 1. Instance of \Psr\Http\Message\ServerRequestInterface
* 2. Instance of \Psr\Http\Message\ResponseInterface
*
* The callable MUST return an instance of
* \Psr\Http\Message\ResponseInterface.
*
* @return callable
*/
$this['notFoundHandler'] = function () {
return new NotFound;
};
}
if (!isset($this['notAllowedHandler'])) {
/**
* This service MUST return a callable
* that accepts three arguments:
*
* 1. Instance of \Psr\Http\Message\ServerRequestInterface
* 2. Instance of \Psr\Http\Message\ResponseInterface
* 3. Array of allowed HTTP methods
*
* The callable MUST return an instance of
* \Psr\Http\Message\ResponseInterface.
*
* @return callable
*/
$this['notAllowedHandler'] = function () {
return new NotAllowed;
};
}
if (!isset($this['callableResolver'])) {
/**
* Instance of \Slim\Interfaces\CallableResolverInterface
*
* @param Container $c
*
* @return CallableResolverInterface
*/
$this['callableResolver'] = function ($c) {
return new CallableResolver($c);
};
}
}
/********************************************************************************
* Methods to satisfy Interop\Container\ContainerInterface
*******************************************************************************/
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @throws ContainerValueNotFoundException No entry was found for this identifier.
* @throws ContainerException Error while retrieving the entry.
*
* @return mixed Entry.
*/
public function get($id)
{
if (!$this->offsetExists($id)) {
throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id));
}
return $this->offsetGet($id);
}
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* @param string $id Identifier of the entry to look for.
*
* @return boolean
*/
public function has($id)
{
return $this->offsetExists($id);
}
/********************************************************************************
* Magic methods for convenience
*******************************************************************************/
public function __get($name)
{
return $this->get($name);
}
public function __isset($name)
{
return $this->has($name);
}
}
+5 -9
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -140,10 +140,7 @@ class Environment implements \ArrayAccess, \IteratorAggregate
$env['SCRIPT_NAME'] = rtrim($physicalPath, '/'); // <-- Remove trailing slashes $env['SCRIPT_NAME'] = rtrim($physicalPath, '/'); // <-- Remove trailing slashes
// Virtual path // Virtual path
$env['PATH_INFO'] = $requestUri; $env['PATH_INFO'] = substr_replace($requestUri, '', 0, strlen($physicalPath)); // <-- Remove physical path
if (substr($requestUri, 0, strlen($physicalPath)) == $physicalPath) {
$env['PATH_INFO'] = substr($requestUri, strlen($physicalPath)); // <-- Remove physical path
}
$env['PATH_INFO'] = str_replace('?' . $queryString, '', $env['PATH_INFO']); // <-- Remove query string $env['PATH_INFO'] = str_replace('?' . $queryString, '', $env['PATH_INFO']); // <-- Remove query string
$env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/'); // <-- Ensure leading slash $env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/'); // <-- Ensure leading slash
@@ -154,8 +151,7 @@ class Environment implements \ArrayAccess, \IteratorAggregate
$env['SERVER_NAME'] = $_SERVER['SERVER_NAME']; $env['SERVER_NAME'] = $_SERVER['SERVER_NAME'];
//Number of server port that is running the script //Number of server port that is running the script
//Fixes: https://github.com/slimphp/Slim/issues/962 $env['SERVER_PORT'] = $_SERVER['SERVER_PORT'];
$env['SERVER_PORT'] = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80;
//HTTP request headers (retains HTTP_ prefix to match $_SERVER) //HTTP request headers (retains HTTP_ prefix to match $_SERVER)
$headers = \Slim\Http\Headers::extract($_SERVER); $headers = \Slim\Http\Headers::extract($_SERVER);
@@ -195,9 +191,9 @@ class Environment implements \ArrayAccess, \IteratorAggregate
{ {
if (isset($this->properties[$offset])) { if (isset($this->properties[$offset])) {
return $this->properties[$offset]; return $this->properties[$offset];
} else {
return null;
} }
return null;
} }
/** /**
@@ -0,0 +1,20 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/codeguy/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/codeguy/Slim/blob/master/LICENSE (MIT License)
*/
namespace Slim\Exception;
use RuntimeException;
use Interop\Container\Exception\NotFoundException as InteropNotFoundException;
/**
* Not Found Exception
*/
class ContainerValueNotFoundException extends RuntimeException implements InteropNotFoundException
{
}
@@ -0,0 +1,39 @@
<?php
namespace Slim\Exception;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
class MethodNotAllowedException extends SlimException
{
/**
* HTTP methods allowed
*
* @var string[]
*/
protected $allowedMethods;
/**
* Create new exception
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param string[] $allowedMethods
*/
public function __construct(ServerRequestInterface $request, ResponseInterface $response, array $allowedMethods)
{
parent::__construct($request, $response);
$this->allowedMethods = $allowedMethods;
}
/**
* Get allowed methods
*
* @return string[]
*/
public function getAllowedMethods()
{
return $this->allowedMethods;
}
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Slim\Exception;
class NotFoundException extends SlimException
{
}
+1 -1
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
+69
View File
@@ -0,0 +1,69 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Exception;
use Exception;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Stop Exception
*
* This Exception is thrown when the Slim application needs to abort
* processing and return control flow to the outer PHP script.
*/
class SlimException extends Exception
{
/**
* A request object
*
* @var ServerRequestInterface
*/
protected $request;
/**
* A response object to send to the HTTP client
*
* @var ResponseInterface
*/
protected $response;
/**
* Create new exception
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
*/
public function __construct(ServerRequestInterface $request, ResponseInterface $response)
{
parent::__construct();
$this->request = $request;
$this->response = $response;
}
/**
* Get request
*
* @return ServerRequestInterface
*/
public function getRequest()
{
return $this->request;
}
/**
* Get response
*
* @return ResponseInterface
*/
public function getResponse()
{
return $this->response;
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
+239
View File
@@ -0,0 +1,239 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Handlers;
use Exception;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Http\Body;
/**
* Default Slim application error handler
*
* It outputs the error message and diagnostic information in either JSON, XML,
* or HTML based on the Accept header.
*/
class Error
{
protected $displayErrorDetails;
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Constructor
*
* @param boolean $displayErrorDetails Set to true to display full details
*/
public function __construct($displayErrorDetails = false)
{
$this->displayErrorDetails = (bool)$displayErrorDetails;
}
/**
* Invoke error handler
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
* @param Exception $exception The caught Exception object
*
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Exception $exception)
{
$contentType = $this->determineContentType($request);
switch ($contentType) {
case 'application/json':
$output = $this->renderJsonErrorMessage($exception);
break;
case 'text/xml':
case 'application/xml':
$output = $this->renderXmlErrorMessage($exception);
break;
case 'text/html':
$output = $this->renderHtmlErrorMessage($exception);
break;
}
$body = new Body(fopen('php://temp', 'r+'));
$body->write($output);
return $response
->withStatus(500)
->withHeader('Content-type', $contentType)
->withBody($body);
}
/**
* Render HTML error page
*
* @param Exception $exception
* @return string
*/
protected function renderHtmlErrorMessage(Exception $exception)
{
$title = 'Slim Application Error';
if ($this->displayErrorDetails) {
$html = '<p>The application could not run because of the following error:</p>';
$html .= '<h2>Details</h2>';
$html .= $this->renderHtmlException($exception);
while ($exception = $exception->getPrevious()) {
$html .= '<h2>Previous exception</h2>';
$html .= $this->renderHtmlException($exception);
}
} else {
$html = '<p>A website error has occurred. Sorry for the temporary inconvenience.</p>';
}
$output = sprintf(
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" .
"<title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana," .
"sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{" .
"display:inline-block;width:65px;}</style></head><body><h1>%s</h1>%s</body></html>",
$title,
$title,
$html
);
return $output;
}
/**
* Render exception as HTML.
*
* @param Exception $exception
*
* @return string
*/
protected function renderHtmlException(Exception $exception)
{
$html = sprintf('<div><strong>Type:</strong> %s</div>', get_class($exception));
if (($code = $exception->getCode())) {
$html .= sprintf('<div><strong>Code:</strong> %s</div>', $code);
}
if (($message = $exception->getMessage())) {
$html .= sprintf('<div><strong>Message:</strong> %s</div>', htmlentities($message));
}
if (($file = $exception->getFile())) {
$html .= sprintf('<div><strong>File:</strong> %s</div>', $file);
}
if (($line = $exception->getLine())) {
$html .= sprintf('<div><strong>Line:</strong> %s</div>', $line);
}
if (($trace = $exception->getTraceAsString())) {
$html .= '<h2>Trace</h2>';
$html .= sprintf('<pre>%s</pre>', htmlentities($trace));
}
return $html;
}
/**
* Render JSON error
*
* @param Exception $exception
* @return string
*/
protected function renderJsonErrorMessage(Exception $exception)
{
$error = [
'message' => 'Slim Application Error',
];
if ($this->displayErrorDetails) {
$error['exception'] = [];
do {
$error['exception'][] = [
'type' => get_class($exception),
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => explode("\n", $exception->getTraceAsString()),
];
} while ($exception = $exception->getPrevious());
}
return json_encode($error, JSON_PRETTY_PRINT);
}
/**
* Render XML error
*
* @param Exception $exception
* @return string
*/
protected function renderXmlErrorMessage(Exception $exception)
{
$xml = "<error>\n <message>Slim Application Error</message>\n";
if ($this->displayErrorDetails) {
do {
$xml .= " <exception>\n";
$xml .= " <type>" . get_class($exception) . "</type>\n";
$xml .= " <code>" . $exception->getCode() . "</code>\n";
$xml .= " <message>" . $this->createCdataSection($exception->getMessage()) . "</message>\n";
$xml .= " <file>" . $exception->getFile() . "</file>\n";
$xml .= " <line>" . $exception->getLine() . "</line>\n";
$xml .= " <trace>" . $this->createCdataSection($exception->getTraceAsString()) . "</trace>\n";
$xml .= " </exception>\n";
} while ($exception = $exception->getPrevious());
}
$xml .= "</error>";
return $xml;
}
/**
* Returns a CDATA section with the given content.
*
* @param string $content
* @return string
*/
private function createCdataSection($content)
{
return sprintf('<![CDATA[%s]]>', str_replace(']]>', ']]]]><![CDATA[>', $content));
}
/**
* Determine which content type we know about is wanted using Accept header
*
* @param ServerRequestInterface $request
* @return string
*/
private function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return $selectedContentTypes[0];
}
return 'text/html';
}
}
+173
View File
@@ -0,0 +1,173 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Body;
/**
* Default Slim application not allowed handler
*
* It outputs a simple message in either JSON, XML or HTML based on the
* Accept header.
*/
class NotAllowed
{
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Invoke error handler
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
* @param string[] $methods Allowed HTTP methods
*
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, array $methods)
{
if ($request->getMethod() === 'OPTIONS') {
$status = 200;
$contentType = 'text/plain';
$output = $this->renderPlainNotAllowedMessage($methods);
} else {
$status = 405;
$contentType = $this->determineContentType($request);
switch ($contentType) {
case 'application/json':
$output = $this->renderJsonNotAllowedMessage($methods);
break;
case 'text/xml':
case 'application/xml':
$output = $this->renderXmlNotAllowedMessage($methods);
break;
case 'text/html':
$output = $this->renderHtmlNotAllowedMessage($methods);
break;
}
}
$body = new Body(fopen('php://temp', 'r+'));
$body->write($output);
$allow = implode(', ', $methods);
return $response
->withStatus($status)
->withHeader('Content-type', $contentType)
->withHeader('Allow', $allow)
->withBody($body);
}
/**
* Determine which content type we know about is wanted using Accept header
*
* @param ServerRequestInterface $request
* @return string
*/
private function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return $selectedContentTypes[0];
}
return 'text/html';
}
/**
* Render PLAIN not allowed message
*
* @param array $methods
* @return string
*/
protected function renderPlainNotAllowedMessage($methods)
{
$allow = implode(', ', $methods);
return 'Allowed methods: ' . $allow;
}
/**
* Render JSON not allowed message
*
* @param array $methods
* @return string
*/
protected function renderJsonNotAllowedMessage($methods)
{
$allow = implode(', ', $methods);
return '{"message":"Method not allowed. Must be one of: ' . $allow . '"}';
}
/**
* Render XML not allowed message
*
* @param array $methods
* @return string
*/
protected function renderXmlNotAllowedMessage($methods)
{
$allow = implode(', ', $methods);
return "<root><message>Method not allowed. Must be one of: $allow</message></root>";
}
/**
* Render HTML not allowed message
*
* @param array $methods
* @return string
*/
protected function renderHtmlNotAllowedMessage($methods)
{
$allow = implode(', ', $methods);
$output = <<<END
<html>
<head>
<title>Method not allowed</title>
<style>
body{
margin:0;
padding:30px;
font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;
}
h1{
margin:0;
font-size:48px;
font-weight:normal;
line-height:48px;
}
</style>
</head>
<body>
<h1>Method not allowed</h1>
<p>Method not allowed. Must be one of: <strong>$allow</strong></p>
</body>
</html>
END;
return $output;
}
}
+157
View File
@@ -0,0 +1,157 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Body;
/**
* Default Slim application not found handler.
*
* It outputs a simple message in either JSON, XML or HTML based on the
* Accept header.
*/
class NotFound
{
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Invoke not found handler
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
{
$contentType = $this->determineContentType($request);
switch ($contentType) {
case 'application/json':
$output = $this->renderJsonNotFoundOutput($request, $response);
break;
case 'text/xml':
case 'application/xml':
$output = $this->renderXmlNotFoundOutput($request, $response);
break;
case 'text/html':
$output = $this->renderHtmlNotFoundOutput($request, $response);
}
$body = new Body(fopen('php://temp', 'r+'));
$body->write($output);
return $response->withStatus(404)
->withHeader('Content-Type', $contentType)
->withBody($body);
}
/**
* Determine which content type we know about is wanted using Accept header
*
* @param ServerRequestInterface $request
* @return string
*/
private function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return $selectedContentTypes[0];
}
return 'text/html';
}
/**
* Return a response for application/json content not found
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
*/
protected function renderJsonNotFoundOutput(ServerRequestInterface $request, ResponseInterface $response)
{
return '{"message":"Not found"}';
}
/**
* Return a response for xml content not found
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
*/
protected function renderXmlNotFoundOutput(ServerRequestInterface $request, ResponseInterface $response)
{
return '<root><message>Not found</message></root>';
}
/**
* Return a response for text/html content not found
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
*/
protected function renderHtmlNotFoundOutput(ServerRequestInterface $request, ResponseInterface $response)
{
$homeUrl = (string)($request->getUri()->withPath('')->withQuery('')->withFragment(''));
return <<<END
<html>
<head>
<title>Page Not Found</title>
<style>
body{
margin:0;
padding:30px;
font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;
}
h1{
margin:0;
font-size:48px;
font-weight:normal;
line-height:48px;
}
strong{
display:inline-block;
width:65px;
}
</style>
</head>
<body>
<h1>Page Not Found</h1>
<p>
The page you are looking for could not be found. Check the address bar
to ensure your URL is spelled correctly. If all else fails, you can
visit our home page at the link below.
</p>
<a href='$homeUrl'>Visit the Home Page</a>
</body>
</html>
END;
}
}
@@ -0,0 +1,43 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Handlers\Strategies;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Interfaces\InvocationStrategyInterface;
/**
* Default route callback strategy with route parameters as an array of arguments.
*/
class RequestResponse implements InvocationStrategyInterface
{
/**
* Invoke a route callable with request, response, and all route parameters
* as an array of arguments.
*
* @param array|callable $callable
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param array $routeArguments
*
* @return mixed
*/
public function __invoke(
callable $callable,
ServerRequestInterface $request,
ResponseInterface $response,
array $routeArguments
) {
foreach ($routeArguments as $k => $v) {
$request = $request->withAttribute($k, $v);
}
return call_user_func($callable, $request, $response, $routeArguments);
}
}
@@ -0,0 +1,42 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Handlers\Strategies;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Interfaces\InvocationStrategyInterface;
/**
* Route callback strategy with route parameters as individual arguments.
*/
class RequestResponseArgs implements InvocationStrategyInterface
{
/**
* Invoke a route callable with request, response and all route parameters
* as individual arguments.
*
* @param array|callable $callable
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param array $routeArguments
*
* @return mixed
*/
public function __invoke(
callable $callable,
ServerRequestInterface $request,
ResponseInterface $response,
array $routeArguments
) {
array_unshift($routeArguments, $request, $response);
return call_user_func_array($callable, $routeArguments);
}
}
+6 -6
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -160,7 +160,7 @@ class Set implements \ArrayAccess, \Countable, \IteratorAggregate
public function __unset($key) public function __unset($key)
{ {
$this->remove($key); return $this->remove($key);
} }
/** /**
@@ -215,8 +215,8 @@ class Set implements \ArrayAccess, \Countable, \IteratorAggregate
/** /**
* Ensure a value or object will remain globally unique * Ensure a value or object will remain globally unique
* @param string $key The value or object name * @param string $key The value or object name
* @param \Closure $value The closure that defines the object * @param Closure The closure that defines the object
* @return mixed * @return mixed
*/ */
public function singleton($key, $value) public function singleton($key, $value)
@@ -234,8 +234,8 @@ class Set implements \ArrayAccess, \Countable, \IteratorAggregate
/** /**
* Protect closure from being directly invoked * Protect closure from being directly invoked
* @param \Closure $callable A closure to keep from being invoked and evaluated * @param Closure $callable A closure to keep from being invoked and evaluated
* @return \Closure * @return Closure
*/ */
public function protect(\Closure $callable) public function protect(\Closure $callable)
{ {
+22
View File
@@ -0,0 +1,22 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Http;
/**
* Body
*
* This class represents an HTTP message body and encapsulates a
* streamable resource according to the PSR-7 standard.
*
* @link https://github.com/php-fig/http-message/blob/master/src/StreamInterface.php
*/
class Body extends Stream
{
}
+161 -62
View File
@@ -1,91 +1,190 @@
<?php <?php
/** /**
* Slim - a micro PHP 5 framework * Slim Framework (http://slimframework.com)
* *
* @author Josh Lockhart <[email protected]> * @link https://github.com/slimphp/Slim
* @copyright 2011 Josh Lockhart * @copyright Copyright (c) 2011-2015 Josh Lockhart
* @link http://www.slimframework.com * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
* @license http://www.slimframework.com/license
* @version 2.6.1
* @package Slim
*
* MIT LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
namespace Slim\Http; namespace Slim\Http;
class Cookies extends \Slim\Helper\Set use InvalidArgumentException;
use Slim\Interfaces\Http\CookiesInterface;
/**
* Cookie helper
*/
class Cookies implements CookiesInterface
{ {
/** /**
* Default cookie settings * Cookies from HTTP request
*
* @var array * @var array
*/ */
protected $defaults = array( protected $requestCookies = [];
/**
* Cookies for HTTP response
*
* @var array
*/
protected $responseCookies = [];
/**
* Default cookie properties
*
* @var array
*/
protected $defaults = [
'value' => '', 'value' => '',
'domain' => null, 'domain' => null,
'path' => null, 'path' => null,
'expires' => null, 'expires' => null,
'secure' => false, 'secure' => false,
'httponly' => false 'httponly' => false
); ];
/** /**
* Set cookie * Create new cookies helper
* *
* The second argument may be a single scalar value, in which case * @param array $cookies
* it will be merged with the default settings and considered the `value`
* of the merged result.
*
* The second argument may also be an array containing any or all of
* the keys shown in the default settings above. This array will be
* merged with the defaults shown above.
*
* @param string $key Cookie name
* @param mixed $value Cookie settings
*/ */
public function set($key, $value) public function __construct(array $cookies = [])
{ {
if (is_array($value)) { $this->requestCookies = $cookies;
$cookieSettings = array_replace($this->defaults, $value);
} else {
$cookieSettings = array_replace($this->defaults, array('value' => $value));
}
parent::set($key, $cookieSettings);
} }
/** /**
* Remove cookie * Set default cookie properties
* *
* Unlike \Slim\Helper\Set, this will actually *set* a cookie with * @param array $settings
* an expiration date in the past. This expiration date will force
* the client-side cache to remove its cookie with the given name
* and settings.
*
* @param string $key Cookie name
* @param array $settings Optional cookie settings
*/ */
public function remove($key, $settings = array()) public function setDefaults(array $settings)
{ {
$settings['value'] = ''; $this->defaults = array_replace($this->defaults, $settings);
$settings['expires'] = time() - 86400; }
$this->set($key, array_replace($this->defaults, $settings));
/**
* Get request cookie
*
* @param string $name Cookie name
* @param mixed $default Cookie default value
*
* @return mixed Cookie value if present, else default
*/
public function get($name, $default = null)
{
return isset($this->requestCookies[$name]) ? $this->requestCookies[$name] : $default;
}
/**
* Set response cookie
*
* @param string $name Cookie name
* @param string|array $value Cookie value, or cookie properties
*/
public function set($name, $value)
{
if (!is_array($value)) {
$value = ['value' => (string)$value];
}
$this->responseCookies[$name] = array_replace($this->defaults, $value);
}
/**
* Convert to `Set-Cookie` headers
*
* @return string[]
*/
public function toHeaders()
{
$headers = [];
foreach ($this->responseCookies as $name => $properties) {
$headers[] = $this->toHeader($name, $properties);
}
return $headers;
}
/**
* Convert to `Set-Cookie` header
*
* @param string $name Cookie name
* @param array $properties Cookie properties
*
* @return string
*/
protected function toHeader($name, array $properties)
{
$result = urlencode($name) . '=' . urlencode($properties['value']);
if (isset($properties['domain'])) {
$result .= '; domain=' . $properties['domain'];
}
if (isset($properties['path'])) {
$result .= '; path=' . $properties['path'];
}
if (isset($properties['expires'])) {
if (is_string($properties['expires'])) {
$timestamp = strtotime($properties['expires']);
} else {
$timestamp = (int)$properties['expires'];
}
if ($timestamp !== 0) {
$result .= '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp);
}
}
if (isset($properties['secure']) && $properties['secure']) {
$result .= '; secure';
}
if (isset($properties['httponly']) && $properties['httponly']) {
$result .= '; HttpOnly';
}
return $result;
}
/**
* Parse HTTP request `Cookie:` header and extract
* into a PHP associative array.
*
* @param string $header The raw HTTP request `Cookie:` header
*
* @return array Associative array of cookie names and values
*
* @throws InvalidArgumentException if the cookie data cannot be parsed
*/
public static function parseHeader($header)
{
if (is_array($header) === true) {
$header = isset($header[0]) ? $header[0] : '';
}
if (is_string($header) === false) {
throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.');
}
$header = rtrim($header, "\r\n");
$pieces = preg_split('@\s*[;,]\s*@', $header);
$cookies = [];
foreach ($pieces as $cookie) {
$cookie = explode('=', $cookie, 2);
if (count($cookie) === 2) {
$key = urldecode($cookie[0]);
$value = urldecode($cookie[1]);
if (!isset($cookies[$key])) {
$cookies[$key] = $value;
}
}
}
return $cookies;
} }
} }
+52
View File
@@ -0,0 +1,52 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Http;
use Slim\Collection;
use Slim\Interfaces\Http\EnvironmentInterface;
/**
* Environment
*
* This class decouples the Slim application from the global PHP environment.
* This is particularly useful for unit testing, but it also lets us create
* custom sub-requests.
*/
class Environment extends Collection implements EnvironmentInterface
{
/**
* Create mock environment
*
* @param array $userData Array of custom environment keys and values
*
* @return self
*/
public static function mock(array $userData = [])
{
$data = array_merge([
'SERVER_PROTOCOL' => 'HTTP/1.1',
'REQUEST_METHOD' => 'GET',
'SCRIPT_NAME' => '',
'REQUEST_URI' => '',
'QUERY_STRING' => '',
'SERVER_NAME' => 'localhost',
'SERVER_PORT' => 80,
'HTTP_HOST' => 'localhost',
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8',
'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'HTTP_USER_AGENT' => 'Slim Framework',
'REMOTE_ADDR' => '127.0.0.1',
'REQUEST_TIME' => time(),
'REQUEST_TIME_FLOAT' => microtime(true),
], $userData);
return new static($data);
}
}
+166 -73
View File
@@ -1,103 +1,196 @@
<?php <?php
/** /**
* Slim - a micro PHP 5 framework * Slim Framework (http://slimframework.com)
* *
* @author Josh Lockhart <[email protected]> * @link https://github.com/slimphp/Slim
* @copyright 2011 Josh Lockhart * @copyright Copyright (c) 2011-2015 Josh Lockhart
* @link http://www.slimframework.com * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
* @license http://www.slimframework.com/license
* @version 2.6.1
* @package Slim
*
* MIT LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
namespace Slim\Http; namespace Slim\Http;
/** use Slim\Collection;
* HTTP Headers use Slim\Interfaces\Http\HeadersInterface;
*
* @package Slim
* @author Josh Lockhart
* @since 1.6.0
*/
class Headers extends \Slim\Helper\Set
{
/********************************************************************************
* Static interface
*******************************************************************************/
/**
* Headers
*
* This class represents a collection of HTTP headers
* that is used in both the HTTP request and response objects.
* It also enables header name case-insensitivity when
* getting or setting a header value.
*
* Each HTTP header can have multiple values. This class
* stores values into an array for each header name. When
* you request a header value, you receive an array of values
* for that header.
*/
class Headers extends Collection implements HeadersInterface
{
/** /**
* Special-case HTTP headers that are otherwise unidentifiable as HTTP headers. * Special HTTP headers that do not have the "HTTP_" prefix
* Typically, HTTP headers in the $_SERVER array will be prefixed with
* `HTTP_` or `X_`. These are not so we list them here for later reference.
* *
* @var array * @var array
*/ */
protected static $special = array( protected static $special = [
'CONTENT_TYPE', 'CONTENT_TYPE' => 1,
'CONTENT_LENGTH', 'CONTENT_LENGTH' => 1,
'PHP_AUTH_USER', 'PHP_AUTH_USER' => 1,
'PHP_AUTH_PW', 'PHP_AUTH_PW' => 1,
'PHP_AUTH_DIGEST', 'PHP_AUTH_DIGEST' => 1,
'AUTH_TYPE' 'AUTH_TYPE' => 1,
); ];
/** /**
* Extract HTTP headers from an array of data (e.g. $_SERVER) * Create new headers collection with data extracted from
* @param array $data * the application Environment object
* @return array *
* @param Environment $environment The Slim application Environment
*
* @return self
*/ */
public static function extract($data) public static function createFromEnvironment(Environment $environment)
{ {
$results = array(); $data = [];
foreach ($data as $key => $value) { foreach ($environment as $key => $value) {
$key = strtoupper($key); $key = strtoupper($key);
if (strpos($key, 'X_') === 0 || strpos($key, 'HTTP_') === 0 || in_array($key, static::$special)) { if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) {
if ($key === 'HTTP_CONTENT_LENGTH') { if ($key !== 'HTTP_CONTENT_LENGTH') {
continue; $data[$key] = $value;
} }
$results[$key] = $value;
} }
} }
return $results; return new static($data);
} }
/******************************************************************************** /**
* Instance interface * Return array of HTTP header names and values.
*******************************************************************************/ * This method returns the _original_ header name
* as specified by the end user.
*
* @return array
*/
public function all()
{
$all = parent::all();
$out = [];
foreach ($all as $key => $props) {
$out[$props['originalKey']] = $props['value'];
}
return $out;
}
/** /**
* Transform header name into canonical form * Set HTTP header value
* @param string $key *
* This method sets a header value. It replaces
* any values that may already exist for the header name.
*
* @param string $key The case-insensitive header name
* @param string $value The header value
*/
public function set($key, $value)
{
if (!is_array($value)) {
$value = [$value];
}
parent::set($this->normalizeKey($key), [
'value' => $value,
'originalKey' => $key
]);
}
/**
* Get HTTP header value
*
* @param string $key The case-insensitive header name
* @param mixed $default The default value if key does not exist
*
* @return string[]
*/
public function get($key, $default = null)
{
if ($this->has($key)) {
return parent::get($this->normalizeKey($key))['value'];
}
return $default;
}
/**
* Get HTTP header key as originally specified
*
* @param string $key The case-insensitive header name
* @param mixed $default The default value if key does not exist
*
* @return string * @return string
*/ */
protected function normalizeKey($key) public function getOriginalKey($key, $default = null)
{ {
$key = strtolower($key); if ($this->has($key)) {
$key = str_replace(array('-', '_'), ' ', $key); return parent::get($this->normalizeKey($key))['originalKey'];
$key = preg_replace('#^http #', '', $key); }
$key = ucwords($key);
$key = str_replace(' ', '-', $key); return $default;
}
/**
* Add HTTP header value
*
* This method appends a header value. Unlike the set() method,
* this method _appends_ this new value to any values
* that already exist for this header name.
*
* @param string $key The case-insensitive header name
* @param array|string $value The new header value(s)
*/
public function add($key, $value)
{
$oldValues = $this->get($key, []);
$newValues = is_array($value) ? $value : [$value];
$this->set($key, array_merge($oldValues, array_values($newValues)));
}
/**
* Does this collection have a given header?
*
* @param string $key The case-insensitive header name
*
* @return bool
*/
public function has($key)
{
return parent::has($this->normalizeKey($key));
}
/**
* Remove header from collection
*
* @param string $key The case-insensitive header name
*/
public function remove($key)
{
parent::remove($this->normalizeKey($key));
}
/**
* Normalize header name
*
* This method transforms header names into a
* normalized form. This is how we enable case-insensitive
* header names in the other methods in this class.
*
* @param string $key The case-insensitive header name
*
* @return string Normalized header name
*/
public function normalizeKey($key)
{
$key = strtr(strtolower($key), '_', '-');
if (strpos($key, 'http-') === 0) {
$key = substr($key, 5);
}
return $key; return $key;
} }
+295
View File
@@ -0,0 +1,295 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Http;
use InvalidArgumentException;
use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\StreamInterface;
/**
* Abstract message (base class for Request and Response)
*
* This class represents a general HTTP message. It provides common properties and methods for
* the HTTP request and response, as defined in the PSR-7 MessageInterface.
*
* @link https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
* @see Slim\Http\Request
* @see Slim\Http\Response
*/
abstract class Message implements MessageInterface
{
/**
* Protocol version
*
* @var string
*/
protected $protocolVersion = '1.1';
/**
* Headers
*
* @var \Slim\Interfaces\Http\HeadersInterface
*/
protected $headers;
/**
* Body object
*
* @var \Psr\Http\Message\StreamInterface
*/
protected $body;
/**
* Disable magic setter to ensure immutability
*/
public function __set($name, $value)
{
// Do nothing
}
/*******************************************************************************
* Protocol
******************************************************************************/
/**
* Retrieves the HTTP protocol version as a string.
*
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
*
* @return string HTTP protocol version.
*/
public function getProtocolVersion()
{
return $this->protocolVersion;
}
/**
* Return an instance with the specified HTTP protocol version.
*
* The version string MUST contain only the HTTP version number (e.g.,
* "1.1", "1.0").
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new protocol version.
*
* @param string $version HTTP protocol version
* @return static
* @throws InvalidArgumentException if the http version is an invalid number
*/
public function withProtocolVersion($version)
{
static $valid = [
'1.0' => true,
'1.1' => true,
'2.0' => true,
];
if (!isset($valid[$version])) {
throw new InvalidArgumentException('Invalid HTTP version. Must be one of: 1.0, 1.1, 2.0');
}
$clone = clone $this;
$clone->protocolVersion = $version;
return $clone;
}
/*******************************************************************************
* Headers
******************************************************************************/
/**
* Retrieves all message header values.
*
* The keys represent the header name as it will be sent over the wire, and
* each value is an array of strings associated with the header.
*
* // Represent the headers as a string
* foreach ($message->getHeaders() as $name => $values) {
* echo $name . ": " . implode(", ", $values);
* }
*
* // Emit headers iteratively:
* foreach ($message->getHeaders() as $name => $values) {
* foreach ($values as $value) {
* header(sprintf('%s: %s', $name, $value), false);
* }
* }
*
* While header names are not case-sensitive, getHeaders() will preserve the
* exact case in which headers were originally specified.
*
* @return array Returns an associative array of the message's headers. Each
* key MUST be a header name, and each value MUST be an array of strings
* for that header.
*/
public function getHeaders()
{
return $this->headers->all();
}
/**
* Checks if a header exists by the given case-insensitive name.
*
* @param string $name Case-insensitive header field name.
* @return bool Returns true if any header names match the given header
* name using a case-insensitive string comparison. Returns false if
* no matching header name is found in the message.
*/
public function hasHeader($name)
{
return $this->headers->has($name);
}
/**
* Retrieves a message header value by the given case-insensitive name.
*
* This method returns an array of all the header values of the given
* case-insensitive header name.
*
* If the header does not appear in the message, this method MUST return an
* empty array.
*
* @param string $name Case-insensitive header field name.
* @return string[] An array of string values as provided for the given
* header. If the header does not appear in the message, this method MUST
* return an empty array.
*/
public function getHeader($name)
{
return $this->headers->get($name, []);
}
/**
* Retrieves a comma-separated string of the values for a single header.
*
* This method returns all of the header values of the given
* case-insensitive header name as a string concatenated together using
* a comma.
*
* NOTE: Not all header values may be appropriately represented using
* comma concatenation. For such headers, use getHeader() instead
* and supply your own delimiter when concatenating.
*
* If the header does not appear in the message, this method MUST return
* an empty string.
*
* @param string $name Case-insensitive header field name.
* @return string A string of values as provided for the given header
* concatenated together using a comma. If the header does not appear in
* the message, this method MUST return an empty string.
*/
public function getHeaderLine($name)
{
return implode(',', $this->headers->get($name, []));
}
/**
* Return an instance with the provided value replacing the specified header.
*
* While header names are case-insensitive, the casing of the header will
* be preserved by this function, and returned from getHeaders().
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new and/or updated header and value.
*
* @param string $name Case-insensitive header field name.
* @param string|string[] $value Header value(s).
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withHeader($name, $value)
{
$clone = clone $this;
$clone->headers->set($name, $value);
return $clone;
}
/**
* Return an instance with the specified header appended with the given value.
*
* Existing values for the specified header will be maintained. The new
* value(s) will be appended to the existing list. If the header did not
* exist previously, it will be added.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new header and/or value.
*
* @param string $name Case-insensitive header field name to add.
* @param string|string[] $value Header value(s).
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withAddedHeader($name, $value)
{
$clone = clone $this;
$clone->headers->add($name, $value);
return $clone;
}
/**
* Return an instance without the specified header.
*
* Header resolution MUST be done without case-sensitivity.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that removes
* the named header.
*
* @param string $name Case-insensitive header field name to remove.
* @return static
*/
public function withoutHeader($name)
{
$clone = clone $this;
$clone->headers->remove($name);
return $clone;
}
/*******************************************************************************
* Body
******************************************************************************/
/**
* Gets the body of the message.
*
* @return StreamInterface Returns the body as a stream.
*/
public function getBody()
{
return $this->body;
}
/**
* Return an instance with the specified message body.
*
* The body MUST be a StreamInterface object.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return a new instance that has the
* new body stream.
*
* @param StreamInterface $body Body.
* @return static
* @throws \InvalidArgumentException When the body is not valid.
*/
public function withBody(StreamInterface $body)
{
// TODO: Test for invalid body?
$clone = clone $this;
$clone->body = $body;
return $clone;
}
}
+880 -421
View File
File diff suppressed because it is too large Load Diff
+27
View File
@@ -0,0 +1,27 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Http;
/**
* Provides a PSR-7 implementation of a reusable raw request body
*/
class RequestBody extends Body
{
/**
* Create a new RequestBody.
*/
public function __construct()
{
$stream = fopen('php://temp', 'w+');
stream_copy_to_stream(fopen('php://input', 'r'), $stream);
rewind($stream);
parent::__construct($stream);
}
}
+294 -364
View File
@@ -1,520 +1,450 @@
<?php <?php
/** /**
* Slim - a micro PHP 5 framework * Slim Framework (http://slimframework.com)
* *
* @author Josh Lockhart <[email protected]> * @link https://github.com/slimphp/Slim
* @copyright 2011 Josh Lockhart * @copyright Copyright (c) 2011-2015 Josh Lockhart
* @link http://www.slimframework.com * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
* @license http://www.slimframework.com/license
* @version 2.6.1
* @package Slim
*
* MIT LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
namespace Slim\Http; namespace Slim\Http;
use InvalidArgumentException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UriInterface;
use Slim\Interfaces\Http\HeadersInterface;
/** /**
* Response * Response
* *
* This is a simple abstraction over top an HTTP response. This * This class represents an HTTP response. It manages
* provides methods to set the HTTP status, the HTTP headers, * the response status, headers, and body
* and the HTTP body. * according to the PSR-7 standard.
* *
* @package Slim * @link https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
* @author Josh Lockhart * @link https://github.com/php-fig/http-message/blob/master/src/ResponseInterface.php
* @since 1.0.0
*/ */
class Response implements \ArrayAccess, \Countable, \IteratorAggregate class Response extends Message implements ResponseInterface
{ {
/** /**
* @var int HTTP status code * Status code
*
* @var int
*/ */
protected $status; protected $status = 200;
/** /**
* @var \Slim\Http\Headers * Reason phrase
*
* @var string
*/ */
public $headers; protected $reasonPhrase = '';
/** /**
* @var \Slim\Http\Cookies * Status codes and reason phrases
*
* @var array
*/ */
public $cookies; protected static $messages = [
/**
* @var string HTTP response body
*/
protected $body;
/**
* @var int Length of HTTP response body
*/
protected $length;
/**
* @var array HTTP response codes and messages
*/
protected static $messages = array(
//Informational 1xx //Informational 1xx
100 => '100 Continue', 100 => 'Continue',
101 => '101 Switching Protocols', 101 => 'Switching Protocols',
102 => 'Processing',
//Successful 2xx //Successful 2xx
200 => '200 OK', 200 => 'OK',
201 => '201 Created', 201 => 'Created',
202 => '202 Accepted', 202 => 'Accepted',
203 => '203 Non-Authoritative Information', 203 => 'Non-Authoritative Information',
204 => '204 No Content', 204 => 'No Content',
205 => '205 Reset Content', 205 => 'Reset Content',
206 => '206 Partial Content', 206 => 'Partial Content',
226 => '226 IM Used', 207 => 'Multi-Status',
208 => 'Already Reported',
226 => 'IM Used',
//Redirection 3xx //Redirection 3xx
300 => '300 Multiple Choices', 300 => 'Multiple Choices',
301 => '301 Moved Permanently', 301 => 'Moved Permanently',
302 => '302 Found', 302 => 'Found',
303 => '303 See Other', 303 => 'See Other',
304 => '304 Not Modified', 304 => 'Not Modified',
305 => '305 Use Proxy', 305 => 'Use Proxy',
306 => '306 (Unused)', 306 => '(Unused)',
307 => '307 Temporary Redirect', 307 => 'Temporary Redirect',
308 => 'Permanent Redirect',
//Client Error 4xx //Client Error 4xx
400 => '400 Bad Request', 400 => 'Bad Request',
401 => '401 Unauthorized', 401 => 'Unauthorized',
402 => '402 Payment Required', 402 => 'Payment Required',
403 => '403 Forbidden', 403 => 'Forbidden',
404 => '404 Not Found', 404 => 'Not Found',
405 => '405 Method Not Allowed', 405 => 'Method Not Allowed',
406 => '406 Not Acceptable', 406 => 'Not Acceptable',
407 => '407 Proxy Authentication Required', 407 => 'Proxy Authentication Required',
408 => '408 Request Timeout', 408 => 'Request Timeout',
409 => '409 Conflict', 409 => 'Conflict',
410 => '410 Gone', 410 => 'Gone',
411 => '411 Length Required', 411 => 'Length Required',
412 => '412 Precondition Failed', 412 => 'Precondition Failed',
413 => '413 Request Entity Too Large', 413 => 'Request Entity Too Large',
414 => '414 Request-URI Too Long', 414 => 'Request-URI Too Long',
415 => '415 Unsupported Media Type', 415 => 'Unsupported Media Type',
416 => '416 Requested Range Not Satisfiable', 416 => 'Requested Range Not Satisfiable',
417 => '417 Expectation Failed', 417 => 'Expectation Failed',
418 => '418 I\'m a teapot', 418 => 'I\'m a teapot',
422 => '422 Unprocessable Entity', 422 => 'Unprocessable Entity',
423 => '423 Locked', 423 => 'Locked',
426 => '426 Upgrade Required', 424 => 'Failed Dependency',
428 => '428 Precondition Required', 426 => 'Upgrade Required',
429 => '429 Too Many Requests', 428 => 'Precondition Required',
431 => '431 Request Header Fields Too Large', 429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
//Server Error 5xx //Server Error 5xx
500 => '500 Internal Server Error', 500 => 'Internal Server Error',
501 => '501 Not Implemented', 501 => 'Not Implemented',
502 => '502 Bad Gateway', 502 => 'Bad Gateway',
503 => '503 Service Unavailable', 503 => 'Service Unavailable',
504 => '504 Gateway Timeout', 504 => 'Gateway Timeout',
505 => '505 HTTP Version Not Supported', 505 => 'HTTP Version Not Supported',
506 => '506 Variant Also Negotiates', 506 => 'Variant Also Negotiates',
510 => '510 Not Extended', 507 => 'Insufficient Storage',
511 => '511 Network Authentication Required' 508 => 'Loop Detected',
); 510 => 'Not Extended',
511 => 'Network Authentication Required',
];
/** /**
* Constructor * Create new HTTP response.
* @param string $body The HTTP response body *
* @param int $status The HTTP response status * @param int $status The response status code.
* @param \Slim\Http\Headers|array $headers The HTTP response headers * @param HeadersInterface|null $headers The response headers.
* @param StreamInterface|null $body The response body.
*/ */
public function __construct($body = '', $status = 200, $headers = array()) public function __construct($status = 200, HeadersInterface $headers = null, StreamInterface $body = null)
{ {
$this->setStatus($status); $this->status = $this->filterStatus($status);
$this->headers = new \Slim\Http\Headers(array('Content-Type' => 'text/html')); $this->headers = $headers ? $headers : new Headers();
$this->headers->replace($headers); $this->body = $body ? $body : new Body(fopen('php://temp', 'r+'));
$this->cookies = new \Slim\Http\Cookies();
$this->write($body);
} }
public function getStatus() /**
* This method is applied to the cloned object
* after PHP performs an initial shallow-copy. This
* method completes a deep-copy by creating new objects
* for the cloned object's internal reference pointers.
*/
public function __clone()
{
$this->headers = clone $this->headers;
$this->body = clone $this->body;
}
/*******************************************************************************
* Status
******************************************************************************/
/**
* Gets the response status code.
*
* The status code is a 3-digit integer result code of the server's attempt
* to understand and satisfy the request.
*
* @return int Status code.
*/
public function getStatusCode()
{ {
return $this->status; return $this->status;
} }
public function setStatus($status) /**
* Return an instance with the specified status code and, optionally, reason phrase.
*
* If no reason phrase is specified, implementations MAY choose to default
* to the RFC 7231 or IANA recommended reason phrase for the response's
* status code.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* updated status and reason phrase.
*
* @link http://tools.ietf.org/html/rfc7231#section-6
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
* @param int $code The 3-digit integer result code to set.
* @param string $reasonPhrase The reason phrase to use with the
* provided status code; if none is provided, implementations MAY
* use the defaults as suggested in the HTTP specification.
* @return self
* @throws \InvalidArgumentException For invalid status code arguments.
*/
public function withStatus($code, $reasonPhrase = '')
{ {
$this->status = (int)$status; $code = $this->filterStatus($code);
if (!is_string($reasonPhrase) && !method_exists($reasonPhrase, '__toString')) {
throw new InvalidArgumentException('ReasonPhrase must be a string');
}
$clone = clone $this;
$clone->status = $code;
if ($reasonPhrase === '' && isset(static::$messages[$code])) {
$reasonPhrase = static::$messages[$code];
}
if ($reasonPhrase === '') {
throw new InvalidArgumentException('ReasonPhrase must be supplied for this code');
}
$clone->reasonPhrase = $reasonPhrase;
return $clone;
} }
/** /**
* DEPRECATION WARNING! Use `getStatus` or `setStatus` instead. * Filter HTTP status code.
* *
* Get and set status * @param int $status HTTP status code.
* @param int|null $status
* @return int * @return int
* @throws \InvalidArgumentException If an invalid HTTP status code is provided.
*/ */
public function status($status = null) protected function filterStatus($status)
{ {
if (!is_null($status)) { if (!is_integer($status) || $status<100 || $status>599) {
$this->status = (int) $status; throw new InvalidArgumentException('Invalid HTTP status code');
} }
return $this->status; return $status;
} }
/** /**
* DEPRECATION WARNING! Access `headers` property directly. * Gets the response reason phrase associated with the status code.
* *
* Get and set header * Because a reason phrase is not a required element in a response
* @param string $name Header name * status line, the reason phrase value MAY be null. Implementations MAY
* @param string|null $value Header value * choose to return the default RFC 7231 recommended reason phrase (or those
* @return string Header value * listed in the IANA HTTP Status Code Registry) for the response's
* status code.
*
* @link http://tools.ietf.org/html/rfc7231#section-6
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
* @return string Reason phrase; must return an empty string if none present.
*/ */
public function header($name, $value = null) public function getReasonPhrase()
{ {
if (!is_null($value)) { if ($this->reasonPhrase) {
$this->headers->set($name, $value); return $this->reasonPhrase;
} }
if (isset(static::$messages[$this->status])) {
return $this->headers->get($name); return static::$messages[$this->status];
}
/**
* DEPRECATION WARNING! Access `headers` property directly.
*
* Get headers
* @return \Slim\Http\Headers
*/
public function headers()
{
return $this->headers;
}
public function getBody()
{
return $this->body;
}
public function setBody($content)
{
$this->write($content, true);
}
/**
* DEPRECATION WARNING! use `getBody` or `setBody` instead.
*
* Get and set body
* @param string|null $body Content of HTTP response body
* @return string
*/
public function body($body = null)
{
if (!is_null($body)) {
$this->write($body, true);
} }
return '';
return $this->body;
} }
/*******************************************************************************
* Body
******************************************************************************/
/** /**
* Append HTTP response body * Write data to the response body.
* @param string $body Content to append to the current HTTP response body *
* @param bool $replace Overwrite existing response body? * Note: This method is not part of the PSR-7 standard.
* @return string The updated HTTP response body *
* Proxies to the underlying stream and writes the provided data to it.
*
* @param string $data
* @return self
*/ */
public function write($body, $replace = false) public function write($data)
{ {
if ($replace) { $this->getBody()->write($data);
$this->body = $body;
} else {
$this->body .= (string)$body;
}
$this->length = strlen($this->body);
return $this->body; return $this;
} }
public function getLength() /*******************************************************************************
{ * Response Helpers
return $this->length; ******************************************************************************/
}
/** /**
* DEPRECATION WARNING! Use `getLength` or `write` or `body` instead. * Redirect.
* *
* Get and set length * Note: This method is not part of the PSR-7 standard.
* @param int|null $length *
* @return int * This method prepares the response object to return an HTTP Redirect
* response to the client.
*
* @param string|UriInterface $url The redirect destination.
* @param int $status The redirect HTTP status code.
* @return self
*/ */
public function length($length = null) public function withRedirect($url, $status = 302)
{ {
if (!is_null($length)) { return $this->withStatus($status)->withHeader('Location', (string)$url);
$this->length = (int) $length;
}
return $this->length;
} }
/** /**
* Finalize * Json.
* *
* This prepares this response and returns an array * Note: This method is not part of the PSR-7 standard.
* of [status, headers, body]. This array is passed to outer middleware
* if available or directly to the Slim run method.
* *
* @return array[int status, array headers, string body] * This method prepares the response object to return an HTTP Json
* response to the client.
*
* @param mixed $data The data
* @param int $status The HTTP status code.
* @param int $encodingOptions Json encoding options
* @return self
*/ */
public function finalize() public function withJson($data, $status = 200, $encodingOptions = 0)
{ {
// Prepare response $body = $this->getBody();
if (in_array($this->status, array(204, 304))) { $body->rewind();
$this->headers->remove('Content-Type'); $body->write(json_encode($data, $encodingOptions));
$this->headers->remove('Content-Length');
$this->setBody('');
}
return array($this->status, $this->headers, $this->body); return $this->withStatus($status)->withHeader('Content-Type', 'application/json;charset=utf-8');
} }
/** /**
* DEPRECATION WARNING! Access `cookies` property directly. * Is this response empty?
* *
* Set cookie * Note: This method is not part of the PSR-7 standard.
* *
* Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
* header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
* response's header is passed by reference to the utility class and is directly modified. By not
* relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
* analyze the raw header before the response is ultimately delivered to the HTTP client.
*
* @param string $name The name of the cookie
* @param string|array $value If string, the value of cookie; if array, properties for
* cookie including: value, expire, path, domain, secure, httponly
*/
public function setCookie($name, $value)
{
// Util::setCookieHeader($this->header, $name, $value);
$this->cookies->set($name, $value);
}
/**
* DEPRECATION WARNING! Access `cookies` property directly.
*
* Delete cookie
*
* Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
* header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
* response's header is passed by reference to the utility class and is directly modified. By not
* relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
* analyze the raw header before the response is ultimately delivered to the HTTP client.
*
* This method will set a cookie with the given name that has an expiration time in the past; this will
* prompt the HTTP client to invalidate and remove the client-side cookie. Optionally, you may
* also pass a key/value array as the second argument. If the "domain" key is present in this
* array, only the Cookie with the given name AND domain will be removed. The invalidating cookie
* sent with this response will adopt all properties of the second argument.
*
* @param string $name The name of the cookie
* @param array $settings Properties for cookie including: value, expire, path, domain, secure, httponly
*/
public function deleteCookie($name, $settings = array())
{
$this->cookies->remove($name, $settings);
// Util::deleteCookieHeader($this->header, $name, $value);
}
/**
* Redirect
*
* This method prepares this response to return an HTTP Redirect response
* to the HTTP client.
*
* @param string $url The redirect destination
* @param int $status The redirect HTTP status code
*/
public function redirect ($url, $status = 302)
{
$this->setStatus($status);
$this->headers->set('Location', $url);
}
/**
* Helpers: Empty?
* @return bool * @return bool
*/ */
public function isEmpty() public function isEmpty()
{ {
return in_array($this->status, array(201, 204, 304)); return in_array($this->getStatusCode(), [204, 205, 304]);
} }
/** /**
* Helpers: Informational? * Is this response informational?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isInformational() public function isInformational()
{ {
return $this->status >= 100 && $this->status < 200; return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200;
} }
/** /**
* Helpers: OK? * Is this response OK?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isOk() public function isOk()
{ {
return $this->status === 200; return $this->getStatusCode() === 200;
} }
/** /**
* Helpers: Successful? * Is this response successful?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isSuccessful() public function isSuccessful()
{ {
return $this->status >= 200 && $this->status < 300; return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300;
} }
/** /**
* Helpers: Redirect? * Is this response a redirect?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isRedirect() public function isRedirect()
{ {
return in_array($this->status, array(301, 302, 303, 307)); return in_array($this->getStatusCode(), [301, 302, 303, 307]);
} }
/** /**
* Helpers: Redirection? * Is this response a redirection?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isRedirection() public function isRedirection()
{ {
return $this->status >= 300 && $this->status < 400; return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400;
} }
/** /**
* Helpers: Forbidden? * Is this response forbidden?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
* @api
*/ */
public function isForbidden() public function isForbidden()
{ {
return $this->status === 403; return $this->getStatusCode() === 403;
} }
/** /**
* Helpers: Not Found? * Is this response not Found?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isNotFound() public function isNotFound()
{ {
return $this->status === 404; return $this->getStatusCode() === 404;
} }
/** /**
* Helpers: Client error? * Is this response a client error?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isClientError() public function isClientError()
{ {
return $this->status >= 400 && $this->status < 500; return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500;
} }
/** /**
* Helpers: Server Error? * Is this response a server error?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool * @return bool
*/ */
public function isServerError() public function isServerError()
{ {
return $this->status >= 500 && $this->status < 600; return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600;
} }
/** /**
* DEPRECATION WARNING! ArrayAccess interface will be removed from \Slim\Http\Response. * Convert response to string.
* Iterate `headers` or `cookies` properties directly.
*/
/**
* Array Access: Offset Exists
*/
public function offsetExists($offset)
{
return isset($this->headers[$offset]);
}
/**
* Array Access: Offset Get
*/
public function offsetGet($offset)
{
return $this->headers[$offset];
}
/**
* Array Access: Offset Set
*/
public function offsetSet($offset, $value)
{
$this->headers[$offset] = $value;
}
/**
* Array Access: Offset Unset
*/
public function offsetUnset($offset)
{
unset($this->headers[$offset]);
}
/**
* DEPRECATION WARNING! Countable interface will be removed from \Slim\Http\Response.
* Call `count` on `headers` or `cookies` properties directly.
* *
* Countable: Count * Note: This method is not part of the PSR-7 standard.
*/
public function count()
{
return count($this->headers);
}
/**
* DEPRECATION WARNING! IteratorAggregate interface will be removed from \Slim\Http\Response.
* Iterate `headers` or `cookies` properties directly.
* *
* Get Iterator * @return string
*
* This returns the contained `\Slim\Http\Headers` instance which
* is itself iterable.
*
* @return \Slim\Http\Headers
*/ */
public function getIterator() public function __toString()
{ {
return $this->headers->getIterator(); $output = sprintf(
} 'HTTP/%s %s %s',
$this->getProtocolVersion(),
/** $this->getStatusCode(),
* Get message for HTTP status code $this->getReasonPhrase()
* @param int $status );
* @return string|null $output .= PHP_EOL;
*/ foreach ($this->getHeaders() as $name => $values) {
public static function getMessageForCode($status) $output .= sprintf('%s: %s', $name, $this->getHeaderLine($name)) . PHP_EOL;
{
if (isset(self::$messages[$status])) {
return self::$messages[$status];
} else {
return null;
} }
$output .= PHP_EOL;
$output .= (string)$this->getBody();
return $output;
} }
} }
+409
View File
@@ -0,0 +1,409 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Http;
use InvalidArgumentException;
use Psr\Http\Message\StreamInterface;
use RuntimeException;
/**
* Represents a data stream as defined in PSR-7.
*
* @link https://github.com/php-fig/http-message/blob/master/src/StreamInterface.php
*/
class Stream implements StreamInterface
{
/**
* Resource modes
*
* @var array
* @link http://php.net/manual/function.fopen.php
*/
protected static $modes = [
'readable' => ['r', 'r+', 'w+', 'a+', 'x+', 'c+'],
'writable' => ['r+', 'w', 'w+', 'a', 'a+', 'x', 'x+', 'c', 'c+'],
];
/**
* The underlying stream resource
*
* @var resource
*/
protected $stream;
/**
* Stream metadata
*
* @var array
*/
protected $meta;
/**
* Is this stream readable?
*
* @var bool
*/
protected $readable;
/**
* Is this stream writable?
*
* @var bool
*/
protected $writable;
/**
* Is this stream seekable?
*
* @var bool
*/
protected $seekable;
/**
* The size of the stream if known
*
* @var null|int
*/
protected $size;
/**
* Create a new Stream.
*
* @param resource $stream A PHP resource handle.
*
* @throws InvalidArgumentException If argument is not a resource.
*/
public function __construct($stream)
{
$this->attach($stream);
}
/**
* Get stream metadata as an associative array or retrieve a specific key.
*
* The keys returned are identical to the keys returned from PHP's
* stream_get_meta_data() function.
*
* @link http://php.net/manual/en/function.stream-get-meta-data.php
*
* @param string $key Specific metadata to retrieve.
*
* @return array|mixed|null Returns an associative array if no key is
* provided. Returns a specific key value if a key is provided and the
* value is found, or null if the key is not found.
*/
public function getMetadata($key = null)
{
$this->meta = stream_get_meta_data($this->stream);
if (is_null($key) === true) {
return $this->meta;
}
return isset($this->meta[$key]) ? $this->meta[$key] : null;
}
/**
* Is a resource attached to this stream?
*
* Note: This method is not part of the PSR-7 standard.
*
* @return bool
*/
protected function isAttached()
{
return is_resource($this->stream);
}
/**
* Attach new resource to this object.
*
* Note: This method is not part of the PSR-7 standard.
*
* @param resource $newStream A PHP resource handle.
*
* @throws InvalidArgumentException If argument is not a valid PHP resource.
*/
protected function attach($newStream)
{
if (is_resource($newStream) === false) {
throw new InvalidArgumentException(__METHOD__ . ' argument must be a valid PHP resource');
}
if ($this->isAttached() === true) {
$this->detach();
}
$this->stream = $newStream;
}
/**
* Separates any underlying resources from the stream.
*
* After the stream has been detached, the stream is in an unusable state.
*
* @return resource|null Underlying PHP stream, if any
*/
public function detach()
{
$oldResource = $this->stream;
$this->stream = null;
$this->meta = null;
$this->readable = null;
$this->writable = null;
$this->seekable = null;
$this->size = null;
return $oldResource;
}
/**
* Reads all data from the stream into a string, from the beginning to end.
*
* This method MUST attempt to seek to the beginning of the stream before
* reading data and read the stream until the end is reached.
*
* Warning: This could attempt to load a large amount of data into memory.
*
* This method MUST NOT raise an exception in order to conform with PHP's
* string casting operations.
*
* @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
* @return string
*/
public function __toString()
{
if (!$this->isAttached()) {
return '';
}
try {
$this->rewind();
return $this->getContents();
} catch (RuntimeException $e) {
return '';
}
}
/**
* Closes the stream and any underlying resources.
*/
public function close()
{
if ($this->isAttached() === true) {
fclose($this->stream);
}
$this->detach();
}
/**
* Get the size of the stream if known.
*
* @return int|null Returns the size in bytes if known, or null if unknown.
*/
public function getSize()
{
if (!$this->size && $this->isAttached() === true) {
$stats = fstat($this->stream);
$this->size = isset($stats['size']) ? $stats['size'] : null;
}
return $this->size;
}
/**
* Returns the current position of the file read/write pointer
*
* @return int Position of the file pointer
*
* @throws RuntimeException on error.
*/
public function tell()
{
if (!$this->isAttached() || ($position = ftell($this->stream)) === false) {
throw new RuntimeException('Could not get the position of the pointer in stream');
}
return $position;
}
/**
* Returns true if the stream is at the end of the stream.
*
* @return bool
*/
public function eof()
{
return $this->isAttached() ? feof($this->stream) : true;
}
/**
* Returns whether or not the stream is readable.
*
* @return bool
*/
public function isReadable()
{
if ($this->readable === null) {
$this->readable = false;
if ($this->isAttached()) {
$meta = $this->getMetadata();
foreach (self::$modes['readable'] as $mode) {
if (strpos($meta['mode'], $mode) === 0) {
$this->readable = true;
break;
}
}
}
}
return $this->readable;
}
/**
* Returns whether or not the stream is writable.
*
* @return bool
*/
public function isWritable()
{
if ($this->writable === null) {
$this->writable = false;
if ($this->isAttached()) {
$meta = $this->getMetadata();
foreach (self::$modes['writable'] as $mode) {
if (strpos($meta['mode'], $mode) === 0) {
$this->writable = true;
break;
}
}
}
}
return $this->writable;
}
/**
* Returns whether or not the stream is seekable.
*
* @return bool
*/
public function isSeekable()
{
if ($this->seekable === null) {
$this->seekable = false;
if ($this->isAttached()) {
$meta = $this->getMetadata();
$this->seekable = $meta['seekable'];
}
}
return $this->seekable;
}
/**
* Seek to a position in the stream.
*
* @link http://www.php.net/manual/en/function.fseek.php
*
* @param int $offset Stream offset
* @param int $whence Specifies how the cursor position will be calculated
* based on the seek offset. Valid values are identical to the built-in
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
* offset bytes SEEK_CUR: Set position to current location plus offset
* SEEK_END: Set position to end-of-stream plus offset.
*
* @throws RuntimeException on failure.
*/
public function seek($offset, $whence = SEEK_SET)
{
// Note that fseek returns 0 on success!
if (!$this->isSeekable() || fseek($this->stream, $offset, $whence) === -1) {
throw new RuntimeException('Could not seek in stream');
}
}
/**
* Seek to the beginning of the stream.
*
* If the stream is not seekable, this method will raise an exception;
* otherwise, it will perform a seek(0).
*
* @see seek()
*
* @link http://www.php.net/manual/en/function.fseek.php
*
* @throws RuntimeException on failure.
*/
public function rewind()
{
if (!$this->isSeekable() || rewind($this->stream) === false) {
throw new RuntimeException('Could not rewind stream');
}
}
/**
* Read data from the stream.
*
* @param int $length Read up to $length bytes from the object and return
* them. Fewer than $length bytes may be returned if underlying stream
* call returns fewer bytes.
*
* @return string Returns the data read from the stream, or an empty string
* if no bytes are available.
*
* @throws RuntimeException if an error occurs.
*/
public function read($length)
{
if (!$this->isReadable() || ($data = fread($this->stream, $length)) === false) {
throw new RuntimeException('Could not read from stream');
}
return $data;
}
/**
* Write data to the stream.
*
* @param string $string The string that is to be written.
*
* @return int Returns the number of bytes written to the stream.
*
* @throws RuntimeException on failure.
*/
public function write($string)
{
if (!$this->isWritable() || ($written = fwrite($this->stream, $string)) === false) {
throw new RuntimeException('Could not write to stream');
}
// reset size so that it will be recalculated on next call to getSize()
$this->size = null;
return $written;
}
/**
* Returns the remaining contents in a string
*
* @return string
*
* @throws RuntimeException if unable to read or an error occurs while
* reading.
*/
public function getContents()
{
if (!$this->isReadable() || ($contents = stream_get_contents($this->stream)) === false) {
throw new RuntimeException('Could not get contents of stream');
}
return $contents;
}
}
+317
View File
@@ -0,0 +1,317 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Http;
use RuntimeException;
use InvalidArgumentException;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UploadedFileInterface;
/**
* Represents Uploaded Files.
*
* It manages and normalizes uploaded files according to the PSR-7 standard.
*
* @link https://github.com/php-fig/http-message/blob/master/src/UploadedFileInterface.php
* @link https://github.com/php-fig/http-message/blob/master/src/StreamInterface.php
*/
class UploadedFile implements UploadedFileInterface
{
/**
* The client-provided file name.
*
* @var string
*/
protected $name;
/**
* The client-provided media type of the file.
*
* @var string
*/
protected $type;
/**
* The size of the file in bytes.
*
* @var int
*/
protected $size;
/**
* A valid PHP UPLOAD_ERR_xxx code for the file upload.
*
* @var int
*/
protected $error = UPLOAD_ERR_OK;
/**
* Indicates if the upload is from a SAPI environment.
*
* @var bool
*/
protected $sapi = false;
/**
* An optional StreamInterface wrapping the file resource.
*
* @var StreamInterface
*/
protected $stream;
/**
* Indicates if the uploaded file has already been moved.
*
* @var bool
*/
protected $moved = false;
/**
* Create a normalized tree of UploadedFile instances from the Environment.
*
* @param Environment $env The environment
*
* @return array|null A normalized tree of UploadedFile instances or null if none are provided.
*/
public static function createFromEnvironment(Environment $env)
{
if (is_array($env['slim.files']) && $env->has('slim.files')) {
return $env['slim.files'];
} elseif (isset($_FILES)) {
return static::parseUploadedFiles($_FILES);
}
return [];
}
/**
* Parse a non-normalized, i.e. $_FILES superglobal, tree of uploaded file data.
*
* @param array $uploadedFiles The non-normalized tree of uploaded file data.
*
* @return array A normalized tree of UploadedFile instances.
*/
private static function parseUploadedFiles(array $uploadedFiles)
{
$parsed = [];
foreach ($uploadedFiles as $field => $uploadedFile) {
if (!isset($uploadedFile['error'])) {
if (is_array($uploadedFile)) {
$parsed[$field] = static::parseUploadedFiles($uploadedFile);
}
continue;
}
$parsed[$field] = [];
if (!is_array($uploadedFile['error'])) {
$parsed[$field] = new static(
$uploadedFile['tmp_name'],
isset($uploadedFile['tmp_name']) ? $uploadedFile['name'] : null,
isset($uploadedFile['type']) ? $uploadedFile['type'] : null,
isset($uploadedFile['size']) ? $uploadedFile['size'] : null,
$uploadedFile['error'],
true
);
} else {
foreach ($uploadedFile['error'] as $fileIdx => $error) {
$parsed[$field][] = new static(
$uploadedFile['tmp_name'][$fileIdx],
isset($uploadedFile['tmp_name']) ? $uploadedFile['name'][$fileIdx] : null,
isset($uploadedFile['type']) ? $uploadedFile['type'][$fileIdx] : null,
isset($uploadedFile['size']) ? $uploadedFile['size'][$fileIdx] : null,
$uploadedFile['error'][$fileIdx],
true
);
}
}
}
return $parsed;
}
/**
* Construct a new UploadedFile instance.
*
* @param string $file The full path to the uploaded file provided by the client.
* @param string|null $name The file name.
* @param string|null $type The file media type.
* @param int|null $size The file size in bytes.
* @param int $error The UPLOAD_ERR_XXX code representing the status of the upload.
* @param bool $sapi Indicates if the upload is in a SAPI environment.
*/
public function __construct($file, $name = null, $type = null, $size = null, $error = UPLOAD_ERR_OK, $sapi = false)
{
$this->file = $file;
$this->name = $name;
$this->type = $type;
$this->size = $size;
$this->error = $error;
$this->sapi = $sapi;
}
/**
* Retrieve a stream representing the uploaded file.
*
* This method MUST return a StreamInterface instance, representing the
* uploaded file. The purpose of this method is to allow utilizing native PHP
* stream functionality to manipulate the file upload, such as
* stream_copy_to_stream() (though the result will need to be decorated in a
* native PHP stream wrapper to work with such functions).
*
* If the moveTo() method has been called previously, this method MUST raise
* an exception.
*
* @return StreamInterface Stream representation of the uploaded file.
* @throws \RuntimeException in cases when no stream is available or can be
* created.
*/
public function getStream()
{
if ($this->moved) {
throw new \RuntimeException(sprintf('Uploaded file %1s has already been moved', $this->name));
}
if ($this->stream === null) {
$this->stream = new Stream(fopen($this->file, 'r'));
}
return $this->stream;
}
/**
* Move the uploaded file to a new location.
*
* Use this method as an alternative to move_uploaded_file(). This method is
* guaranteed to work in both SAPI and non-SAPI environments.
* Implementations must determine which environment they are in, and use the
* appropriate method (move_uploaded_file(), rename(), or a stream
* operation) to perform the operation.
*
* $targetPath may be an absolute path, or a relative path. If it is a
* relative path, resolution should be the same as used by PHP's rename()
* function.
*
* The original file or stream MUST be removed on completion.
*
* If this method is called more than once, any subsequent calls MUST raise
* an exception.
*
* When used in an SAPI environment where $_FILES is populated, when writing
* files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
* used to ensure permissions and upload status are verified correctly.
*
* If you wish to move to a stream, use getStream(), as SAPI operations
* cannot guarantee writing to stream destinations.
*
* @see http://php.net/is_uploaded_file
* @see http://php.net/move_uploaded_file
*
* @param string $targetPath Path to which to move the uploaded file.
*
* @throws InvalidArgumentException if the $path specified is invalid.
* @throws RuntimeException on any error during the move operation, or on
* the second or subsequent call to the method.
*/
public function moveTo($targetPath)
{
if ($this->moved) {
throw new RuntimeException('Uploaded file already moved');
}
if (!is_writable(dirname($targetPath))) {
throw new InvalidArgumentException('Upload target path is not writable');
}
$targetIsStream = strpos($targetPath, '://') > 0;
if ($targetIsStream) {
if (!copy($this->file, $targetPath)) {
throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath));
}
if (!unlink($this->file)) {
throw new RuntimeException(sprintf('Error removing uploaded file %1s', $this->name));
}
} elseif ($this->sapi) {
if (!is_uploaded_file($this->file)) {
throw new RuntimeException(sprintf('%1s is not a valid uploaded file', $this->file));
}
if (!move_uploaded_file($this->file, $targetPath)) {
throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath));
}
} else {
if (!rename($this->file, $targetPath)) {
throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath));
}
}
$this->moved = true;
}
/**
* Retrieve the error associated with the uploaded file.
*
* The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
*
* If the file was uploaded successfully, this method MUST return
* UPLOAD_ERR_OK.
*
* Implementations SHOULD return the value stored in the "error" key of
* the file in the $_FILES array.
*
* @see http://php.net/manual/en/features.file-upload.errors.php
*
* @return int One of PHP's UPLOAD_ERR_XXX constants.
*/
public function getError()
{
return $this->error;
}
/**
* Retrieve the filename sent by the client.
*
* Do not trust the value returned by this method. A client could send
* a malicious filename with the intention to corrupt or hack your
* application.
*
* Implementations SHOULD return the value stored in the "name" key of
* the file in the $_FILES array.
*
* @return string|null The filename sent by the client or null if none
* was provided.
*/
public function getClientFilename()
{
return $this->name;
}
/**
* Retrieve the media type sent by the client.
*
* Do not trust the value returned by this method. A client could send
* a malicious media type with the intention to corrupt or hack your
* application.
*
* Implementations SHOULD return the value stored in the "type" key of
* the file in the $_FILES array.
*
* @return string|null The media type sent by the client or null if none
* was provided.
*/
public function getClientMediaType()
{
return $this->type;
}
/**
* Retrieve the file size.
*
* Implementations SHOULD return the value stored in the "size" key of
* the file in the $_FILES array if available, as PHP calculates this based
* on the actual size transmitted.
*
* @return int|null The file size in bytes or null if unknown.
*/
public function getSize()
{
return $this->size;
}
}
+809
View File
@@ -0,0 +1,809 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Http;
use InvalidArgumentException;
use \Psr\Http\Message\UriInterface;
use Slim\Http\Environment;
/**
* Value object representing a URI.
*
* This interface is meant to represent URIs according to RFC 3986 and to
* provide methods for most common operations. Additional functionality for
* working with URIs can be provided on top of the interface or externally.
* Its primary use is for HTTP requests, but may also be used in other
* contexts.
*
* Instances of this interface are considered immutable; all methods that
* might change state MUST be implemented such that they retain the internal
* state of the current instance and return an instance that contains the
* changed state.
*
* Typically the Host header will be also be present in the request message.
* For server-side requests, the scheme will typically be discoverable in the
* server parameters.
*
* @link http://tools.ietf.org/html/rfc3986 (the URI specification)
*/
class Uri implements UriInterface
{
/**
* Uri scheme (without "://" suffix)
*
* @var string
*/
protected $scheme = '';
/**
* Uri user
*
* @var string
*/
protected $user = '';
/**
* Uri password
*
* @var string
*/
protected $password = '';
/**
* Uri host
*
* @var string
*/
protected $host = '';
/**
* Uri port number
*
* @var null|int
*/
protected $port;
/**
* Uri base path
*
* @var string
*/
protected $basePath = '';
/**
* Uri path
*
* @var string
*/
protected $path = '';
/**
* Uri query string (without "?" prefix)
*
* @var string
*/
protected $query = '';
/**
* Uri fragment string (without "#" prefix)
*
* @var string
*/
protected $fragment = '';
/**
* Create new Uri.
*
* @param string $scheme Uri scheme.
* @param string $host Uri host.
* @param int $port Uri port number.
* @param string $path Uri path.
* @param string $query Uri query string.
* @param string $fragment Uri fragment.
* @param string $user Uri user.
* @param string $password Uri password.
*/
public function __construct($scheme, $host, $port = null, $path = '/', $query = '', $fragment = '', $user = '', $password = '')
{
$this->scheme = $this->filterScheme($scheme);
$this->host = $host;
$this->port = $this->filterPort($port);
$this->path = empty($path) ? '/' : $this->filterPath($path);
$this->query = $this->filterQuery($query);
$this->fragment = $this->filterQuery($fragment);
$this->user = $user;
$this->password = $password;
}
/**
* Create new Uri from string.
*
* @param string $uri Complete Uri string
* (i.e., https://user:pass@host:443/path?query).
*
* @return self
*/
public static function createFromString($uri)
{
if (!is_string($uri) && !method_exists($uri, '__toString')) {
throw new InvalidArgumentException('Uri must be a string');
}
$parts = parse_url($uri);
$scheme = isset($parts['scheme']) ? $parts['scheme'] : '';
$user = isset($parts['user']) ? $parts['user'] : '';
$pass = isset($parts['pass']) ? $parts['pass'] : '';
$host = isset($parts['host']) ? $parts['host'] : '';
$port = isset($parts['port']) ? $parts['port'] : null;
$path = isset($parts['path']) ? $parts['path'] : '';
$query = isset($parts['query']) ? $parts['query'] : '';
$fragment = isset($parts['fragment']) ? $parts['fragment'] : '';
return new static($scheme, $host, $port, $path, $query, $fragment, $user, $pass);
}
/**
* Create new Uri from environment.
*
* @param Environment $env
*
* @return self
*/
public static function createFromEnvironment(Environment $env)
{
// Scheme
$isSecure = $env->get('HTTPS');
$scheme = (empty($isSecure) || $isSecure === 'off') ? 'http' : 'https';
// Authority: Username and password
$username = $env->get('PHP_AUTH_USER', '');
$password = $env->get('PHP_AUTH_PW', '');
// Authority: Host
if ($env->has('HTTP_HOST')) {
$host = $env->get('HTTP_HOST');
} else {
$host = $env->get('SERVER_NAME');
}
// Authority: Port
$port = (int)$env->get('SERVER_PORT', 80);
if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) {
$host = $matches[1];
if ($matches[2]) {
$port = (int) substr($matches[2], 1);
}
} else {
$pos = strpos($host, ':');
if ($pos !== false) {
$port = (int) substr($host, $pos + 1);
$host = strstr($host, ':', true);
}
}
// Path
$requestScriptName = parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH);
$requestScriptDir = dirname($requestScriptName);
$requestUri = parse_url($env->get('REQUEST_URI'), PHP_URL_PATH);
$basePath = '';
$virtualPath = $requestUri;
if (stripos($requestUri, $requestScriptName) === 0) {
$basePath = $requestScriptName;
} elseif ($requestScriptDir !== '/' && stripos($requestUri, $requestScriptDir) === 0) {
$basePath = $requestScriptDir;
}
if ($basePath) {
$virtualPath = ltrim(substr($requestUri, strlen($basePath)), '/');
}
// Query string
$queryString = $env->get('QUERY_STRING', '');
// Fragment
$fragment = '';
// Build Uri
$uri = new static($scheme, $host, $port, $virtualPath, $queryString, $fragment, $username, $password);
if ($basePath) {
$uri = $uri->withBasePath($basePath);
}
return $uri;
}
/********************************************************************************
* Scheme
*******************************************************************************/
/**
* Retrieve the scheme component of the URI.
*
* If no scheme is present, this method MUST return an empty string.
*
* The value returned MUST be normalized to lowercase, per RFC 3986
* Section 3.1.
*
* The trailing ":" character is not part of the scheme and MUST NOT be
* added.
*
* @see https://tools.ietf.org/html/rfc3986#section-3.1
* @return string The URI scheme.
*/
public function getScheme()
{
return $this->scheme;
}
/**
* Return an instance with the specified scheme.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified scheme.
*
* Implementations MUST support the schemes "http" and "https" case
* insensitively, and MAY accommodate other schemes if required.
*
* An empty scheme is equivalent to removing the scheme.
*
* @param string $scheme The scheme to use with the new instance.
* @return self A new instance with the specified scheme.
* @throws \InvalidArgumentException for invalid or unsupported schemes.
*/
public function withScheme($scheme)
{
$scheme = $this->filterScheme($scheme);
$clone = clone $this;
$clone->scheme = $scheme;
return $clone;
}
/**
* Filter Uri scheme.
*
* @param string $scheme Raw Uri scheme.
* @return string
*
* @throws InvalidArgumentException If the Uri scheme is not a string.
* @throws InvalidArgumentException If Uri scheme is not "", "https", or "http".
*/
protected function filterScheme($scheme)
{
static $valid = [
'' => true,
'https' => true,
'http' => true,
];
if (!is_string($scheme) && !method_exists($scheme, '__toString')) {
throw new InvalidArgumentException('Uri scheme must be a string');
}
$scheme = str_replace('://', '', strtolower((string)$scheme));
if (!isset($valid[$scheme])) {
throw new InvalidArgumentException('Uri scheme must be one of: "", "https", "http"');
}
return $scheme;
}
/********************************************************************************
* Authority
*******************************************************************************/
/**
* Retrieve the authority component of the URI.
*
* If no authority information is present, this method MUST return an empty
* string.
*
* The authority syntax of the URI is:
*
* <pre>
* [user-info@]host[:port]
* </pre>
*
* If the port component is not set or is the standard port for the current
* scheme, it SHOULD NOT be included.
*
* @see https://tools.ietf.org/html/rfc3986#section-3.2
* @return string The URI authority, in "[user-info@]host[:port]" format.
*/
public function getAuthority()
{
$userInfo = $this->getUserInfo();
$host = $this->getHost();
$port = $this->getPort();
return ($userInfo ? $userInfo . '@' : '') . $host . ($port !== null ? ':' . $port : '');
}
/**
* Retrieve the user information component of the URI.
*
* If no user information is present, this method MUST return an empty
* string.
*
* If a user is present in the URI, this will return that value;
* additionally, if the password is also present, it will be appended to the
* user value, with a colon (":") separating the values.
*
* The trailing "@" character is not part of the user information and MUST
* NOT be added.
*
* @return string The URI user information, in "username[:password]" format.
*/
public function getUserInfo()
{
return $this->user . ($this->password ? ':' . $this->password : '');
}
/**
* Return an instance with the specified user information.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified user information.
*
* Password is optional, but the user information MUST include the
* user; an empty string for the user is equivalent to removing user
* information.
*
* @param string $user The user name to use for authority.
* @param null|string $password The password associated with $user.
* @return self A new instance with the specified user information.
*/
public function withUserInfo($user, $password = null)
{
$clone = clone $this;
$clone->user = $user;
$clone->password = $password ? $password : '';
return $clone;
}
/**
* Retrieve the host component of the URI.
*
* If no host is present, this method MUST return an empty string.
*
* The value returned MUST be normalized to lowercase, per RFC 3986
* Section 3.2.2.
*
* @see http://tools.ietf.org/html/rfc3986#section-3.2.2
* @return string The URI host.
*/
public function getHost()
{
return $this->host;
}
/**
* Return an instance with the specified host.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified host.
*
* An empty host value is equivalent to removing the host.
*
* @param string $host The hostname to use with the new instance.
* @return self A new instance with the specified host.
* @throws \InvalidArgumentException for invalid hostnames.
*/
public function withHost($host)
{
$clone = clone $this;
$clone->host = $host;
return $clone;
}
/**
* Retrieve the port component of the URI.
*
* If a port is present, and it is non-standard for the current scheme,
* this method MUST return it as an integer. If the port is the standard port
* used with the current scheme, this method SHOULD return null.
*
* If no port is present, and no scheme is present, this method MUST return
* a null value.
*
* If no port is present, but a scheme is present, this method MAY return
* the standard port for that scheme, but SHOULD return null.
*
* @return null|int The URI port.
*/
public function getPort()
{
return $this->port && !$this->hasStandardPort() ? $this->port : null;
}
/**
* Return an instance with the specified port.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified port.
*
* Implementations MUST raise an exception for ports outside the
* established TCP and UDP port ranges.
*
* A null value provided for the port is equivalent to removing the port
* information.
*
* @param null|int $port The port to use with the new instance; a null value
* removes the port information.
* @return self A new instance with the specified port.
* @throws \InvalidArgumentException for invalid ports.
*/
public function withPort($port)
{
$port = $this->filterPort($port);
$clone = clone $this;
$clone->port = $port;
return $clone;
}
/**
* Does this Uri use a standard port?
*
* @return bool
*/
protected function hasStandardPort()
{
return ($this->scheme === 'http' && $this->port === 80) || ($this->scheme === 'https' && $this->port === 443);
}
/**
* Filter Uri port.
*
* @param null|int $port The Uri port number.
* @return null|int
*
* @throws InvalidArgumentException If the port is invalid.
*/
protected function filterPort($port)
{
if (is_null($port) || (is_integer($port) && ($port >= 1 && $port <= 65535))) {
return $port;
}
throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)');
}
/********************************************************************************
* Path
*******************************************************************************/
/**
* Retrieve the path component of the URI.
*
* The path can either be empty or absolute (starting with a slash) or
* rootless (not starting with a slash). Implementations MUST support all
* three syntaxes.
*
* Normally, the empty path "" and absolute path "/" are considered equal as
* defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
* do this normalization because in contexts with a trimmed base path, e.g.
* the front controller, this difference becomes significant. It's the task
* of the user to handle both "" and "/".
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.3.
*
* As an example, if the value should include a slash ("/") not intended as
* delimiter between path segments, that value MUST be passed in encoded
* form (e.g., "%2F") to the instance.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.3
* @return string The URI path.
*/
public function getPath()
{
return $this->path;
}
/**
* Return an instance with the specified path.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified path.
*
* The path can either be empty or absolute (starting with a slash) or
* rootless (not starting with a slash). Implementations MUST support all
* three syntaxes.
*
* If the path is intended to be domain-relative rather than path relative then
* it must begin with a slash ("/"). Paths not starting with a slash ("/")
* are assumed to be relative to some base path known to the application or
* consumer.
*
* Users can provide both encoded and decoded path characters.
* Implementations ensure the correct encoding as outlined in getPath().
*
* @param string $path The path to use with the new instance.
* @return self A new instance with the specified path.
* @throws \InvalidArgumentException for invalid paths.
*/
public function withPath($path)
{
if (!is_string($path)) {
throw new InvalidArgumentException('Uri path must be a string');
}
$clone = clone $this;
$clone->path = $this->filterPath($path);
// if the path is absolute, then clear basePath
if (substr($path, 0, 1) == '/') {
$clone->basePath = '';
}
return $clone;
}
/**
* Retrieve the base path segment of the URI.
*
* Note: This method is not part of the PSR-7 standard.
*
* This method MUST return a string; if no path is present it MUST return
* an empty string.
*
* @return string The base path segment of the URI.
*/
public function getBasePath()
{
return $this->basePath;
}
/**
* Set base path.
*
* Note: This method is not part of the PSR-7 standard.
*
* @param string $basePath
* @return self
*/
public function withBasePath($basePath)
{
if (!is_string($basePath)) {
throw new InvalidArgumentException('Uri path must be a string');
}
if (!empty($basePath)) {
$basePath = '/' . trim($basePath, '/'); // <-- Trim on both sides
}
$clone = clone $this;
if ($basePath !== '/') {
$clone->basePath = $this->filterPath($basePath);
}
return $clone;
}
/**
* Filter Uri path.
*
* This method percent-encodes all reserved
* characters in the provided path string. This method
* will NOT double-encode characters that are already
* percent-encoded.
*
* @param string $path The raw uri path.
* @return string The RFC 3986 percent-encoded uri path.
* @link http://www.faqs.org/rfcs/rfc3986.html
*/
protected function filterPath($path)
{
return preg_replace_callback(
'/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/',
function ($match) {
return rawurlencode($match[0]);
},
$path
);
}
/********************************************************************************
* Query
*******************************************************************************/
/**
* Retrieve the query string of the URI.
*
* If no query string is present, this method MUST return an empty string.
*
* The leading "?" character is not part of the query and MUST NOT be
* added.
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.4.
*
* As an example, if a value in a key/value pair of the query string should
* include an ampersand ("&") not intended as a delimiter between values,
* that value MUST be passed in encoded form (e.g., "%26") to the instance.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.4
* @return string The URI query string.
*/
public function getQuery()
{
return $this->query;
}
/**
* Return an instance with the specified query string.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified query string.
*
* Users can provide both encoded and decoded query characters.
* Implementations ensure the correct encoding as outlined in getQuery().
*
* An empty query string value is equivalent to removing the query string.
*
* @param string $query The query string to use with the new instance.
* @return self A new instance with the specified query string.
* @throws \InvalidArgumentException for invalid query strings.
*/
public function withQuery($query)
{
if (!is_string($query) && !method_exists($query, '__toString')) {
throw new InvalidArgumentException('Uri query must be a string');
}
$query = ltrim((string)$query, '?');
$clone = clone $this;
$clone->query = $this->filterQuery($query);
return $clone;
}
/**
* Filters the query string or fragment of a URI.
*
* @param string $query The raw uri query string.
* @return string The percent-encoded query string.
*/
protected function filterQuery($query)
{
return preg_replace_callback(
'/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/',
function ($match) {
return rawurlencode($match[0]);
},
$query
);
}
/********************************************************************************
* Fragment
*******************************************************************************/
/**
* Retrieve the fragment component of the URI.
*
* If no fragment is present, this method MUST return an empty string.
*
* The leading "#" character is not part of the fragment and MUST NOT be
* added.
*
* The value returned MUST be percent-encoded, but MUST NOT double-encode
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.5.
*
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see https://tools.ietf.org/html/rfc3986#section-3.5
* @return string The URI fragment.
*/
public function getFragment()
{
return $this->fragment;
}
/**
* Return an instance with the specified URI fragment.
*
* This method MUST retain the state of the current instance, and return
* an instance that contains the specified URI fragment.
*
* Users can provide both encoded and decoded fragment characters.
* Implementations ensure the correct encoding as outlined in getFragment().
*
* An empty fragment value is equivalent to removing the fragment.
*
* @param string $fragment The fragment to use with the new instance.
* @return self A new instance with the specified fragment.
*/
public function withFragment($fragment)
{
if (!is_string($fragment) && !method_exists($fragment, '__toString')) {
throw new InvalidArgumentException('Uri fragment must be a string');
}
$fragment = ltrim((string)$fragment, '#');
$clone = clone $this;
$clone->fragment = $this->filterQuery($fragment);
return $clone;
}
/********************************************************************************
* Helpers
*******************************************************************************/
/**
* Return the string representation as a URI reference.
*
* Depending on which components of the URI are present, the resulting
* string is either a full URI or relative reference according to RFC 3986,
* Section 4.1. The method concatenates the various components of the URI,
* using the appropriate delimiters:
*
* - If a scheme is present, it MUST be suffixed by ":".
* - If an authority is present, it MUST be prefixed by "//".
* - The path can be concatenated without delimiters. But there are two
* cases where the path has to be adjusted to make the URI reference
* valid as PHP does not allow to throw an exception in __toString():
* - If the path is rootless and an authority is present, the path MUST
* be prefixed by "/".
* - If the path is starting with more than one "/" and no authority is
* present, the starting slashes MUST be reduced to one.
* - If a query is present, it MUST be prefixed by "?".
* - If a fragment is present, it MUST be prefixed by "#".
*
* @see http://tools.ietf.org/html/rfc3986#section-4.1
* @return string
*/
public function __toString()
{
$scheme = $this->getScheme();
$authority = $this->getAuthority();
$basePath = $this->getBasePath();
$path = $this->getPath();
$query = $this->getQuery();
$fragment = $this->getFragment();
$path = $basePath . '/' . ltrim($path, '/');
return ($scheme ? $scheme . ':' : '')
. ($authority ? '//' . $authority : '')
. $path
. ($query ? '?' . $query : '')
. ($fragment ? '#' . $fragment : '');
}
/**
* Return the fully qualified base URL.
*
* Note that this method never includes a trailing /
*
* This method is not part of PSR-7.
*
* @return string
*/
public function getBaseUrl()
{
$scheme = $this->getScheme();
$authority = $this->getAuthority();
$basePath = $this->getBasePath();
if ($authority && substr($basePath, 0, 1) !== '/') {
$basePath = $basePath . '/' . $basePath;
}
return ($scheme ? $scheme . ':' : '')
. ($authority ? '//' . $authority : '')
. rtrim($basePath, '/');
}
}
+3 -3
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -60,9 +60,9 @@ class Util
$strip = is_null($overrideStripSlashes) ? get_magic_quotes_gpc() : $overrideStripSlashes; $strip = is_null($overrideStripSlashes) ? get_magic_quotes_gpc() : $overrideStripSlashes;
if ($strip) { if ($strip) {
return self::stripSlashes($rawData); return self::stripSlashes($rawData);
} else {
return $rawData;
} }
return $rawData;
} }
/** /**
@@ -0,0 +1,27 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces;
/**
* Resolves a callable.
*
* @package Slim
* @since 3.0.0
*/
interface CallableResolverInterface
{
/**
* Invoke the resolved callable.
*
* @param mixed $toResolve
*
* @return callable
*/
public function resolve($toResolve);
}
+32
View File
@@ -0,0 +1,32 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces;
/**
* Collection Interface
*
* @package Slim
* @since 3.0.0
*/
interface CollectionInterface extends \ArrayAccess, \Countable, \IteratorAggregate
{
public function set($key, $value);
public function get($key, $default = null);
public function replace(array $items);
public function all();
public function has($key);
public function remove($key);
public function clear();
}
+23
View File
@@ -0,0 +1,23 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces\Http;
/**
* Cookies Interface
*
* @package Slim
* @since 3.0.0
*/
interface CookiesInterface
{
public function get($name, $default = null);
public function set($name, $value);
public function toHeaders();
public static function parseHeader($header);
}
@@ -0,0 +1,20 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces\Http;
/**
* Environment Interface
*
* @package Slim
* @since 3.0.0
*/
interface EnvironmentInterface
{
public static function mock(array $settings = []);
}
+24
View File
@@ -0,0 +1,24 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces\Http;
use Slim\Interfaces\CollectionInterface;
/**
* Headers Interface
*
* @package Slim
* @since 3.0.0
*/
interface HeadersInterface extends CollectionInterface
{
public function add($key, $value);
public function normalizeKey($key);
}
@@ -0,0 +1,30 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Defines a contract for invoking a route callable.
*/
interface InvocationStrategyInterface
{
/**
* Invoke a route callable.
*
* @param callable $callable The callable to invoke using the strategy.
* @param ServerRequestInterface $request The request object.
* @param ResponseInterface $response The response object.
* @param array $routeArguments The route's placholder arguments
*
* @return ResponseInterface|string The response from the callable.
*/
public function __invoke(callable $callable, ServerRequestInterface $request, ResponseInterface $response, array $routeArguments);
}
+46
View File
@@ -0,0 +1,46 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces;
use Slim\App;
/**
* RouteGroup Interface
*
* @package Slim
* @since 3.0.0
*/
interface RouteGroupInterface
{
/**
* Get route pattern
*
* @return string
*/
public function getPattern();
/**
* Prepend middleware to the group middleware collection
*
* @param mixed $callable The callback routine
*
* @return RouteGroupInterface
*/
public function add($callable);
/**
* Execute route group callable in the context of the Slim App
*
* This method invokes the route group object's callable, collecting
* nested route objects
*
* @param App $app
*/
public function __invoke(App $app);
}
+129
View File
@@ -0,0 +1,129 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Route Interface
*
* @package Slim
* @since 3.0.0
*/
interface RouteInterface
{
/**
* Retrieve a specific route argument
*
* @param string $name
* @param mixed $default
*
* @return mixed
*/
public function getArgument($name, $default = null);
/**
* Get route arguments
*
* @return array
*/
public function getArguments();
/**
* Get route name
*
* @return null|string
*/
public function getName();
/**
* Get route pattern
*
* @return string
*/
public function getPattern();
/**
* Set a route argument
*
* @param string $name
* @param string $value
*
* @return static
*/
public function setArgument($name, $value);
/**
* Replace route arguments
*
* @param array $arguments
*
* @return static
*/
public function setArguments(array $arguments);
/**
* Set route name
*
* @param string $name
*
* @return static
* @throws InvalidArgumentException if the route name is not a string
*/
public function setName($name);
/**
* Add middleware
*
* This method prepends new middleware to the route's middleware stack.
*
* @param mixed $callable The callback routine
*
* @return RouteInterface
*/
public function add($callable);
/**
* Prepare the route for use
*
* @param ServerRequestInterface $request
* @param array $arguments
*/
public function prepare(ServerRequestInterface $request, array $arguments);
/**
* Run route
*
* This method traverses the middleware stack, including the route's callable
* and captures the resultant HTTP response object. It then sends the response
* back to the Application.
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @return ResponseInterface
*/
public function run(ServerRequestInterface $request, ResponseInterface $response);
/**
* Dispatch route callable against current Request and Response objects
*
* This method invokes the route object's callable. If middleware is
* registered for the route, each callable middleware is invoked in
* the order specified.
*
* @param ServerRequestInterface $request The current Request object
* @param ResponseInterface $response The current Response object
*
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response);
}
+107
View File
@@ -0,0 +1,107 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Interfaces;
use RuntimeException;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
/**
* Router Interface
*
* @package Slim
* @since 3.0.0
*/
interface RouterInterface
{
/**
* Add route
*
* @param string[] $methods Array of HTTP methods
* @param string $pattern The route pattern
* @param callable $handler The route callable
*
* @return RouteInterface
*/
public function map($methods, $pattern, $handler);
/**
* Dispatch router for HTTP request
*
* @param ServerRequestInterface $request The current HTTP request object
*
* @return array
*
* @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php
*/
public function dispatch(ServerRequestInterface $request);
/**
* Add a route group to the array
*
* @param string $pattern The group pattern
* @param callable $callable A group callable
*
* @return RouteGroupInterface
*/
public function pushGroup($pattern, $callable);
/**
* Removes the last route group from the array
*
* @return bool True if successful, else False
*/
public function popGroup();
/**
* Get named route object
*
* @param string $name Route name
*
* @return \Slim\Interfaces\RouteInterface
*
* @throws RuntimeException If named route does not exist
*/
public function getNamedRoute($name);
/**
* @param $identifier
*
* @return \Slim\Interfaces\RouteInterface
*/
public function lookupRoute($identifier);
/**
* Build the path for a named route excluding the base path
*
* @param string $name Route name
* @param array $data Named argument replacement data
* @param array $queryParams Optional query string parameters
*
* @return string
*
* @throws RuntimeException If named route does not exist
* @throws InvalidArgumentException If required data not provided
*/
public function relativePathFor($name, array $data = [], array $queryParams = []);
/**
* Build the path for a named route including the base path
*
* @param string $name Route name
* @param array $data Named argument replacement data
* @param array $queryParams Optional query string parameters
*
* @return string
*
* @throws RuntimeException If named route does not exist
* @throws InvalidArgumentException If required data not provided
*/
public function pathFor($name, array $data = [], array $queryParams = []);
}
+2 -7
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -306,12 +306,7 @@ class Log
if (!isset(self::$levels[$level])) { if (!isset(self::$levels[$level])) {
throw new \InvalidArgumentException('Invalid log level supplied to function'); throw new \InvalidArgumentException('Invalid log level supplied to function');
} else if ($this->enabled && $this->writer && $level <= $this->level) { } else if ($this->enabled && $this->writer && $level <= $this->level) {
if (is_array($object) || (is_object($object) && !method_exists($object, "__toString"))) { $message = (string)$object;
$message = print_r($object, true);
} else {
$message = (string) $object;
}
if (count($context) > 0) { if (count($context) > 0) {
if (isset($context['exception']) && $context['exception'] instanceof \Exception) { if (isset($context['exception']) && $context['exception'] instanceof \Exception) {
$message .= ' - ' . $context['exception']; $message .= ' - ' . $context['exception'];
+1 -1
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
+1 -1
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
+2 -2
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -116,7 +116,7 @@ class ContentTypes extends \Slim\Middleware
{ {
if (function_exists('json_decode')) { if (function_exists('json_decode')) {
$result = json_decode($input, true); $result = json_decode($input, true);
if(json_last_error() === JSON_ERROR_NONE) { if ($result) {
return $result; return $result;
} }
} }
+1 -1
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
+1 -1
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
+2 -2
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -89,7 +89,7 @@ class PrettyExceptions extends \Slim\Middleware
$message = $exception->getMessage(); $message = $exception->getMessage();
$file = $exception->getFile(); $file = $exception->getFile();
$line = $exception->getLine(); $line = $exception->getLine();
$trace = str_replace(array('#', "\n"), array('<div>#', '</div>'), $exception->getTraceAsString()); $trace = str_replace(array('#', '\n'), array('<div>#', '</div>'), $exception->getTraceAsString());
$html = sprintf('<h1>%s</h1>', $title); $html = sprintf('<h1>%s</h1>', $title);
$html .= '<p>The application could not run because of the following error:</p>'; $html .= '<p>The application could not run because of the following error:</p>';
$html .= '<h2>Details</h2>'; $html .= '<h2>Details</h2>';
+9 -4
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -119,10 +119,15 @@ class SessionCookie extends \Slim\Middleware
if (session_id() === '') { if (session_id() === '') {
session_start(); session_start();
} }
$value = $this->app->getCookie($this->settings['name']); $value = $this->app->getCookie($this->settings['name']);
if ($value) { if ($value) {
$value = json_decode($value, true); try {
$_SESSION = is_array($value) ? $value : array(); $_SESSION = unserialize($value);
} catch (\Exception $e) {
$this->app->getLog()->error('Error unserializing session cookie value! ' . $e->getMessage());
}
} else { } else {
$_SESSION = array(); $_SESSION = array();
} }
@@ -133,7 +138,7 @@ class SessionCookie extends \Slim\Middleware
*/ */
protected function saveSession() protected function saveSession()
{ {
$value = json_encode($_SESSION); $value = serialize($_SESSION);
if (strlen($value) > 4096) { if (strlen($value) > 4096) {
$this->app->getLog()->error('WARNING! Slim\Middleware\SessionCookie data size is larger than 4KB. Content save failed.'); $this->app->getLog()->error('WARNING! Slim\Middleware\SessionCookie data size is larger than 4KB. Content save failed.');
+118
View File
@@ -0,0 +1,118 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use RuntimeException;
use SplStack;
use SplDoublyLinkedList;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use UnexpectedValueException;
/**
* Middleware
*
* This is an internal class that enables concentric middleware layers. This
* class is an implementation detail and is used only inside of the Slim
* application; it is not visible to—and should not be used by—end users.
*/
trait MiddlewareAwareTrait
{
/**
* Middleware call stack
*
* @var \SplStack
* @link http://php.net/manual/class.splstack.php
*/
protected $stack;
/**
* Middleware stack lock
*
* @var bool
*/
protected $middlewareLock = false;
/**
* Add middleware
*
* This method prepends new middleware to the application middleware stack.
*
* @param callable $callable Any callable that accepts three arguments:
* 1. A Request object
* 2. A Response object
* 3. A "next" middleware callable
* @return static
*
* @throws RuntimeException If middleware is added while the stack is dequeuing
* @throws UnexpectedValueException If the middleware doesn't return an instance of \Psr\Http\Message\ResponseInterface
*/
protected function addMiddleware(callable $callable)
{
if ($this->middlewareLock) {
throw new RuntimeException('Middleware cant be added once the stack is dequeuing');
}
if (is_null($this->stack)) {
$this->seedMiddlewareStack();
}
$next = $this->stack->top();
$this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) {
$result = call_user_func($callable, $req, $res, $next);
if ($result instanceof ResponseInterface === false) {
throw new UnexpectedValueException('Middleware must return instance of \Psr\Http\Message\ResponseInterface');
}
return $result;
};
return $this;
}
/**
* Seed middleware stack with first callable
*
* @param callable $kernel The last item to run as middleware
*
* @throws RuntimeException if the stack is seeded more than once
*/
protected function seedMiddlewareStack(callable $kernel = null)
{
if (!is_null($this->stack)) {
throw new RuntimeException('MiddlewareStack can only be seeded once.');
}
if ($kernel === null) {
$kernel = $this;
}
$this->stack = new SplStack;
$this->stack->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO | SplDoublyLinkedList::IT_MODE_KEEP);
$this->stack[] = $kernel;
}
/**
* Call middleware stack
*
* @param ServerRequestInterface $req A request object
* @param ResponseInterface $res A response object
*
* @return ResponseInterface
*/
public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res)
{
if (is_null($this->stack)) {
$this->seedMiddlewareStack();
}
/** @var callable $start */
$start = $this->stack->top();
$this->middlewareLock = true;
$resp = $start($req, $res);
$this->middlewareLock = false;
return $resp;
}
}
+102
View File
@@ -0,0 +1,102 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use Closure;
use Interop\Container\ContainerInterface;
/**
* A routable, middleware-aware object
*
* @package Slim
* @since 3.0.0
*/
abstract class Routable
{
use CallableResolverAwareTrait;
/**
* Route callable
*
* @var callable
*/
protected $callable;
/**
* Container
*
* @var ContainerInterface
*/
protected $container;
/**
* Route middleware
*
* @var callable[]
*/
protected $middleware = [];
/**
* Route pattern
*
* @var string
*/
protected $pattern;
/**
* Get the middleware registered for the group
*
* @return callable[]
*/
public function getMiddleware()
{
return $this->middleware;
}
/**
* Get the route pattern
*
* @return string
*/
public function getPattern()
{
return $this->pattern;
}
/**
* Set container for use with resolveCallable
*
* @param ContainerInterface $container
*
* @return self
*/
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
return $this;
}
/**
* Prepend middleware to the middleware collection
*
* @param mixed $callable The callback routine
*
* @return static
*/
public function add($callable)
{
$callable = $this->resolveCallable($callable);
if ($callable instanceof Closure) {
$callable = $callable->bindTo($this->container);
}
$this->middleware[] = $callable;
return $this;
}
}
+246 -360
View File
@@ -1,153 +1,119 @@
<?php <?php
/** /**
* Slim - a micro PHP 5 framework * Slim Framework (http://slimframework.com)
* *
* @author Josh Lockhart <[email protected]> * @link https://github.com/slimphp/Slim
* @copyright 2011 Josh Lockhart * @copyright Copyright (c) 2011-2015 Josh Lockhart
* @link http://www.slimframework.com * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
* @license http://www.slimframework.com/license
* @version 2.6.1
* @package Slim
*
* MIT LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
namespace Slim; namespace Slim;
use Exception;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Handlers\Strategies\RequestResponse;
use Slim\Interfaces\InvocationStrategyInterface;
use Slim\Interfaces\RouteInterface;
/** /**
* Route * Route
* @package Slim
* @author Josh Lockhart, Thomas Bley
* @since 1.0.0
*/ */
class Route class Route extends Routable implements RouteInterface
{ {
/** use MiddlewareAwareTrait;
* @var string The route pattern (e.g. "/books/:id")
*/
protected $pattern;
/** /**
* @var mixed The route callable * HTTP methods supported by this route
*
* @var string[]
*/ */
protected $callable; protected $methods = [];
/** /**
* @var array Conditions for this route's URL parameters * Route identifier
*
* @var string
*/ */
protected $conditions = array(); protected $identifier;
/** /**
* @var array Default conditions applied to all route instances * Route name
*/ *
protected static $defaultConditions = array(); * @var null|string
/**
* @var string The name of this route (optional)
*/ */
protected $name; protected $name;
/** /**
* @var array Key-value array of URL parameters * Parent route groups
*
* @var RouteGroup[]
*/ */
protected $params = array(); protected $groups;
private $finalized = false;
/** /**
* @var array value array of URL parameter names * Output buffering mode
*
* One of: false, 'prepend' or 'append'
*
* @var boolean|string
*/ */
protected $paramNames = array(); protected $outputBuffering = 'append';
/** /**
* @var array key array of URL parameter names with + at the end * Route parameters
*
* @var array
*/ */
protected $paramNamesPath = array(); protected $arguments = [];
/** /**
* @var array HTTP methods supported by this Route * Create new route
*
* @param string[] $methods The route HTTP methods
* @param string $pattern The route pattern
* @param callable $callable The route callable
* @param int $identifier The route identifier
* @param RouteGroup[] $groups The parent route groups
*/ */
protected $methods = array(); public function __construct($methods, $pattern, $callable, $groups = [], $identifier = 0)
/**
* @var array[Callable] Middleware to be run before only this route instance
*/
protected $middleware = array();
/**
* @var bool Whether or not this route should be matched in a case-sensitive manner
*/
protected $caseSensitive;
/**
* Constructor
* @param string $pattern The URL pattern (e.g. "/books/:id")
* @param mixed $callable Anything that returns TRUE for is_callable()
* @param bool $caseSensitive Whether or not this route should be matched in a case-sensitive manner
*/
public function __construct($pattern, $callable, $caseSensitive = true)
{ {
$this->setPattern($pattern); $this->methods = $methods;
$this->setCallable($callable); $this->pattern = $pattern;
$this->setConditions(self::getDefaultConditions()); $this->callable = $callable;
$this->caseSensitive = $caseSensitive; $this->groups = $groups;
$this->identifier = 'route' . $identifier;
} }
/** /**
* Set default route conditions for all instances * Finalize the route in preparation for dispatching
* @param array $defaultConditions
*/ */
public static function setDefaultConditions(array $defaultConditions) public function finalize()
{ {
self::$defaultConditions = $defaultConditions; if ($this->finalized) {
} return;
}
/** $groupMiddleware = [];
* Get default route conditions for all instances foreach ($this->getGroups() as $group) {
* @return array $groupMiddleware = array_merge($group->getMiddleware(), $groupMiddleware);
*/ }
public static function getDefaultConditions()
{
return self::$defaultConditions;
}
/** $this->middleware = array_merge($this->middleware, $groupMiddleware);
* Get route pattern
* @return string
*/
public function getPattern()
{
return $this->pattern;
}
/** foreach ($this->getMiddleware() as $middleware) {
* Set route pattern $this->addMiddleware($middleware);
* @param string $pattern }
*/
public function setPattern($pattern) $this->finalized = true;
{
$this->pattern = $pattern;
} }
/** /**
* Get route callable * Get route callable
* @return mixed *
* @return callable
*/ */
public function getCallable() public function getCallable()
{ {
@@ -155,317 +121,237 @@ class Route
} }
/** /**
* Set route callable * Get route methods
* @param mixed $callable *
* @throws \InvalidArgumentException If argument is not callable * @return string[]
*/ */
public function setCallable($callable) public function getMethods()
{ {
$matches = array(); return $this->methods;
if (is_string($callable) && preg_match('!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!', $callable, $matches)) {
$class = $matches[1];
$method = $matches[2];
$callable = function() use ($class, $method) {
static $obj = null;
if ($obj === null) {
$obj = new $class;
}
return call_user_func_array(array($obj, $method), func_get_args());
};
}
if (!is_callable($callable)) {
throw new \InvalidArgumentException('Route callable must be callable');
}
$this->callable = $callable;
} }
/** /**
* Get route conditions * Get parent route groups
* @return array *
* @return RouteGroup[]
*/ */
public function getConditions() public function getGroups()
{ {
return $this->conditions; return $this->groups;
}
/**
* Set route conditions
* @param array $conditions
*/
public function setConditions(array $conditions)
{
$this->conditions = $conditions;
} }
/** /**
* Get route name * Get route name
* @return string|null *
* @return null|string
*/ */
public function getName() public function getName()
{ {
return $this->name; return $this->name;
} }
/**
* Get route identifier
*
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Get output buffering mode
*
* @return boolean|string
*/
public function getOutputBuffering()
{
return $this->outputBuffering;
}
/**
* Set output buffering mode
*
* One of: false, 'prepend' or 'append'
*
* @param boolean|string $mode
*
* @throws InvalidArgumentException If an unknown buffering mode is specified
*/
public function setOutputBuffering($mode)
{
if (!in_array($mode, [false, 'prepend', 'append'], true)) {
throw new InvalidArgumentException('Unknown output buffering mode');
}
$this->outputBuffering = $mode;
}
/** /**
* Set route name * Set route name
* @param string $name *
* @param string $name
*
* @return self
*
* @throws InvalidArgumentException if the route name is not a string
*/ */
public function setName($name) public function setName($name)
{ {
$this->name = (string)$name; if (!is_string($name)) {
throw new InvalidArgumentException('Route name must be a string');
}
$this->name = $name;
return $this;
} }
/** /**
* Get route parameters * Set a route argument
*
* @param string $name
* @param string $value
*
* @return self
*/
public function setArgument($name, $value)
{
$this->arguments[$name] = $value;
return $this;
}
/**
* Replace route arguments
*
* @param array $arguments
*
* @return self
*/
public function setArguments(array $arguments)
{
$this->arguments = $arguments;
return $this;
}
/**
* Retrieve route arguments
*
* @return array * @return array
*/ */
public function getParams() public function getArguments()
{ {
return $this->params; return $this->arguments;
} }
/** /**
* Set route parameters * Retrieve a specific route argument
* @param array $params
*/
public function setParams($params)
{
$this->params = $params;
}
/**
* Get route parameter value
* @param string $index Name of URL parameter
* @return string
* @throws \InvalidArgumentException If route parameter does not exist at index
*/
public function getParam($index)
{
if (!isset($this->params[$index])) {
throw new \InvalidArgumentException('Route parameter does not exist at specified index');
}
return $this->params[$index];
}
/**
* Set route parameter value
* @param string $index Name of URL parameter
* @param mixed $value The new parameter value
* @throws \InvalidArgumentException If route parameter does not exist at index
*/
public function setParam($index, $value)
{
if (!isset($this->params[$index])) {
throw new \InvalidArgumentException('Route parameter does not exist at specified index');
}
$this->params[$index] = $value;
}
/**
* Add supported HTTP method(s)
*/
public function setHttpMethods()
{
$args = func_get_args();
$this->methods = $args;
}
/**
* Get supported HTTP methods
* @return array
*/
public function getHttpMethods()
{
return $this->methods;
}
/**
* Append supported HTTP methods
*/
public function appendHttpMethods()
{
$args = func_get_args();
if(count($args) && is_array($args[0])){
$args = $args[0];
}
$this->methods = array_merge($this->methods, $args);
}
/**
* Append supported HTTP methods (alias for Route::appendHttpMethods)
* @return \Slim\Route
*/
public function via()
{
$args = func_get_args();
if(count($args) && is_array($args[0])){
$args = $args[0];
}
$this->methods = array_merge($this->methods, $args);
return $this;
}
/**
* Detect support for an HTTP method
* @param string $method
* @return bool
*/
public function supportsHttpMethod($method)
{
return in_array($method, $this->methods);
}
/**
* Get middleware
* @return array[Callable]
*/
public function getMiddleware()
{
return $this->middleware;
}
/**
* Set middleware
* *
* This method allows middleware to be assigned to a specific Route. * @param string $name
* If the method argument `is_callable` (including callable arrays!), * @param mixed $default
* we directly append the argument to `$this->middleware`. Else, we
* assume the argument is an array of callables and merge the array
* with `$this->middleware`. Each middleware is checked for is_callable()
* and an InvalidArgumentException is thrown immediately if it isn't.
* *
* @param Callable|array[Callable] * @return mixed
* @return \Slim\Route
* @throws \InvalidArgumentException If argument is not callable or not an array of callables.
*/ */
public function setMiddleware($middleware) public function getArgument($name, $default = null)
{ {
if (is_callable($middleware)) { if (array_key_exists($name, $this->arguments)) {
$this->middleware[] = $middleware; return $this->arguments[$name];
} elseif (is_array($middleware)) {
foreach ($middleware as $callable) {
if (!is_callable($callable)) {
throw new \InvalidArgumentException('All Route middleware must be callable');
}
}
$this->middleware = array_merge($this->middleware, $middleware);
} else {
throw new \InvalidArgumentException('Route middleware must be callable or an array of callables');
} }
return $default;
return $this;
} }
/********************************************************************************
* Route Runner
*******************************************************************************/
/** /**
* Matches URI? * Prepare the route for use
* *
* Parse this route's pattern, and then compare it to an HTTP resource URI * @param ServerRequestInterface $request
* This method was modeled after the techniques demonstrated by Dan Sosedoff at: * @param array $arguments
*/
public function prepare(ServerRequestInterface $request, array $arguments)
{
// Add the arguments
foreach ($arguments as $k => $v) {
$this->setArgument($k, $v);
}
}
/**
* Run route
* *
* http://blog.sosedoff.com/2009/09/20/rails-like-php-url-router/ * This method traverses the middleware stack, including the route's callable
* and captures the resultant HTTP response object. It then sends the response
* back to the Application.
* *
* @param string $resourceUri A Request URI * @param ServerRequestInterface $request
* @return bool * @param ResponseInterface $response
*
* @return ResponseInterface
*/ */
public function matches($resourceUri) public function run(ServerRequestInterface $request, ResponseInterface $response)
{ {
//Convert URL params into regex patterns, construct a regex for this route, init params // Finalise route now that we are about to run it
$patternAsRegex = preg_replace_callback( $this->finalize();
'#:([\w]+)\+?#',
array($this, 'matchesCallback'),
str_replace(')', ')?', (string)$this->pattern)
);
if (substr($this->pattern, -1) === '/') {
$patternAsRegex .= '?';
}
$regex = '#^' . $patternAsRegex . '$#'; // Traverse middleware stack and fetch updated response
return $this->callMiddlewareStack($request, $response);
if ($this->caseSensitive === false) {
$regex .= 'i';
}
//Cache URL params' names and values if this route matches the current HTTP request
if (!preg_match($regex, $resourceUri, $paramValues)) {
return false;
}
foreach ($this->paramNames as $name) {
if (isset($paramValues[$name])) {
if (isset($this->paramNamesPath[$name])) {
$this->params[$name] = explode('/', urldecode($paramValues[$name]));
} else {
$this->params[$name] = urldecode($paramValues[$name]);
}
}
}
return true;
} }
/** /**
* Convert a URL parameter (e.g. ":id", ":id+") into a regular expression * Dispatch route callable against current Request and Response objects
* @param array $m URL parameters
* @return string Regular expression for URL parameter
*/
protected function matchesCallback($m)
{
$this->paramNames[] = $m[1];
if (isset($this->conditions[$m[1]])) {
return '(?P<' . $m[1] . '>' . $this->conditions[$m[1]] . ')';
}
if (substr($m[0], -1) === '+') {
$this->paramNamesPath[$m[1]] = 1;
return '(?P<' . $m[1] . '>.+)';
}
return '(?P<' . $m[1] . '>[^/]+)';
}
/**
* Set route name
* @param string $name The name of the route
* @return \Slim\Route
*/
public function name($name)
{
$this->setName($name);
return $this;
}
/**
* Merge route conditions
* @param array $conditions Key-value array of URL parameter conditions
* @return \Slim\Route
*/
public function conditions(array $conditions)
{
$this->conditions = array_merge($this->conditions, $conditions);
return $this;
}
/**
* Dispatch route
* *
* This method invokes the route object's callable. If middleware is * This method invokes the route object's callable. If middleware is
* registered for the route, each callable middleware is invoked in * registered for the route, each callable middleware is invoked in
* the order specified. * the order specified.
* *
* @return bool * @param ServerRequestInterface $request The current Request object
* @param ResponseInterface $response The current Response object
* @return \Psr\Http\Message\ResponseInterface
* @throws \Exception if the route callable throws an exception
*/ */
public function dispatch() public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
{ {
foreach ($this->middleware as $mw) { $this->callable = $this->resolveCallable($this->callable);
call_user_func_array($mw, array($this));
/** @var InvocationStrategyInterface $handler */
$handler = isset($this->container) ? $this->container->get('foundHandler') : new RequestResponse();
// invoke route callable
if ($this->outputBuffering === false) {
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
} else {
try {
ob_start();
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
$output = ob_get_clean();
} catch (Exception $e) {
ob_end_clean();
throw $e;
}
} }
$return = call_user_func_array($this->getCallable(), array_values($this->getParams())); if ($newResponse instanceof ResponseInterface) {
return ($return === false) ? false : true; // if route callback returns a ResponseInterface, then use it
$response = $newResponse;
} elseif (is_string($newResponse)) {
// if route callback returns a string, then append it to the response
if ($response->getBody()->isWritable()) {
$response->getBody()->write($newResponse);
}
}
if (!empty($output) && $response->getBody()->isWritable()) {
if ($this->outputBuffering === 'prepend') {
// prepend output buffer content
$body = new Http\Body(fopen('php://temp', 'r+'));
$body->write($output . $response->getBody());
$response = $response->withBody($body);
} elseif ($this->outputBuffering === 'append') {
// append output buffer content
$response->getBody()->write($output);
}
}
return $response;
} }
} }
+47
View File
@@ -0,0 +1,47 @@
<?php
/**
* Slim Framework (http://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2015 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use Closure;
use Slim\Interfaces\RouteGroupInterface;
/**
* A collector for Routable objects with a common middleware stack
*
* @package Slim
*/
class RouteGroup extends Routable implements RouteGroupInterface
{
/**
* Create a new RouteGroup
*
* @param string $pattern The pattern prefix for the group
* @param callable $callable The group callable
*/
public function __construct($pattern, $callable)
{
$this->pattern = $pattern;
$this->callable = $callable;
}
/**
* Invoke the group to register any Routable objects within it.
*
* @param App $app The App to bind the callable to.
*/
public function __invoke(App $app = null)
{
$callable = $this->resolveCallable($this->callable);
if ($callable instanceof Closure && $app !== null) {
$callable = $callable->bindTo($app);
}
$callable();
}
}
+292 -166
View File
@@ -1,257 +1,383 @@
<?php <?php
/** /**
* Slim - a micro PHP 5 framework * Slim Framework (http://slimframework.com)
* *
* @author Josh Lockhart <[email protected]> * @link https://github.com/slimphp/Slim
* @copyright 2011 Josh Lockhart * @copyright Copyright (c) 2011-2015 Josh Lockhart
* @link http://www.slimframework.com * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
* @license http://www.slimframework.com/license
* @version 2.6.1
* @package Slim
*
* MIT LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
namespace Slim; namespace Slim;
use FastRoute\Dispatcher;
use InvalidArgumentException;
use RuntimeException;
use Psr\Http\Message\ServerRequestInterface;
use FastRoute\RouteCollector;
use FastRoute\RouteParser;
use FastRoute\RouteParser\Std as StdParser;
use FastRoute\DataGenerator;
use Slim\Interfaces\RouteGroupInterface;
use Slim\Interfaces\RouterInterface;
use Slim\Interfaces\RouteInterface;
/** /**
* Router * Router
* *
* This class organizes, iterates, and dispatches \Slim\Route objects. * This class organizes Slim application route objects. It is responsible
* * for registering route objects, assigning names to route objects,
* @package Slim * finding routes that match the current HTTP request, and creating
* @author Josh Lockhart * URLs for a named route.
* @since 1.0.0
*/ */
class Router class Router implements RouterInterface
{ {
/** /**
* @var Route The current route (most recently dispatched) * Parser
*
* @var \FastRoute\RouteParser
*/ */
protected $currentRoute; protected $routeParser;
/** /**
* @var array Lookup hash of all route objects * Base path used in pathFor()
*
* @var string
*/ */
protected $routes; protected $basePath = '';
/** /**
* @var array Lookup hash of named route objects, keyed by route name (lazy-loaded) * Routes
*
* @var Route[]
*/
protected $routes = [];
/**
* Route counter incrementer
* @var int
*/
protected $routeCounter = 0;
/**
* Named routes
*
* @var null|Route[]
*/ */
protected $namedRoutes; protected $namedRoutes;
/** /**
* @var array Array of route objects that match the request URI (lazy-loaded) * Route groups
*
* @var RouteGroup[]
*/ */
protected $matchedRoutes; protected $routeGroups = [];
/** /**
* @var array Array containing all route groups * @var \FastRoute\Dispatcher
*/ */
protected $routeGroups; protected $dispatcher;
/** /**
* Constructor * Create new router
*
* @param RouteParser $parser
*/ */
public function __construct() public function __construct(RouteParser $parser = null)
{ {
$this->routes = array(); $this->routeParser = $parser ?: new StdParser;
$this->routeGroups = array();
} }
/** /**
* Get Current Route object or the first matched one if matching has been performed * Set the base path used in pathFor()
* @return \Slim\Route|null *
* @param string $basePath
*
* @return self
*/ */
public function getCurrentRoute() public function setBasePath($basePath)
{ {
if ($this->currentRoute !== null) { if (!is_string($basePath)) {
return $this->currentRoute; throw new InvalidArgumentException('Router basePath must be a string');
} }
if (is_array($this->matchedRoutes) && count($this->matchedRoutes) > 0) { $this->basePath = $basePath;
return $this->matchedRoutes[0];
}
return null; return $this;
} }
/** /**
* Return route objects that match the given HTTP method and URI * Add route
* @param string $httpMethod The HTTP method to match against *
* @param string $resourceUri The resource URI to match against * @param string[] $methods Array of HTTP methods
* @param bool $reload Should matching routes be re-parsed? * @param string $pattern The route pattern
* @return array[\Slim\Route] * @param callable $handler The route callable
*
* @return RouteInterface
*
* @throws InvalidArgumentException if the route pattern isn't a string
*/ */
public function getMatchedRoutes($httpMethod, $resourceUri, $reload = false) public function map($methods, $pattern, $handler)
{ {
if ($reload || is_null($this->matchedRoutes)) { if (!is_string($pattern)) {
$this->matchedRoutes = array(); throw new InvalidArgumentException('Route pattern must be a string');
foreach ($this->routes as $route) { }
if (!$route->supportsHttpMethod($httpMethod) && !$route->supportsHttpMethod("ANY")) {
continue;
}
if ($route->matches($resourceUri)) { // Prepend parent group pattern(s)
$this->matchedRoutes[] = $route; if ($this->routeGroups) {
} $pattern = $this->processGroups() . $pattern;
}
// According to RFC methods are defined in uppercase (See RFC 7231)
$methods = array_map("strtoupper", $methods);
// Add route
$route = new Route($methods, $pattern, $handler, $this->routeGroups, $this->routeCounter);
$this->routes[$route->getIdentifier()] = $route;
$this->routeCounter++;
return $route;
}
/**
* Dispatch router for HTTP request
*
* @param ServerRequestInterface $request The current HTTP request object
*
* @return array
*
* @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php
*/
public function dispatch(ServerRequestInterface $request)
{
$uri = '/' . ltrim($request->getUri()->getPath(), '/');
return $this->createDispatcher()->dispatch(
$request->getMethod(),
$uri
);
}
/**
* @return \FastRoute\Dispatcher
*/
protected function createDispatcher()
{
return $this->dispatcher ?: \FastRoute\simpleDispatcher(function (RouteCollector $r) {
foreach ($this->getRoutes() as $route) {
$r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier());
} }
} }, [
'routeParser' => $this->routeParser
return $this->matchedRoutes; ]);
} }
/** /**
* Add a route object to the router * @param \FastRoute\Dispatcher $dispatcher
* @param \Slim\Route $route The Slim Route
*/ */
public function map(\Slim\Route $route) public function setDispatcher(Dispatcher $dispatcher)
{ {
list($groupPattern, $groupMiddleware) = $this->processGroups(); $this->dispatcher = $dispatcher;
$route->setPattern($groupPattern . $route->getPattern());
$this->routes[] = $route;
foreach ($groupMiddleware as $middleware) {
$route->setMiddleware($middleware);
}
} }
/** /**
* A helper function for processing the group's pattern and middleware * Get route objects
* @return array Returns an array with the elements: pattern, middlewareArr *
* @return Route[]
*/
public function getRoutes()
{
return $this->routes;
}
/**
* Get named route object
*
* @param string $name Route name
*
* @return Route
*
* @throws RuntimeException If named route does not exist
*/
public function getNamedRoute($name)
{
if (is_null($this->namedRoutes)) {
$this->buildNameIndex();
}
if (!isset($this->namedRoutes[$name])) {
throw new RuntimeException('Named route does not exist for name: ' . $name);
}
return $this->namedRoutes[$name];
}
/**
* Process route groups
*
* @return string A group pattern to prefix routes with
*/ */
protected function processGroups() protected function processGroups()
{ {
$pattern = ""; $pattern = "";
$middleware = array();
foreach ($this->routeGroups as $group) { foreach ($this->routeGroups as $group) {
$k = key($group); $pattern .= $group->getPattern();
$pattern .= $k;
if (is_array($group[$k])) {
$middleware = array_merge($middleware, $group[$k]);
}
} }
return array($pattern, $middleware); return $pattern;
} }
/** /**
* Add a route group to the array * Add a route group to the array
* @param string $group The group pattern (ie. "/books/:id") *
* @param array|null $middleware Optional parameter array of middleware * @param string $pattern
* @return int The index of the new group * @param callable $callable
*
* @return RouteGroupInterface
*/ */
public function pushGroup($group, $middleware = array()) public function pushGroup($pattern, $callable)
{ {
return array_push($this->routeGroups, array($group => $middleware)); $group = new RouteGroup($pattern, $callable);
array_push($this->routeGroups, $group);
return $group;
} }
/** /**
* Removes the last route group from the array * Removes the last route group from the array
* @return bool True if successful, else False *
* @return RouteGroup|bool The RouteGroup if successful, else False
*/ */
public function popGroup() public function popGroup()
{ {
return (array_pop($this->routeGroups) !== null); $group = array_pop($this->routeGroups);
return $group instanceof RouteGroup ? $group : false;
} }
/** /**
* Get URL for named route * @param $identifier
* @param string $name The name of the route * @return \Slim\Interfaces\RouteInterface
* @param array $params Associative array of URL parameter names and replacement values
* @throws \RuntimeException If named route not found
* @return string The URL for the given route populated with provided replacement values
*/ */
public function urlFor($name, $params = array()) public function lookupRoute($identifier)
{ {
if (!$this->hasNamedRoute($name)) { if (!isset($this->routes[$identifier])) {
throw new \RuntimeException('Named route not found for name: ' . $name); throw new RuntimeException('Route not found, looks like your route cache is stale.');
} }
$search = array(); return $this->routes[$identifier];
foreach ($params as $key => $value) {
$search[] = '#:' . preg_quote($key, '#') . '\+?(?!\w)#';
}
$pattern = preg_replace($search, $params, $this->getNamedRoute($name)->getPattern());
//Remove remnants of unpopulated, trailing optional pattern segments, escaped special characters
return preg_replace('#\(/?:.+\)|\(|\)|\\\\#', '', $pattern);
} }
/** /**
* Add named route * Build the path for a named route excluding the base path
* @param string $name The route name *
* @param \Slim\Route $route The route object * @param string $name Route name
* @throws \RuntimeException If a named route already exists with the same name * @param array $data Named argument replacement data
* @param array $queryParams Optional query string parameters
*
* @return string
*
* @throws RuntimeException If named route does not exist
* @throws InvalidArgumentException If required data not provided
*/ */
public function addNamedRoute($name, \Slim\Route $route) public function relativePathFor($name, array $data = [], array $queryParams = [])
{ {
if ($this->hasNamedRoute($name)) { $route = $this->getNamedRoute($name);
throw new \RuntimeException('Named route already exists with name: ' . $name); $pattern = $route->getPattern();
}
$this->namedRoutes[(string) $name] = $route;
}
/** $routeDatas = $this->routeParser->parse($pattern);
* Has named route // $routeDatas is an array of all possible routes that can be made. There is
* @param string $name The route name // one routedata for each optional parameter plus one for no optional parameters.
* @return bool //
*/ // The most specific is last, so we look for that first.
public function hasNamedRoute($name) $routeDatas = array_reverse($routeDatas);
{
$this->getNamedRoutes();
return isset($this->namedRoutes[(string) $name]); $segments = [];
} foreach ($routeDatas as $routeData) {
foreach ($routeData as $item) {
/** if (is_string($item)) {
* Get named route // this segment is a static string
* @param string $name $segments[] = $item;
* @return \Slim\Route|null continue;
*/
public function getNamedRoute($name)
{
$this->getNamedRoutes();
if ($this->hasNamedRoute($name)) {
return $this->namedRoutes[(string) $name];
}
return null;
}
/**
* Get named routes
* @return \ArrayIterator
*/
public function getNamedRoutes()
{
if (is_null($this->namedRoutes)) {
$this->namedRoutes = array();
foreach ($this->routes as $route) {
if ($route->getName() !== null) {
$this->addNamedRoute($route->getName(), $route);
} }
// This segment has a parameter: first element is the name
if (!array_key_exists($item[0], $data)) {
// we don't have a data element for this segment: cancel
// testing this routeData item, so that we can try a less
// specific routeData item.
$segments = [];
$segmentName = $item[0];
break;
}
$segments[] = $data[$item[0]];
}
if (!empty($segments)) {
// we found all the parameters for this route data, no need to check
// less specific ones
break;
} }
} }
return new \ArrayIterator($this->namedRoutes); if (empty($segments)) {
throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName);
}
$url = implode('', $segments);
if ($queryParams) {
$url .= '?' . http_build_query($queryParams);
}
return $url;
}
/**
* Build the path for a named route including the base path
*
* @param string $name Route name
* @param array $data Named argument replacement data
* @param array $queryParams Optional query string parameters
*
* @return string
*
* @throws RuntimeException If named route does not exist
* @throws InvalidArgumentException If required data not provided
*/
public function pathFor($name, array $data = [], array $queryParams = [])
{
$url = $this->relativePathFor($name, $data, $queryParams);
if ($this->basePath) {
$url = $this->basePath . $url;
}
return $url;
}
/**
* Build the path for a named route.
*
* This method is deprecated. Use pathFor() from now on.
*
* @param string $name Route name
* @param array $data Named argument replacement data
* @param array $queryParams Optional query string parameters
*
* @return string
*
* @throws RuntimeException If named route does not exist
* @throws InvalidArgumentException If required data not provided
*/
public function urlFor($name, array $data = [], array $queryParams = [])
{
trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED);
return $this->pathFor($name, $data, $queryParams);
}
/**
* Build index of named routes
*/
protected function buildNameIndex()
{
$this->namedRoutes = [];
foreach ($this->routes as $route) {
$name = $route->getName();
if ($name) {
$this->namedRoutes[$name] = $route;
}
}
} }
} }
+11 -43
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -54,7 +54,7 @@ class Slim
/** /**
* @const string * @const string
*/ */
const VERSION = '2.6.1'; const VERSION = '2.4.2';
/** /**
* @var \Slim\Helper\Set * @var \Slim\Helper\Set
@@ -231,22 +231,22 @@ class Slim
public function __get($name) public function __get($name)
{ {
return $this->container->get($name); return $this->container[$name];
} }
public function __set($name, $value) public function __set($name, $value)
{ {
$this->container->set($name, $value); $this->container[$name] = $value;
} }
public function __isset($name) public function __isset($name)
{ {
return $this->container->has($name); return isset($this->container[$name]);
} }
public function __unset($name) public function __unset($name)
{ {
$this->container->remove($name); unset($this->container[$name]);
} }
/** /**
@@ -906,12 +906,7 @@ class Slim
} }
} }
/* return $value;
* transform $value to @return doc requirement.
* \Slim\Http\Util::decodeSecureCookie - is able
* to return false and we have to cast it to null.
*/
return $value === false ? null : $value;
} }
/** /**
@@ -1105,18 +1100,6 @@ class Slim
$this->halt($status); $this->halt($status);
} }
/**
* RedirectTo
*
* Redirects to a specific named route
*
* @param string $route The route name
* @param array $params Associative array of URL parameters and replacement values
*/
public function redirectTo($route, $params = array(), $status = 302){
$this->redirect($this->urlFor($route, $params), $status);
}
/******************************************************************************** /********************************************************************************
* Flash Messages * Flash Messages
*******************************************************************************/ *******************************************************************************/
@@ -1155,16 +1138,6 @@ class Slim
} }
} }
/**
* Get all flash messages
*/
public function flashData()
{
if (isset($this->environment['slim.flash'])) {
return $this->environment['slim.flash']->getMessages();
}
}
/******************************************************************************** /********************************************************************************
* Hooks * Hooks
*******************************************************************************/ *******************************************************************************/
@@ -1187,10 +1160,10 @@ class Slim
/** /**
* Invoke hook * Invoke hook
* @param string $name The hook name * @param string $name The hook name
* @param mixed ... (Optional) Argument(s) for hooked functions, can specify multiple arguments * @param mixed $hookArg (Optional) Argument for hooked functions
*/ */
public function applyHook($name) public function applyHook($name, $hookArg = null)
{ {
if (!isset($this->hooks[$name])) { if (!isset($this->hooks[$name])) {
$this->hooks[$name] = array(array()); $this->hooks[$name] = array(array());
@@ -1200,14 +1173,10 @@ class Slim
if (count($this->hooks[$name]) > 1) { if (count($this->hooks[$name]) > 1) {
ksort($this->hooks[$name]); ksort($this->hooks[$name]);
} }
$args = func_get_args();
array_shift($args);
foreach ($this->hooks[$name] as $priority) { foreach ($this->hooks[$name] as $priority) {
if (!empty($priority)) { if (!empty($priority)) {
foreach ($priority as $callable) { foreach ($priority as $callable) {
call_user_func_array($callable, $args); call_user_func($callable, $hookArg);
} }
} }
} }
@@ -1375,7 +1344,6 @@ class Slim
throw $e; throw $e;
} else { } else {
try { try {
$this->response()->write(ob_get_clean());
$this->error($e); $this->error($e);
} catch (\Slim\Exception\Stop $e) { } catch (\Slim\Exception\Stop $e) {
// Do nothing // Do nothing
+4 -4
View File
@@ -6,7 +6,7 @@
* @copyright 2011 Josh Lockhart * @copyright 2011 Josh Lockhart
* @link http://www.slimframework.com * @link http://www.slimframework.com
* @license http://www.slimframework.com/license * @license http://www.slimframework.com/license
* @version 2.6.1 * @version 2.4.2
* @package Slim * @package Slim
* *
* MIT LICENSE * MIT LICENSE
@@ -108,7 +108,7 @@ class View
* @param string $key * @param string $key
* @param mixed $value * @param mixed $value
*/ */
public function keep($key, \Closure $value) public function keep($key, Closure $value)
{ {
$this->data->keep($key, $value); $this->data->keep($key, $value);
} }
@@ -152,9 +152,9 @@ class View
{ {
if (!is_null($key)) { if (!is_null($key)) {
return isset($this->data[$key]) ? $this->data[$key] : null; return isset($this->data[$key]) ? $this->data[$key] : null;
} else {
return $this->data->all();
} }
return $this->data->all();
} }
/** /**
+12
View File
@@ -0,0 +1,12 @@
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ serviceapp.php [QSA,L]
</ifModule>
<Limit GET POST PUT DELETE>
# Allow from app.gruppolapastamadre.it
</Limit>
#Header set Access-Control-Allow-Origin "app.gruppolapastamadre.it"
#Header set Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"
+1 -1
View File
@@ -5,7 +5,7 @@ $allowedHost = array(
"denisnotebook", "denisnotebook",
"app.gruppolapastamadre.it", "app.gruppolapastamadre.it",
"dev.gruppolapastamadre.it", "dev.gruppolapastamadre.it",
"blog.gruppolapastamadre.it", "old.gruppolapastamadre.it",
"management.gruppolapastamadre.it" "management.gruppolapastamadre.it"
); );
+22 -57
View File
@@ -5,93 +5,58 @@ require_once "./include.php";
require_once "./myDropBoxObj.php"; require_once "./myDropBoxObj.php";
//include "./SimpleImage.php"; //include "./SimpleImage.php";
$app->get('/photo/thumbnail/:imageID(/:noRedirect)', function ($imageID, $noRedirect = 0) use ($app, $dirRicetteDropBox) { $app->get('/photos/thumbnail/:imageID(/:createImgTag)', function ($imageID, $createImgTag = 0) use ($app, $dirRicetteDropBox) {
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$retObj = $mysqlconnetion->queryToObject("select type_format, id_ricette, thumb_link from immagini where id=" . $imageID, false); $retObj = $mysqlconnetion->queryToObject("select type_format, id_ricette from immagini where id=" . $imageID, false);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
$ext = "png";
$retLink = $retObj["thumb_link"];
if($retLink == ""){
$folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
$imageFileName = $imageID . "_thumb_ricetta." . $ext;
$dropBoxObj = new myDropBox();
$retLink = $dropBoxObj->GetLink($folder . "/" . $imageFileName);
}
if ($noRedirect) {
echo $retLink;
}
else
$app->response->redirect($retLink, 303);
});
$app->get('/photo/medium/:imageID(/:noRedirect)', function ($imageID, $noRedirect = 0) use ($app, $dirRicetteDropBox) {
$mysqlconnetion = new MysqlClass;
$retObj = $mysqlconnetion->queryToObject("select type_format, id_ricette, medium_link from immagini where id=" . $imageID, false);
$mysqlconnetion->disconnetti();
$ext = ""; $ext = "";
if ($retObj["type_format"] == "image/jpeg") { if ($retObj["type_format"] == "image/jpeg") {
$ext = "jpeg"; $ext = "jpg";
} else if ($retObj["type_format"] == "image/png") { } else if ($retObj["type_format"] == "image/png") {
$ext = "png"; $ext = "png";
} }
$retLink = $retObj["medium_link"]; $folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
if($retLink == ""){ $imageFileName = $imageID . "_thumb_ricetta." . $ext;
$folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
$imageFileName = $imageID . "_medium_ricetta." . $ext; $dropBoxObj = new myDropBox();
$dropBoxObj = new myDropBox(); if ($createImgTag) {
echo '<img src="';
$retLink = $dropBoxObj->GetLink($folder . "/" . $imageFileName);
} }
echo $dropBoxObj->GetLink($folder . "/" . $imageFileName);
if ($noRedirect) { if ($createImgTag) {
echo $retLink; echo '"/>';
} }
else
$app->response->redirect($retLink, 303);
}); });
$app->get('/photo/:imageID(/:noRedirect)', function ($imageID, $noRedirect = 0) use ($app, $dirRicetteDropBox) { $app->get('/photos/:imageID(/:createImgTag)', function ($imageID, $createImgTag = 0) use ($app, $dirRicetteDropBox) {
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$retObj = $mysqlconnetion->queryToObject("select type_format, id_ricette, full_link from immagini where id=" . $imageID, false); $retObj = $mysqlconnetion->queryToObject("select type_format, id_ricette from immagini where id=" . $imageID, false);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
$ext = ""; $ext = "";
if ($retObj["type_format"] == "image/jpeg") { if ($retObj["type_format"] == "image/jpeg") {
$ext = "jpeg"; $ext = "jpg";
} else if ($retObj["type_format"] == "image/png") { } else if ($retObj["type_format"] == "image/png") {
$ext = "png"; $ext = "png";
} }
$retLink = $retObj["full_link"]; $folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
if($retLink == ""){ $imageFileName = $imageID . "_full_ricetta." . $ext;
$folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
$imageFileName = $imageID . "_full_ricetta." . $ext; $dropBoxObj = new myDropBox();
$dropBoxObj = new myDropBox(); if ($createImgTag) {
echo '<img src="';
$retLink = $dropBoxObj->GetLink($folder . "/" . $imageFileName);
} }
echo $dropBoxObj->GetLink($folder . "/" . $imageFileName);
if ($noRedirect) { if ($createImgTag) {
echo $retLink; echo '"/>';
} }
else
$app->response->redirect($retLink, 303);
}); });
+22 -137
View File
@@ -9,7 +9,7 @@ use PHPImageWorkshop\ImageWorkshop;
require_once 'PHPImageWorkshop/ImageWorkshop.php'; // Be sure of the path to the class require_once 'PHPImageWorkshop/ImageWorkshop.php'; // Be sure of the path to the class
//include "./SimpleImage.php"; //include "./SimpleImage.php";
$app->get('/photo/publish/:imageID', function ($imageID) use ($app) { $app->put('/photos/publish/:imageID', function ($imageID) use ($app) {
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query = "update immagini set published = 1, published_date = NOW() where id = " . $imageID; $query = "update immagini set published = 1, published_date = NOW() where id = " . $imageID;
@@ -18,51 +18,7 @@ $app->get('/photo/publish/:imageID', function ($imageID) use ($app) {
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
}); });
$app->get('/photo/set_cover/:imageID', function ($imageID) use ($app) { $app->post('/photos', function () use ($app) {
$mysqlconnetion = new MysqlClass;
$query = "select id_ricette from immagini where id = " . $imageID;
$retObj = $mysqlconnetion->queryToObject($query, false);
$query = "update immagini set bCover = 0 where id_ricette = " . $retObj["id_ricette"];
$mysqlconnetion->insertRecord($query);
$query = "update immagini set bCover = 1 where id = " . $imageID;
$mysqlconnetion->insertRecord($query);
$mysqlconnetion->disconnetti();
});
$app->delete('/photo/:imageID', function ($imageID) use ($app,$dirRicetteDropBox) {
$mysqlconnetion = new MysqlClass;
$query = "select id_ricette, type_format from immagini where id = " . $imageID;
$retObj = $mysqlconnetion->queryToObject($query, false);
$ext = "";
if ($retObj["type_format"] == "image/jpeg") {
$ext = "jpeg";
} else if ($retObj["type_format"] == "image/png") {
$ext = "png";
}
$dropBoxObj = new myDropBox();
$folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
$imageFileName = $imageID . "_full_ricetta." . $ext;
$dropBoxObj->Delete($folder . "/" . $imageFileName);
$imageFileName = $imageID . "_medium_ricetta." . $ext;
$dropBoxObj->Delete($folder . "/" . $imageFileName);
$imageFileName = $imageID . "_thumb_ricetta." . $ext;
$dropBoxObj->Delete($folder . "/" . $imageFileName);
$query = "delete from immagini where id = " . $imageID;
$mysqlconnetion->executeQuery($query);
$mysqlconnetion->disconnetti();
});
$app->post('/photo', function () use ($app, $dirRicetteDropBox) {
$idRicette = $app->request()->post('ricetta_id'); $idRicette = $app->request()->post('ricetta_id');
$profileID = $app->request()->post('keyStore'); $profileID = $app->request()->post('keyStore');
$tmpFileName = $_FILES['image']["tmp_name"]; $tmpFileName = $_FILES['image']["tmp_name"];
@@ -70,9 +26,9 @@ $app->post('/photo', function () use ($app, $dirRicetteDropBox) {
// istanza della classe // istanza della classe
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconneti on->connetti(); //$mysqlconneti on->connetti();
$query = "insert into immagini(id_ricette, type_format, from_profile_id, uploaded_date, bCover) " . $query = "insert into immagini(id_ricette, type_format, from_profile_id, uploaded_date) " .
"values(" . $idRicette . ", '" . image_type_to_mime_type(exif_imagetype($tmpFileName)) . "values(" . $idRicette . ", '" . image_type_to_mime_type(exif_imagetype($tmpFileName)) .
"', '" . $profileID . "', NOW(), 0)"; "', '" . $profileID . "', NOW())";
$newID = $mysqlconnetion->insertRecord($query); $newID = $mysqlconnetion->insertRecord($query);
$ext = image_type_to_extension(exif_imagetype($tmpFileName), FALSE); $ext = image_type_to_extension(exif_imagetype($tmpFileName), FALSE);
@@ -81,117 +37,46 @@ $app->post('/photo', function () use ($app, $dirRicetteDropBox) {
$dropBoxObj = new myDropBox(); $dropBoxObj = new myDropBox();
$full_link = resizeImage($dropBoxObj, $layer, 640, dirname($tmpFileName), $imageFileName, $folder); resizeImage($dropBoxObj, $layer, 640, dirname($tmpFileName), $imageFileName, $folder);
$imageMediumFileName = $newID . "_medium_ricetta." . $ext; $imageMediumFileName = $newID . "_medium_ricetta." . $ext;
$medium_link = resizeImage($dropBoxObj, $layer, 320, dirname($tmpFileName), $imageMediumFileName, $folder); resizeImage($dropBoxObj, $layer, 320, dirname($tmpFileName), $imageMediumFileName, $folder);
$thumbFileName = $newID . "_thumb_ricetta." . $ext; $thumbFileName = $newID . "_thumb_ricetta." . $ext;
$thumb_link = makeThumbImage($dropBoxObj, $layer, 80, dirname($tmpFileName), $thumbFileName, $folder); resizeImage($dropBoxObj, $layer, 80, dirname($tmpFileName), $thumbFileName, $folder);
$query = "update immagini set thumb_link = '" . $thumb_link . "', medium_link ='" . $medium_link . "', full_link = '" . $full_link ."'" .
" where id=" . $newID;
$newID = $mysqlconnetion->insertRecord($query);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
echo $newID; echo $newID;
}); });
$app->put('/photo/:imageID', function ($imageID) use ($app, $dirRicetteDropBox) { $app->put('/photos/:imageID', function ($imageID) use ($app) {
$tmpFileName = $_FILES['image']["tmp_name"]; $tmpFileName = $_FILES['image']["tmp_name"];
$layer = ImageWorkshop::initFromPath($tmpFileName); $layer = ImageWorkshop::initFromPath($tmpFileName);
// istanza della classe // istanza della classe
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconneti on->connetti(); //$mysqlconneti on->connetti();
$query = "update immagini set (type_format = '" . image_type_to_mime_type(exif_imagetype($tmpFileName)) . "', " .
$folder = $dirRicetteDropBox . "/" . $imageID;
$imageFileName = $imageID . "_full_ricetta." . $ext;
$full_link = resizeImage($dropBoxObj, $layer, 640, dirname($tmpFileName), $imageFileName, $folder);
$imageMediumFileName = $imageID . "_medium_ricetta." . $ext;
$medium_link = resizeImage($dropBoxObj, $layer, 320, dirname($tmpFileName), $imageMediumFileName, $folder);
$thumbFileName = $imageID . "_thumb_ricetta." . $ext;
$thumb_link = makeThumbImage($dropBoxObj, $layer, 80, dirname($tmpFileName), $thumbFileName, $folder);
$query = "update immagini set (type_format = '" . image_type_to_mime_type(exif_imagetype($tmpFileName)) .
"', thumb_link = '" . $thumb_link . "', medium_link ='" . $medium_link . "', full_link = '" . $full_link ."' )" .
" where id=" . $imageID; " where id=" . $imageID;
$newID = $mysqlconnetion->insertRecord($query); $newID = $mysqlconnetion->insertRecord($query);
$folder = $dirRicetteDropBox . "/" . $newID;
$imageFileName = $newID . "_full_ricetta." . $ext;
resizeImage($dropBoxObj, $layer, 640, dirname($tmpFileName), $imageFileName, $folder);
$imageMediumFileName = $newID . "_medium_ricetta." . $ext;
resizeImage($dropBoxObj, $layer, 320, dirname($tmpFileName), $imageMediumFileName, $folder);
$thumbFileName = $newID . "_thumb_ricetta." . $ext;
resizeImage($dropBoxObj, $layer, 80, dirname($tmpFileName), $thumbFileName, $folder);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
return $newID; return $newID;
}); });
$app->get('/photo/fixLink', function () use ($app, $dirRicetteDropBox) {
ini_set('max_execution_time', 3000);
$mysqlconnetion = new MysqlClass;
$retObj2 = $mysqlconnetion->queryToObject("select type_format, id, id_ricette, thumb_link, medium_link, full_link from immagini where published = 1");
foreach ($retObj2 as $retObj) {
$imageID = $retObj["id"];
$ext = "";
if ($retObj["type_format"] == "image/jpeg") {
$ext = "jpeg";
} else if ($retObj["type_format"] == "image/png") {
$ext = "png";
}
$full_link = $retObj["full_link"];
if($full_link == ""){
$folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
$imageFileName = $imageID . "_full_ricetta." . $ext;
$dropBoxObj = new myDropBox();
$full_link = $dropBoxObj->GetLink($folder . "/" . $imageFileName);
}
$medium_link = $retObj["medium_link"];
if($medium_link == ""){
$folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
$imageFileName = $imageID . "_medium_ricetta." . $ext;
$dropBoxObj = new myDropBox();
$medium_link = $dropBoxObj->GetLink($folder . "/" . $imageFileName);
}
$thumb_link = $retObj["thumb_link"];
if($thumb_link == ""){
$folder = $dirRicetteDropBox . "/" . $retObj["id_ricette"];
$imageFileName = $imageID . "_thumb_ricetta.png";
$dropBoxObj = new myDropBox();
$thumb_link = $dropBoxObj->GetLink($folder . "/" . $imageFileName);
}
$query = "update immagini set thumb_link = '" . $thumb_link . "', medium_link ='" . $medium_link . "', full_link = '" . $full_link ."'" .
" where id=" . $imageID;
$newID = $mysqlconnetion->insertRecord($query);
}
$mysqlconnetion->disconnetti();
});
+2 -23
View File
@@ -5,6 +5,7 @@ require_once "./config.inc.php";
// inclusione del file contenente la classe // inclusione del file contenente la classe
require_once "./MySqlClass.php"; require_once "./MySqlClass.php";
require_once "./utility.php"; require_once "./utility.php";
require_once "./Middleware/CheckFrom.php";
require_once 'Slim/Slim.php'; require_once 'Slim/Slim.php';
@@ -14,28 +15,6 @@ $app = new \Slim\Slim();
date_default_timezone_set('Europe/Rome'); date_default_timezone_set('Europe/Rome');
$app->hook('slim.before.router', function () use ($app, $allowedHost) { $app->add( new CheckFromMV() );
/*$currentRefererRequest = $app->request()->getReferer();
$currentRefererRequest = substr($currentRefererRequest, 7); //Senza http://
$indexDoublePoint = strpos($currentRefererRequest, ':');
$indexFirstSlash = strpos($currentRefererRequest, '/');
$currentRefererRequest = substr($currentRefererRequest, 0, $indexDoublePoint > 0 && $indexDoublePoint < $indexFirstSlash ? $indexDoublePoint : $indexFirstSlash );
if(!in_array($currentRefererRequest, $allowedHost))
{
$app->halt(500, "Generic error occurred");
return;
}
$currentHostRequest = $app->request()->getHost();
if(!in_array($currentHostRequest, $allowedHost))
{
$app->halt(403, "Request arrive from host not allowed " . $currentHostRequest );
return;
}
*/
if(isset($_SERVER['HTTP_ORIGIN']))
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
});
?> ?>
+13 -88
View File
@@ -41,6 +41,17 @@ $app->get('/ricette/:catID', function ($categoryID) use ($app) {
returnJson($app, $callbackFn, $retObj); returnJson($app, $callbackFn, $retObj);
}); });
$app->delete('/ricetta/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback');
// istanza della classe
$mysqlconnetion = new MysqlClass;
$query = "DELETE FROM ricette WHERE ricette.ID = " . $itemID;
$retObj = $mysqlconnetion->insertRecord($query);
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/ricetta/body/:itemID', function ($itemID) use ($app) { $app->get('/ricetta/body/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
// istanza della classe // istanza della classe
@@ -55,10 +66,6 @@ $app->get('/ricetta/body/:itemID', function ($itemID) use ($app) {
$retObj2 = $mysqlconnetion->queryToObject($query2); $retObj2 = $mysqlconnetion->queryToObject($query2);
foreach ($retObj2 as $ele) {
$ele["note"] = html_entity_decode($ele["note"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
}
$retObj[0]["titolo"] = html_entity_decode($retObj[0]["titolo"],ENT_COMPAT | ENT_HTML401,'ISO-8859-1'); $retObj[0]["titolo"] = html_entity_decode($retObj[0]["titolo"],ENT_COMPAT | ENT_HTML401,'ISO-8859-1');
$retObj[0]["procedimento"] = html_entity_decode($retObj[0]["procedimento"],ENT_COMPAT | ENT_HTML401,'ISO-8859-1'); $retObj[0]["procedimento"] = html_entity_decode($retObj[0]["procedimento"],ENT_COMPAT | ENT_HTML401,'ISO-8859-1');
$retObj[0]["ingredienti"] = $retObj2; $retObj[0]["ingredienti"] = $retObj2;
@@ -102,10 +109,6 @@ $app->post('/ricetta/body', function () use ($app) {
$mysqlconnetion->executeQuery($query); $mysqlconnetion->executeQuery($query);
$queryDelete = "DELETE FROM ingredienti where ID_RICETTE = " . $json_data_body->ricettaID; $queryDelete = "DELETE FROM ingredienti where ID_RICETTE = " . $json_data_body->ricettaID;
$mysqlconnetion->executeQuery($queryDelete); $mysqlconnetion->executeQuery($queryDelete);
$queryUpdDataMod = "UPDATE ricette SET data_modifica = NOW() where ID = " . $json_data_body->ricettaID;
$mysqlconnetion->executeQuery($queryUpdDataMod);
$retNewID = $json_data_body->ricettaID; $retNewID = $json_data_body->ricettaID;
} else { } else {
@@ -125,44 +128,14 @@ $app->post('/ricetta/body', function () use ($app) {
} }
$query = "insert into ingredienti(ID_TIPO_INGREDIENTI, ID_RICETTE, Quantita, ID_TIPO_QUANTITA, Note, Posizione) values (" . $query = "insert into ingredienti(ID_TIPO_INGREDIENTI, ID_RICETTE, Quantita, ID_TIPO_QUANTITA, Note, Posizione) values (" .
$arr->ingrediente_id . "," . $retNewID . ",'" . ($arr->quantita == "" ? "0" : $arr->quantita) . "'," . ($arr->tipo_quantita_id == "" ? "NULL" : $arr->tipo_quantita_id) . ",'" . $note . "'," . $pos . ")"; $arr->ingrediente_id . "," . $retNewID . "," . ($arr->quantita == "" ? "0" : $arr->quantita) . "," . ($arr->tipo_quantita_id == "" ? "NULL" : $arr->tipo_quantita_id) . ",'" . $note . "'," . $pos . ")";
$mysqlconnetion->insertRecord($query); $mysqlconnetion->insertRecord($query);
$pos = $pos + 1; $pos = $pos + 1;
} }
$retValue["ricettaID"] = $retNewID;
$retValue["message"] = "Ricetta inserita con successo"; $retValue["message"] = "Ricetta inserita con successo";
} catch (Exception $e) { } catch (Exception $e) {
$retValue["result"] = false;
$retValue["message"] = $e->getMessage();
}
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retValue);
});
$app->delete('/ricetta/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback');
$retValue["result"] = true;
$retValue["message"] = "";
$mysqlconnetion = new MysqlClass;
try {
$queryDelete = "DELETE FROM immagini where id_ricette = " . $itemID;
$mysqlconnetion->executeQuery($queryDelete);
$queryDelete = "DELETE FROM blocco_note where ricetta_id = " . $itemID;
$mysqlconnetion->executeQuery($queryDelete);
$queryDelete = "DELETE FROM ingredienti where ID_RICETTE = " . $itemID;
$mysqlconnetion->executeQuery($queryDelete);
$queryDelete = "DELETE FROM ricette where ID = " . $itemID;
$mysqlconnetion->executeQuery($queryDelete);
$retValue["message"] = "Ricetta cancellata con successo";
} catch (Exception $e) {
$retValue["result"] = false;
$retValue["message"] = $e->getMessage(); $retValue["message"] = $e->getMessage();
} }
@@ -191,7 +164,7 @@ $app->get('/photos/', function () use ($app) {
$app->get('/ricetta/:itemID/photos', function ($itemID) use ($app) { $app->get('/ricetta/:itemID/photos', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
$query = "SELECT id as id_photo, type_format, from_profile_id, uploaded_date, profilo.Name as profile_name, published, bCover from immagini" . $query = "SELECT id as id_photo, type_format, from_profile_id, uploaded_date, profilo.Name as profile_name, published from immagini" .
" INNER JOIN profilo ON profilo.ProfiloID = immagini.from_profile_id". " INNER JOIN profilo ON profilo.ProfiloID = immagini.from_profile_id".
" WHERE id_ricette = " . $itemID; " WHERE id_ricette = " . $itemID;
@@ -201,51 +174,3 @@ $app->get('/ricetta/:itemID/photos', function ($itemID) use ($app) {
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj); returnJson($app, $callbackFn, $retObj);
}); });
$app->get('/statistics/gender', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$query = "SELECT 'Gender' as Type, IF(Gender='', 'Sconosciuto', Gender) as Serie, COUNT(gender) as CountSerie from profilo GROUP BY gender";
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/statistics/typeAccess', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$query = "SELECT 'TipoAccesso' as Type, TipoAccesso as Serie, COUNT(TipoAccesso) as CountSerie from profilo GROUP BY TipoAccesso";
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/statistics/themesUsage', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$query = "SELECT 'TemaUI' as Type, TemaUI as Serie, COUNT(TemaUI) as CountSerie from profilo GROUP BY TemaUI";
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/profiles', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$query = "SELECT ProfiloID as id, Name as name from profilo where name <> '' order by Name";
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
+53
View File
@@ -0,0 +1,53 @@
<?php
require_once "./myDropBoxObj.php";
use PHPImageWorkshop\ImageWorkshop;
require_once('./PHPImageWorkshop/ImageWorkshop.php'); // Be sure of the path to the class
date_default_timezone_set("Europe/Rome");
$dirRicetteDropBox = "IlLievitario/Images/Ricette";
$tmpFileName = "C:/Users/Denis/Desktop/Chiaravalle/Jpg/DSC_7731.jpg";
$ext = pathinfo($tmpFileName, PATHINFO_EXTENSION);
$idRicette = 5;
$newID = 125;
$imageFileName = $newID . "_full_ricetta." . $ext;
$thumbFileName = $newID . "_thumb_ricetta." . $ext;
$dropBoxObj = new myDropBox();
$folder = $dirRicetteDropBox . "/" . $idRicette;
/*
echo $dropBoxObj->GetLink($folder . "/" . $imageFileName);
return;
*/
$layer = ImageWorkshop::initFromPath($tmpFileName);
echo $layer->getImage()->image_type;
return;
$layer->resizeByLargestSideInPixel(640, true);
$layer->save(dirname($tmpFileName), $imageFileName);
$imgData = addslashes(file_get_contents($tmpFileName));
$layer->resizeByLargestSideInPixel(300, true);
$layer->save(dirname($tmpFileName), $thumbFileName);
try {
$dropBoxObj->CreateFolder($folder);
} catch (DropboxException $ex) {
}
$dropBoxObj->UploadFile(dirname($tmpFileName) . "/" . $imageFileName, $folder . "/" . $imageFileName);
$dropBoxObj->UploadFile(dirname($tmpFileName) . "/" . $thumbFileName, $folder . "/" . $thumbFileName);
+1 -9
View File
@@ -52,10 +52,7 @@ class myDropBox {
} }
public function GetLink($dropBoxPathFile) { public function GetLink($dropBoxPathFile) {
$exp = null; return $this->dropbox->GetLink($dropBoxPathFile, false, false);
$ret = $this->dropbox->GetLink($dropBoxPathFile, true, false, $exp);
$ret = str_replace("https://www.dropbox.com/", "https://dl.dropboxusercontent.com/" , $ret);
return $ret;
} }
public function CreateFolder($dropBoxPath) { public function CreateFolder($dropBoxPath) {
@@ -63,11 +60,6 @@ class myDropBox {
return true; return true;
} }
public function Delete($dropBoxPath) {
$ret = $this->dropbox->Delete($dropBoxPath);
return true;
}
private function store_token($token, $name) { private function store_token($token, $name) {
if (!file_put_contents("tokens/$name.token", serialize($token))) if (!file_put_contents("tokens/$name.token", serialize($token)))
die('<br />Could not store token! <b>Make sure that the directory `tokens` exists and is writable!</b>'); die('<br />Could not store token! <b>Make sure that the directory `tokens` exists and is writable!</b>');
-6
View File
@@ -1,6 +0,0 @@
copy.src.files=false
copy.src.on.open=false
copy.src.target=
index.file=
run.as=LOCAL
url=http://localhost:8081/Service_Manut/
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group/>
</open-files>
</project-private>
-7
View File
@@ -1,7 +0,0 @@
include.path=${php.global.include.path}
php.version=PHP_54
source.encoding=UTF-8
src.dir=.
tags.asp=false
tags.short=false
web.root=.
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.php.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/php-project/1">
<name>Service_Manut</name>
</data>
</configuration>
</project>
+19
View File
@@ -0,0 +1,19 @@
<?php
// inclusione del file contenente la classe
include "./MySqlClass.php";
include "./utility.php";
include "./ricette.php";
include "./profile.php";
include "./image.php";
/*
$img = imagecreatefrompng("https://www.google.it/images/srpr/chrome_ntp_white_logo2.png");
echo "caricato immagine";
importImage(28, $img, '10203753344023406');
*/
?>
<img src="<?php getThumbnailImage(11) ?>">
<img src="<?php getImage(11) ?>">
+55 -55
View File
@@ -7,9 +7,9 @@
$app->get('/profile/statusCache', function () use ($app) { $app->get('/profile/statusCache', function () use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query = "select 0 as ID_CATEGORIA, MAX(data_creazione) as LastDateModified from categorie" . $query = "select 0 as ID_CATEGORIA, MAX(Data_creazione) as LastDateModified from categorie" .
" UNION" . " UNION" .
" select ID_CATEGORIA, MAX(Data_modifica) as LastDateModified from ricette" . " select ID_CATEGORIA, MAX(Data_creazione) as LastDateModified from ricette" .
" GROUP BY ID_CATEGORIA"; " GROUP BY ID_CATEGORIA";
$retObj = $mysqlconnetion->queryToObject($query); $retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
@@ -36,6 +36,7 @@ $app->post('/profile/ricetta', function () use ($app) {
$query = "insert into blocco_note(ricetta_id, ProfiloID) values (" . $json_data_body->ricetta_id . ", '" . $json_data_body->keyStore . "')"; $query = "insert into blocco_note(ricetta_id, ProfiloID) values (" . $json_data_body->ricetta_id . ", '" . $json_data_body->keyStore . "')";
$retNewID = $mysqlconnetion->insertRecord($query); $retNewID = $mysqlconnetion->insertRecord($query);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retNewID); returnJson($app, $callbackFn, $retNewID);
}); });
@@ -81,73 +82,84 @@ $app->get('/profile/:keyStore/ricette', function ($keyStore) use ($app) {
$app->get('/profile/:keyStore', function ($keyStore) use ($app) { $app->get('/profile/:keyStore', function ($keyStore) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query = "SELECT ProfiloID,TipoAccesso,RisultatiRicerca,TemaUI,Name,Gender,0 AS NumRicette,BloccoNoteUpdated,Email,bSpacciatore,bPrivacy,Cap,Comune,Stato, Provincia,TipoPM,Note, Latitudine, Longitudine from profilo" . $query = "select ProfiloID, TipoAccesso, RisultatiRicerca, TemaUI, Name, Gender, 0 as NumRicette, BloccoNoteUpdated from profilo" .
" where ProfiloID = '" . $keyStore . "'"; " where ProfiloID = '" . $keyStore . "'";
$retObj = $mysqlconnetion->queryToObject($query); $retObj = $mysqlconnetion->queryToObject($query);
if($retObj != false) $query = "update profilo set PenultimoAccesso = UltimoAccesso, UltimoAccesso = NOW() where ProfiloID = '" . $keyStore . "'";
{ $mysqlconnetion->insertRecord($query);
$retObj[0]["Name"] = html_entity_decode($retObj[0]["Name"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$retObj[0]["Note"] = html_entity_decode($retObj[0]["Note"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$retObj[0]["Comune"] = html_entity_decode($retObj[0]["Comune"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$retObj[0]["Provincia"] = html_entity_decode($retObj[0]["Provincia"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$query = "update profilo set PenultimoAccesso = UltimoAccesso, UltimoAccesso = NOW() where ProfiloID = '" . $keyStore . "'"; $query = "SELECT COUNT( * ) as NumNotifiche" .
$mysqlconnetion->insertRecord($query); " FROM notifiche" .
" inner join conferma_lettura_profilo on notifiche.id = conferma_lettura_profilo.id_notifica" .
" where conferma_lettura_profilo.id_profilo = '" . $keyStore . "' and notifiche.Type = 1 ".
" AND conferma_lettura_profilo.conferma_lettura = 0";
$query = "SELECT COUNT( * ) as NumRicette FROM ricette WHERE data_creazione > ( SELECT PenultimoAccesso FROM profilo " . $retObj2 = $mysqlconnetion->queryToObject($query);
"WHERE `ProfiloID` = '" . $keyStore . "' )";
$retObj2 = $mysqlconnetion->queryToObject($query); $retObj[0]["NumNotifiche"] = $retObj2[0]["NumNotifiche"];
$query = "SELECT COUNT( * ) as NumLastRicette ".
" FROM notifiche" .
" inner join conferma_lettura_profilo on notifiche.id = conferma_lettura_profilo.id_notifica" .
" where conferma_lettura_profilo.id_profilo = '" . $keyStore . "' and notifiche.Type = 2" .
" AND conferma_lettura_profilo.conferma_lettura = 0" .
" ORDER BY CreatoIl desc" .
" LIMIT 1";
$retObj3 = $mysqlconnetion->queryToObject($query);
$retObj[0]["NumLastRicette"] = $retObj3[0]["NumLastRicette"];
$retObj[0]["NumRicette"] = $retObj2[0]["NumRicette"];
}
returnJson($app, $callbackFn, $retObj); returnJson($app, $callbackFn, $retObj);
}); });
$app->get('/profile/province(/:iniz)', function ($iniz = "") use ($app) { $app->get('/profile/:keyStore/notification/:id', function ($keyStore, $idNotification) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$where= "";
if($iniz!="")
$where = "WHERE Provincia like '" . $iniz . "%' ";
$query = "select DISTINCT Provincia from comuni " . $where . "ORDER BY Provincia";
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
foreach ($retObj as $ele) { $query = "SELECT id, titolo, descrizione, type" .
if($ele["Provincia"]!=null) " FROM notifiche" .
$ele["Provincia"] = html_entity_decode($ele["Provincia"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); " where id = " . $idNotification;
}
$retObj = $mysqlconnetion->queryToObject($query);
$query = "UPDATE conferma_lettura_profilo SET conferma_lettura = 1 WHERE id_notifica = " . $idNotification .
" AND id_profilo = '" . $keyStore . "'";
$retNewID = $mysqlconnetion->insertRecord($query);
returnJson($app, $callbackFn, $retObj); returnJson($app, $callbackFn, $retObj);
}); });
$app->get('/profile/comuni/:prov(/:iniz)', function ($prov ,$iniz = "") use ($app) { $app->get('/profile/:keyStore/notifications', function ($keyStore) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$where= "";
if($iniz!="")
$where = "AND Comune like '" . $iniz . "%' ";
$query = "select Comune, CAP from comuni where Provincia = '" . $prov . "' " . $where . "ORDER BY Comune";
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
foreach ($retObj as $ele) { $query = "SELECT id, titolo, type, CreatoIl, conferma_lettura_profilo.conferma_lettura" .
if($ele["Comune"]!=null) " FROM notifiche" .
$ele["Comune"] = html_entity_decode($ele["Comune"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); " inner join conferma_lettura_profilo on notifiche.id = conferma_lettura_profilo.id_notifica" .
} " where conferma_lettura_profilo.id_profilo = '" . $keyStore . "' and notifiche.Type = 1" .
" UNION" .
" (SELECT id, titolo, type, CreatoIl, conferma_lettura_profilo.conferma_lettura" .
" FROM notifiche" .
" inner join conferma_lettura_profilo on notifiche.id = conferma_lettura_profilo.id_notifica" .
" where conferma_lettura_profilo.id_profilo = '" . $keyStore . "' and notifiche.Type = 2" .
" ORDER BY CreatoIl desc" .
" LIMIT 1" .
" )" .
" ORDER BY CreatoIl desc";
$retObj = $mysqlconnetion->queryToObject($query);
returnJson($app, $callbackFn, $retObj); returnJson($app, $callbackFn, $retObj);
}); });
$app->post('/profile', function () use ($app) { $app->post('/profile', function () use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
$json_data_body = json_decode($app->request()->post('dataPair')); $json_data_body = json_decode($app->request()->post('dataPair'));
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query = "insert into profilo(ProfiloID, Name, Email, Gender, TipoAccesso, RisultatiRicerca, TemaUI, UltimoAccesso, CreatoIl) values ('" . $query = "insert into profilo(ProfiloID, Name, Email, Gender, TipoAccesso, RisultatiRicerca, TemaUI, UltimoAccesso, CreatoIl) values ('" . $json_data_body->keyStore . "', '" . $json_data_body->name . "', '" . $json_data_body->email . "', '" . $json_data_body->gender . "', '" . $json_data_body->type . "', '" . $json_data_body->risRic . "', '" . $json_data_body->tema . "', NOW(), NOW())";
$json_data_body->keyStore . "', '" . str_replace("'", "''", htmlentities($json_data_body->name, null, "UTF-8")) . "', '" . $json_data_body->email . "', '" . $json_data_body->gender . "', '" . $json_data_body->type . "', '" . $json_data_body->risRic . "', '" . $json_data_body->tema . "', NOW(), NOW())";
$retNewID = $mysqlconnetion->insertRecord($query); $retNewID = $mysqlconnetion->insertRecord($query);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
@@ -159,20 +171,8 @@ $app->put('/profile', function () use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $app->request()->get('callback');
$json_data_body = json_decode($app->request()->post('dataPair')); $json_data_body = json_decode($app->request()->post('dataPair'));
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query = "update profilo set RisultatiRicerca = '" . $json_data_body->risRic . $query = "update profilo set RisultatiRicerca = '" . $json_data_body->risRic . "', TemaUI = '" . $json_data_body->tema . "' where ProfiloID = '" . $json_data_body->keyStore . "'";
"', TemaUI = '" . $json_data_body->tema .
"', Email = '" . $json_data_body->email .
"', bSpacciatore = " . $json_data_body->isSpacc .
", bPrivacy = " . $json_data_body->privacy .
", Cap = '" . $json_data_body->cap .
"', Stato = '" . $json_data_body->stato .
"', Comune = '" . htmlentities($json_data_body->comune, null, "UTF-8") .
"', Provincia = '" . htmlentities($json_data_body->prov, null, "UTF-8") .
"', Note = '" . htmlentities($json_data_body->note, null, "UTF-8") .
"', TipoPM = " . $json_data_body->tipopm .
", Latitudine = " . $json_data_body->lat .
", Longitudine = " . $json_data_body->lng .
" where ProfiloID = '" . $json_data_body->keyStore . "'";
$retNewID = $mysqlconnetion->insertRecord($query); $retNewID = $mysqlconnetion->insertRecord($query);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
+69 -65
View File
@@ -3,62 +3,42 @@
// inclusione del file contenente la classe // inclusione del file contenente la classe
require_once "./include.php"; require_once "./include.php";
$app->get('/categories', function () use ($app) { $app->get('/categories', function ($request, $response, $args) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconneti on->connetti(); //$mysqlconneti on->connetti();
$retObj = $mysqlconnetion->queryToObject("select ID as category_id, NAME as name from categorie order by name"); $retObj = $mysqlconnetion->queryToObject("select ID as category_id, NAME as name from categorie order by name");
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/typeingredients', function () use ($app) { $app->get('/typeingredients', function ($request, $response, $args) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti(); //$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject("select ID as tipo_ingredienti_id, name from tipo_ingredienti order by name"); $retObj = $mysqlconnetion->queryToObject("select ID as tipo_ingredienti_id, name from tipo_ingredienti order by name");
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/typeqtys', function () use ($app) { $app->get('/typeqtys', function ($request, $response, $args) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti(); //$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject("select ID as tipo_quantita_id, name from tipo_quantita"); $retObj = $mysqlconnetion->queryToObject("select ID as tipo_quantita_id, name from tipo_quantita");
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/ricette/authors(/:startWith)', function ($startWith = "") use ($app) { $app->get('/ricette/{catID}', function ($request, $response, $args) {
$callbackFn = $app->request()->get('callback'); $categoryID = $args["catID"];
$mysqlconnetion = new MysqlClass; $callbackFn = $req->getQueryParams()['callback'];
$query = "select distinct autore from ricette"
. " where 1 = 1";
if ($startWith != null && $startWith != "") {
$query = $query . " AND autore like '%" . $startWith . "%'";
}
$query = $query . " order by autore";
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/ricette/:catID', function ($categoryID) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti(); //$mysqlconnetion->connetti();
$query = "select * from (select ID as ricetta_id, titolo, autore, valutazione, difficolta, " . $query = "select ID as ricetta_id, titolo, autore, valutazione, difficolta from ricette where ID_CATEGORIA = " . $categoryID . " order by titolo, autore";
"(select id from immagini where immagini.id_ricette = ricette.id and bCover = 1) as firstImage, " .
"(select count(id) from immagini where immagini.id_ricette = ricette.id) as countImages " .
"from ricette where ricette.ID_CATEGORIA = " . $categoryID . " order by titolo, autore) as TMP";
$retObj = $mysqlconnetion->queryToObject($query); $retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
@@ -66,11 +46,13 @@ $app->get('/ricette/:catID', function ($categoryID) use ($app) {
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); $ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
} }
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/ricette/:categoryID/mostvote(/:numItems)', function ($categoryID, $numItems = 10) use ($app) { $app->get('/ricette/{categoryID}/mostvote[/{numItems}]', function ($request, $response, $args) {
$callbackFn = $app->request()->get('callback'); $categoryID = $args["categoryID"];
$numItems = $args["numItems"];
$callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti(); //$mysqlconnetion->connetti();
$query = "select ID as ricetta_id, titolo, autore from ricette where ID_CATEGORIA = " . $categoryID . " order by Valutazione desc, titolo, autore LIMIT " . $numItems; $query = "select ID as ricetta_id, titolo, autore from ricette where ID_CATEGORIA = " . $categoryID . " order by Valutazione desc, titolo, autore LIMIT " . $numItems;
@@ -81,11 +63,11 @@ $app->get('/ricette/:categoryID/mostvote(/:numItems)', function ($categoryID, $n
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); $ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
} }
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/ricette/:categoryID/lastinserted(/:numItems)', function ($categoryID, $numItems = 10) use ($app) { $app->get('/ricette/:categoryID/lastinserted(/:numItems)', function ($categoryID, $numItems = 10) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti(); //$mysqlconnetion->connetti();
$query = "select ID as ricetta_id, titolo, autore from ricette where ID_CATEGORIA = " . $categoryID . " order by Data_creazione desc, titolo, autore LIMIT " . $numItems; $query = "select ID as ricetta_id, titolo, autore from ricette where ID_CATEGORIA = " . $categoryID . " order by Data_creazione desc, titolo, autore LIMIT " . $numItems;
@@ -96,12 +78,28 @@ $app->get('/ricette/:categoryID/lastinserted(/:numItems)', function ($categoryID
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); $ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
} }
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/ricette/search/:numItems/:startItem(/:categoryId(/:difficolta/:autore(/:titolo)))', $app->get('/ricette/lastinserted/:profileID', function ($profileID) use ($app) {
function ($numItems = 10, $startItem = 0, $categoryId = 0, $difficolta = 0,$autore="_", $titolo = "") use ($app) { $callbackFn = $req->getQueryParams()['callback'];
$callbackFn = $app->request()->get('callback'); $mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$query = "select ID as ricetta_id, titolo, autore FROM ricette WHERE data_creazione > ( SELECT PenultimoAccesso FROM profilo " .
"WHERE `ProfiloID` = '" . $profileID . "' ) order by Data_creazione desc, titolo, autore";
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
foreach ($retObj as $ele) {
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
}
return returnJson($response, $callbackFn, $retObj);
});
$app->get('/ricette/search/:numItems/:startItem(/:categoryId(/:difficolta(/:titolo)))',
function ($numItems = 10, $startItem = 0, $categoryId = 0, $difficolta = 0, $titolo = "") use ($app) {
$callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$queryBase = " from ricette" $queryBase = " from ricette"
. " INNER JOIN categorie ON categorie.ID = ricette.id_categoria" . " INNER JOIN categorie ON categorie.ID = ricette.id_categoria"
@@ -109,10 +107,6 @@ $app->get('/ricette/search/:numItems/:startItem(/:categoryId(/:difficolta/:autor
if ($categoryId > 0) { if ($categoryId > 0) {
$queryBase = $queryBase . " AND ID_CATEGORIA = " . $categoryId; $queryBase = $queryBase . " AND ID_CATEGORIA = " . $categoryId;
} }
if ($autore != null && $autore != "_") {
foreach (explode(" ", htmlentities(urldecode($autore))) as $ele)
$queryBase = $queryBase . " AND autore like '%" . urldecode($ele) . "%'";
}
if ($titolo != null && $titolo != "") { if ($titolo != null && $titolo != "") {
foreach (explode(" ", htmlentities(urldecode($titolo))) as $ele) foreach (explode(" ", htmlentities(urldecode($titolo))) as $ele)
$queryBase = $queryBase . " AND titolo like '%" . $ele . "%'"; $queryBase = $queryBase . " AND titolo like '%" . $ele . "%'";
@@ -122,11 +116,7 @@ $app->get('/ricette/search/:numItems/:startItem(/:categoryId(/:difficolta/:autor
} }
$queryBase = $queryBase . " order by titolo, autore"; $queryBase = $queryBase . " order by titolo, autore";
$query = "select * from (select ricette.ID as ricetta_id, categorie.name AS categoria_name, titolo, autore, valutazione, difficolta, " . $query = "select ricette.ID as ricetta_id, categorie.name AS categoria_name, titolo, autore, valutazione, difficolta" . $queryBase . " LIMIT " . $numItems * $startItem . " , " . $numItems;
"(select id from immagini where immagini.id_ricette = ricette.id and bCover = 1) as firstImage, " .
"(select count(id) from immagini where immagini.id_ricette = ricette.id) as countImages" .
$queryBase . " LIMIT " . $numItems * $startItem . " , " . $numItems . ") as TMP";
$retObj2 = $mysqlconnetion->queryToObject($query); $retObj2 = $mysqlconnetion->queryToObject($query);
$query = "select COUNT(*) as TotalRecords" . $queryBase; $query = "select COUNT(*) as TotalRecords" . $queryBase;
@@ -139,11 +129,30 @@ $app->get('/ricette/search/:numItems/:startItem(/:categoryId(/:difficolta/:autor
} }
$retObj["records"] = $retObj2; $retObj["records"] = $retObj2;
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
});
$app->get('/ricette/authors(/:startWith)',
function ($startWith = "") use ($app) {
$callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass;
$query = "select distinct autore from ricette"
. " where 1 = 1";
if ($startWith != null && $startWith != "") {
$query = $query . " AND autore like '%" . $startWith . "%'";
}
$query = $query . " order by autore";
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/ricetta/body/:itemID', function ($itemID) use ($app) { $app->get('/ricetta/body/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query = "UPDATE ricette Set valutazione = valutazione + 1 WHERE ricette.ID = " . $itemID; $query = "UPDATE ricette Set valutazione = valutazione + 1 WHERE ricette.ID = " . $itemID;
@@ -159,7 +168,7 @@ $app->get('/ricetta/body/:itemID', function ($itemID) use ($app) {
$retObj2 = $mysqlconnetion->queryToObject($query2); $retObj2 = $mysqlconnetion->queryToObject($query2);
foreach ($retObj2 as $ele) { foreach ($retObj2 as $ele) {
$ele["note"] = html_entity_decode($ele["note"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); $ele["note"] = html_entity_decode($ele["note"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
} }
@@ -169,24 +178,19 @@ $app->get('/ricetta/body/:itemID', function ($itemID) use ($app) {
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/ricetta/header/:itemID', function ($itemID) use ($app) { $app->get('/ricetta/header/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query = "UPDATE ricette Set valutazione = valutazione + 1 WHERE ricette.ID = " . $itemID; $query = "UPDATE ricette Set valutazione = valutazione + 1 WHERE ricette.ID = " . $itemID;
$mysqlconnetion->executeQuery($query); $mysqlconnetion->executeQuery($query);
$query = "SELECT ID from immagini WHERE published = 1 AND ID_RICETTE = " . $itemID; $query = "SELECT id_categoria, categorie.name AS categoria_name, ricette.ID AS ricetta_id, titolo, procedimento, autore, link_fonte, link_youtube, valutazione FROM ricette INNER JOIN categorie ON categorie.ID = ricette.id_categoria WHERE ricette.ID = " . $itemID;
$photos = $mysqlconnetion->queryToObject($query);
$query = "SELECT id_categoria, categorie.name AS categoria_name, ricette.ID AS ricetta_id, " .
"titolo, procedimento, autore, link_fonte, link_youtube, valutazione FROM ricette " .
"INNER JOIN categorie ON categorie.ID = ricette.id_categoria WHERE ricette.ID = " . $itemID;
$retObj = $mysqlconnetion->queryToObject($query); $retObj = $mysqlconnetion->queryToObject($query);
$retObj[0]["titolo"] = html_entity_decode($retObj[0]["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); $retObj[0]["titolo"] = html_entity_decode($retObj[0]["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$retObj[0]["procedimento"] = html_entity_decode($retObj[0]["procedimento"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); $retObj[0]["procedimento"] = html_entity_decode($retObj[0]["procedimento"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$data = $retObj[0]["link_youtube"]; $data = $retObj[0]["link_youtube"];
$retObj[0]["foto"] = $photos;
$output = array(); $output = array();
if ($data != "") { if ($data != "") {
$d = explode(";", $data); $d = explode(";", $data);
@@ -199,11 +203,11 @@ $app->get('/ricetta/header/:itemID', function ($itemID) use ($app) {
} }
$retObj[0]["link_youtube"] = $output; $retObj[0]["link_youtube"] = $output;
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj); return returnJson($response, $callbackFn, $retObj);
}); });
$app->get('/ricetta/ingredienti/:itemID', function ($itemID) use ($app) { $app->get('/ricetta/ingredienti/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback'); $callbackFn = $req->getQueryParams()['callback'];
$mysqlconnetion = new MysqlClass; $mysqlconnetion = new MysqlClass;
$query2 = "select ingredienti.id_tipo_ingredienti, tipo_ingredienti.name as nome_ingrediente, quantita, ingredienti.id_tipo_quantita, tipo_quantita.Name as unita, note, posizione from ingredienti " . $query2 = "select ingredienti.id_tipo_ingredienti, tipo_ingredienti.name as nome_ingrediente, quantita, ingredienti.id_tipo_quantita, tipo_quantita.Name as unita, note, posizione from ingredienti " .
"inner join tipo_ingredienti on ingredienti.ID_TIPO_INGREDIENTI = tipo_ingredienti.ID " . "inner join tipo_ingredienti on ingredienti.ID_TIPO_INGREDIENTI = tipo_ingredienti.ID " .
@@ -218,6 +222,6 @@ $app->get('/ricetta/ingredienti/:itemID', function ($itemID) use ($app) {
$mysqlconnetion->disconnetti(); $mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj2); return returnJson($response, $callbackFn, $retObj2);
}); });
?> ?>
+2 -4
View File
@@ -2,17 +2,15 @@
include_once "./include.php"; include_once "./include.php";
$app->group('/api', function () use ($app, $dirRicetteDropBox) { $app->group('/api', function () {
include "./ricette.php"; include "./ricette.php";
include "./profile.php"; include "./profile.php";
include "./image.php"; include "./image.php";
include "./spacciatoripm.php";
}); });
$app->group('/backend', function () use ($app, $dirRicetteDropBox) { $app->group('/backend', function () {
include "./management.php"; include "./management.php";
include "./image_backend.php"; include "./image_backend.php";
}); });
//include "./image.php";
$app->run(); $app->run();
-109
View File
@@ -1,109 +0,0 @@
<?php
$app->get('/spacciatori/kml', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
$query = "SELECT ProfiloID, Name, Email, CONCAT(Comune, ', ', Cap, ' - ', Provincia) as Indirizzo, Latitudine, Longitudine, TipoPM FROM `profilo` where bSpacciatore = 1";
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
// Creates the Document.
$dom = new DOMDocument('1.0', 'UTF-8');
// Creates the root KML element and appends it to the root document.
$node = $dom->createElementNS('http://earth.google.com/kml/2.1', 'kml');
$parNode = $dom->appendChild($node);
// Creates a KML Document element and append it to the KML element.
$dnode = $dom->createElement('Document');
$docNode = $parNode->appendChild($dnode);
// Creates the two Style elements, one for restaurant and one for bar, and append the elements to the Document element.
$restStyleNode = $dom->createElement('Style');
$restStyleNode->setAttribute('id', '1');
$restIconstyleNode = $dom->createElement('IconStyle');
$restIconstyleNode->setAttribute('id', 'restaurantIcon');
$restIconNode = $dom->createElement('Icon');
$restHref = $dom->createElement('href', 'http://maps.google.com/mapfiles/kml/pal2/icon63.png');
$restIconNode->appendChild($restHref);
$restIconstyleNode->appendChild($restIconNode);
$restStyleNode->appendChild($restIconstyleNode);
$docNode->appendChild($restStyleNode);
$barStyleNode = $dom->createElement('Style');
$barStyleNode->setAttribute('id', '2');
$barIconstyleNode = $dom->createElement('IconStyle');
$barIconstyleNode->setAttribute('id', 'barIcon');
$barIconNode = $dom->createElement('Icon');
$barHref = $dom->createElement('href', 'http://maps.google.com/mapfiles/kml/pal2/icon27.png');
$barIconNode->appendChild($barHref);
$barIconstyleNode->appendChild($barIconNode);
$barStyleNode->appendChild($barIconstyleNode);
$docNode->appendChild($barStyleNode);
// Iterates through the MySQL results, creating one Placemark for each row.
foreach ($retObj as $row)
{
// Creates a Placemark and append it to the Document.
$node = $dom->createElement('Placemark');
$placeNode = $docNode->appendChild($node);
// Creates an id attribute and assign it the value of id column.
$placeNode->setAttribute('id', 'placemark_' . $row['ProfiloID']);
// Create name, and description elements and assigns them the values of the name and address columns from the results.
$nameNode = $dom->createElement('name',htmlentities($row['Name']));
$placeNode->appendChild($nameNode);
$descNode = $dom->createElement('description', $row['Indirizzo'] . '<br>Contatta: ' . $row['Email']);
$placeNode->appendChild($descNode);
$styleUrl = $dom->createElement('styleUrl', '#' . $row['TipoPM']);
$placeNode->appendChild($styleUrl);
// Creates a Point element.
$pointNode = $dom->createElement('Point');
$placeNode->appendChild($pointNode);
// Creates a coordinates element and gives it the value of the lng and lat columns from the results.
$coorStr = $row['Longitudine'] . ',' . $row['Latitudine'];
$coorNode = $dom->createElement('coordinates', $coorStr);
$pointNode->appendChild($coorNode);
}
$kmlOutput = $dom->saveXML();
header('Content-type: application/vnd.google-earth.kml+xml');
echo $kmlOutput;
});
$app->get('/spacciatori/bound/:FromLat/:FromLng/:ToLat/:ToLng', function ($FromLat, $FromLng, $ToLat, $ToLng) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
$query = "SELECT ProfiloID as ID, Name, Email, Comune, Cap, Provincia, Note, \"\" as Indirizzo, Latitudine, Longitudine, TipoPM FROM profilo " .
"where bSpacciatore = 1 AND ";
if($ToLat < $FromLat)
$query = $query . "Latitudine BETWEEN " . $ToLat . " AND " . $FromLat . " AND ";
else
$query = $query . "Latitudine BETWEEN " . $FromLat . " AND " . $ToLat . " AND ";
if($ToLng < $FromLng)
$query = $query . "Longitudine BETWEEN " . $ToLng . " AND " . $FromLng;
else
$query = $query . "Longitudine BETWEEN " . $FromLng . " AND " . $ToLng;
$retObj = $mysqlconnetion->queryToObject($query);
foreach ($retObj as $ele) {
if($ele["Name"]!=null)
$ele["Name"] = html_entity_decode($ele["Name"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
if($ele["Note"]!=null)
$ele["Note"] = html_entity_decode($ele["Note"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
if($ele["Comune"]!=null)
$ele["Comune"] = html_entity_decode($ele["Comune"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
if($ele["Provincia"]!=null)
$ele["Provincia"] = html_entity_decode($ele["Provincia"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$ele["Indirizzo"] = $ele["Comune"] . ", " . $ele["Cap"] . ", " . $ele["Provincia"];
}
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
-178
View File
@@ -1,178 +0,0 @@
<?php
// inclusione del file contenente la classe
require_once "./include.php";
$app->get('/categories', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
//$mysqlconneti on->connetti();
$retObj = $mysqlconnetion->queryToObject("select ID as category_id, NAME as name from categorie order by name");
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/typeingredients', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject("select ID as tipo_ingredienti_id, name from tipo_ingredienti order by name");
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/typeqtys', function () use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$retObj = $mysqlconnetion->queryToObject("select ID as tipo_quantita_id, name from tipo_quantita");
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/categoryitems/:catID', function ($categoryID) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$query = "select ID as ricetta_id, titolo, autore, valutazione, difficolta from ricette where ID_CATEGORIA = " . $categoryID . " order by titolo, autore";
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
foreach ($retObj as $ele) {
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
}
returnJson($app, $callbackFn, $retObj);
});
$app->get('/categoryitems/:categoryID/mostvote(/:numItems)', function ($categoryID, $numItems = 10) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$query = "select ID as ricetta_id, titolo, autore from ricette where ID_CATEGORIA = " . $categoryID . " order by Valutazione desc, titolo, autore LIMIT " . $numItems;
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
foreach ($retObj as $ele) {
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
}
returnJson($app, $callbackFn, $retObj);
});
$app->get('/categoryitems/:categoryID/lastinserted(/:numItems)', function ($categoryID, $numItems = 10) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
//$mysqlconnetion->connetti();
$query = "select ID as ricetta_id, titolo, autore from ricette where ID_CATEGORIA = " . $categoryID . " order by Data_creazione desc, titolo, autore LIMIT " . $numItems;
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
foreach ($retObj as $ele) {
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
}
returnJson($app, $callbackFn, $retObj);
});
$app->get('/categoryitems/search/:numItems(/:categoryId(/:difficolta(/:titolo)))',
function ($numItems = 10, $categoryId = 0, $difficolta = 0, $titolo = "") use ($app) {
$callbackFn = $app->request()->get('callback');
//$filterItem = json_decode($app->request()->post('post'));
$mysqlconnetion = new MysqlClass;
$query = "select ricette.ID as ricetta_id, categorie.name AS categoria_name, titolo, autore, valutazione, difficolta from ricette"
. " INNER JOIN categorie ON categorie.ID = ricette.id_categoria"
. " where 1 = 1";
if ($categoryId > 0) {
$query = $query . " AND ID_CATEGORIA = " . $categoryId;
}
if ($titolo != null && $titolo != "") {
foreach (explode(" ", htmlentities(urldecode($titolo))) as $ele)
$query = $query . " AND titolo like '%" . $ele . "%'";
}
if ($difficolta > 0) {
$query = $query . " AND difficolta = " . $difficolta;
}
$query = $query . " order by titolo, autore LIMIT " . $numItems;
$retObj = $mysqlconnetion->queryToObject($query);
$mysqlconnetion->disconnetti();
foreach ($retObj as $ele) {
$ele["titolo"] = html_entity_decode($ele["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
}
returnJson($app, $callbackFn, $retObj);
});
$app->get('/ricetta/body/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
$query = "UPDATE ricette Set valutazione = valutazione + 1 WHERE ricette.ID = " . $itemID;
$mysqlconnetion->executeQuery($query);
$query = "SELECT id_categoria, categorie.name AS categoria_name, ricette.ID AS ricetta_id, titolo, procedimento, autore, link_fonte, link_youtube, valutazione FROM ricette INNER JOIN categorie ON categorie.ID = ricette.id_categoria WHERE ricette.ID = " . $itemID;
$retObj = $mysqlconnetion->queryToObject($query);
$query2 = "select ingredienti.id_tipo_ingredienti, tipo_ingredienti.name as nome_ingrediente, quantita, ingredienti.id_tipo_quantita, tipo_quantita.Name as unita, note, posizione from ingredienti " .
"inner join tipo_ingredienti on ingredienti.ID_TIPO_INGREDIENTI = tipo_ingredienti.ID " .
"left outer join tipo_quantita on ingredienti.ID_TIPO_QUANTITA = tipo_quantita.ID " .
"where ingredienti.ID_RICETTE = " . $itemID . " order by ingredienti.posizione";
$retObj2 = $mysqlconnetion->queryToObject($query2);
$retObj[0]["titolo"] = html_entity_decode($retObj[0]["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$retObj[0]["procedimento"] = html_entity_decode($retObj[0]["procedimento"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$retObj[0]["ingredienti"] = $retObj2;
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/ricetta/header/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
$query = "UPDATE ricette Set valutazione = valutazione + 1 WHERE ricette.ID = " . $itemID;
$mysqlconnetion->executeQuery($query);
$query = "SELECT id_categoria, categorie.name AS categoria_name, ricette.ID AS ricetta_id, titolo, procedimento, autore, link_fonte, link_youtube, valutazione FROM ricette INNER JOIN categorie ON categorie.ID = ricette.id_categoria WHERE ricette.ID = " . $itemID;
$retObj = $mysqlconnetion->queryToObject($query);
$retObj[0]["titolo"] = html_entity_decode($retObj[0]["titolo"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$retObj[0]["procedimento"] = html_entity_decode($retObj[0]["procedimento"], ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
$data = $retObj[0]["link_youtube"];
$output = array();
if ($data != "") {
$d = explode(";", $data);
$index = 0;
foreach ($d as $ele) {
$obj["VideoID"] = $ele;
$output[$index] = $obj;
$index++;
}
}
$retObj[0]["link_youtube"] = $output;
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj);
});
$app->get('/ricetta/ingredienti/:itemID', function ($itemID) use ($app) {
$callbackFn = $app->request()->get('callback');
$mysqlconnetion = new MysqlClass;
$query2 = "select ingredienti.id_tipo_ingredienti, tipo_ingredienti.name as nome_ingrediente, quantita, ingredienti.id_tipo_quantita, tipo_quantita.Name as unita, note, posizione from ingredienti " .
"inner join tipo_ingredienti on ingredienti.ID_TIPO_INGREDIENTI = tipo_ingredienti.ID " .
"left outer join tipo_quantita on ingredienti.ID_TIPO_QUANTITA = tipo_quantita.ID " .
"where ingredienti.ID_RICETTE = " . $itemID . " order by ingredienti.posizione";
$retObj2 = $mysqlconnetion->queryToObject($query2);
//$retObj[0]["titolo"] = html_entity_decode($retObj[0]["titolo"]);
//$retObj[0]["procedimento"] = html_entity_decode($retObj[0]["procedimento"]);
//$retObj[0]["ingredienti"] = $retObj2;
$mysqlconnetion->disconnetti();
returnJson($app, $callbackFn, $retObj2);
});
?>
+24 -31
View File
@@ -40,24 +40,38 @@ function utf8json($inArray) {
return $inArray; return $inArray;
} }
function returnJsonWithDecode($app, $callbackFn, $retObj) { function returnJsonWithDecode($response, $callbackFn, $retObj) {
$contentType = "";
$body = "";
if ($callbackFn) { if ($callbackFn) {
$app->contentType('application/javascript; Charset=UTF-8'); $contentType = 'application/javascript; Charset=UTF-8';
echo $callbackFn . "(" . html_entity_decode(json_encode(utf8json($retObj)), ENT_COMPAT | ENT_HTML401, 'ISO-8859-1') . ")"; $body = $callbackFn . "(" . html_entity_decode(json_encode(utf8json($retObj)), ENT_COMPAT | ENT_HTML401, 'ISO-8859-1') . ")";
} else { } else {
$app->contentType('application/x-json; Charset=UTF-8'); $contentType = 'application/x-json; Charset=UTF-8';
echo html_entity_decode(json_encode(utf8json($retObj)), ENT_COMPAT | ENT_HTML401, 'ISO-8859-1'); $body = html_entity_decode(json_encode(utf8json($retObj)), ENT_COMPAT | ENT_HTML401, 'ISO-8859-1');
} }
return $response->withHeader(
'Content-Type',
'application/json'
)->write($body);
} }
function returnJson($app, $callbackFn, $retObj) { function returnJson($response, $callbackFn, $retObj) {
$contentType = "";
$body = "";
if ($callbackFn) { if ($callbackFn) {
$app->contentType('application/javascript; Charset=UTF-8'); $contentType = 'application/javascript; Charset=UTF-8';
echo $callbackFn . "(" . (json_encode(utf8json($retObj))) . ")"; $body = $callbackFn . "(" . (json_encode(utf8json($retObj))) . ")";
} else { } else {
$app->contentType('application/x-json; Charset=UTF-8'); $contentType = 'application/x-json; Charset=UTF-8';
echo (json_encode(utf8json($retObj))); $body = (json_encode(utf8json($retObj)));
} }
return $response->withHeader(
'Content-Type',
'application/json'
)->write($body);
} }
function makeThumbnail($im) { function makeThumbnail($im) {
@@ -96,27 +110,6 @@ function resizeImage($dropBoxObj, $layer, $size, $dir, $fileName, $dirDropBox)
} }
$dropBoxObj->UploadFile($fullPath, $dirDropBox . "/" . $fileName); $dropBoxObj->UploadFile($fullPath, $dirDropBox . "/" . $fileName);
return $dropBoxObj->GetLink($dirDropBox . "/" . $fileName);
} }
function makeThumbImage($dropBoxObj, $layer, $size, $dir, $fileName, $dirDropBox)
{
$fileName = str_replace(".jpg", ".png", $fileName);
$fileName = str_replace(".jpeg", ".png", $fileName);
$fullPath = $dir . "/" . $fileName;
$layer->resizeInPixel($size, $size, true, 0, 0, 'MM');
$layer->save($dir, $fileName);
try {
$dropBoxObj->CreateFolder($dirDropBox);
} catch (DropboxException $ex) {
}
$dropBoxObj->UploadFile($fullPath, $dirDropBox . "/" . $fileName);
return $dropBoxObj->GetLink($dirDropBox . "/" . $fileName);
}
?> ?>