add external files for Routes (Espo/routes.json, Espo/Modules/Crm/routes.json)
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
class App extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
public function actionUser()
|
||||
{
|
||||
return '{"user":{"modified_by_name":"Administrator","created_by_name":"","id":"1","user_name":"admin","user_hash":"","system_generated_password":"0","pwd_last_changed":"","authenticate_id":"","sugar_login":"1","first_name":"","last_name":"Administrator","full_name":"Administrator","name":"Administrator","is_admin":"1","external_auth_only":"0","receive_notifications":"1","description":"","date_entered":"2013-06-13 12:18:44","date_modified":"2013-06-13 12:19:48","modified_user_id":"1","created_by":"","title":"Administrator","department":"","phone_home":"","phone_mobile":"","phone_work":"","phone_other":"","phone_fax":"","status":"Active","address_street":"","address_city":"","address_state":"","address_country":"","address_postalcode":"","UserType":"","deleted":"0","portal_only":"0","show_on_employees":"1","employee_status":"Active","messenger_id":"","messenger_type":"","reports_to_id":"","reports_to_name":"","email1":"test@letrium.com","email_link_type":"","is_group":"0","c_accept_status_fields":" ","m_accept_status_fields":" ","accept_status_id":"","accept_status_name":""},"preferences":{}}';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -4,5 +4,6 @@ namespace Espo\Controllers;
|
||||
|
||||
class User extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -90,18 +90,10 @@ class Application
|
||||
$auth = new \Espo\Core\Utils\Api\Auth($container->get('entityManager'), $container);
|
||||
$this->getSlim()->add($auth);
|
||||
|
||||
$this->getSlim()->hook('slim.before.dispatch', function () use ($slim, $container) {
|
||||
$conditions = $slim->router()->getCurrentRoute()->getConditions();
|
||||
$routeParams = $slim->router()->getCurrentRoute()->getParams();
|
||||
if (!empty($routeParams)) {
|
||||
$slim->router()->getCurrentRoute()->setParams($routeParams);
|
||||
}
|
||||
});
|
||||
|
||||
$this->getSlim()->hook('slim.before.dispatch', function () use ($slim, $container, $serviceFactory) {
|
||||
|
||||
$route = $slim->router()->getCurrentRoute();
|
||||
$conditions = $route->getConditions();
|
||||
$conditions = $route->getConditions();
|
||||
|
||||
if (isset($conditions['useController']) && $conditions['useController'] == false) {
|
||||
return;
|
||||
@@ -123,7 +115,7 @@ class Application
|
||||
$value = $params[$paramName];
|
||||
}
|
||||
$controllerParams[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$controllerName = ucfirst($controllerParams['controller']);
|
||||
|
||||
@@ -135,7 +127,7 @@ class Application
|
||||
}
|
||||
|
||||
try {
|
||||
$controllerManager = new \Espo\Core\ControllerManager($container, $serviceFactory);
|
||||
$controllerManager = new \Espo\Core\ControllerManager($container, $serviceFactory);
|
||||
$result = $controllerManager->process($controllerName, $actionName, $params, $data);
|
||||
$container->get('output')->render($result);
|
||||
} catch (\Exception $e) {
|
||||
@@ -152,26 +144,28 @@ class Application
|
||||
|
||||
protected function initRoutes()
|
||||
{
|
||||
//$this->getSlim()->get('/', '\Espo\Utils\Api\Rest::main')->conditions( array('useController' => false) );
|
||||
$routes = new \Espo\Core\Utils\Route($this->getContainer()->get('config'), $this->getContainer()->get('fileManager'));
|
||||
|
||||
//TODO move routing to metadata
|
||||
$routes = array(
|
||||
array(
|
||||
'method' => 'get',
|
||||
'route' => 'metadata',
|
||||
'params' => array(
|
||||
'controller' => 'Metadata',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'method' => 'get',
|
||||
'route' => 'settings',
|
||||
'params' => array(
|
||||
'controller' => 'Settings',
|
||||
),
|
||||
),
|
||||
);
|
||||
$crudList = array_keys( (array) $this->getContainer()->get('config')->get('crud') );
|
||||
|
||||
foreach($routes->getAll() as $route) {
|
||||
|
||||
$method = strtolower($route['method']);
|
||||
if (!in_array($method, $crudList)) {
|
||||
$GLOBALS['log']->add('ERROR', 'Route: Method ['.$method.'] does not exist. Please check your route ['.$route['route'].']');
|
||||
continue;
|
||||
}
|
||||
|
||||
$currentRoute = $this->getSlim()->$method($route['route'], function() use ($route) { //todo change "use" for php 5.4
|
||||
return $route['params'];
|
||||
});
|
||||
|
||||
if (isset($route['conditions'])) {
|
||||
$currentRoute->conditions($route['conditions']);
|
||||
}
|
||||
}
|
||||
|
||||
/* //todo remove when it is tested
|
||||
$this->getSlim()->get('/', function() {
|
||||
return $template = "<h1>EspoCRM REST API</h1>";
|
||||
});
|
||||
@@ -270,7 +264,8 @@ class Application
|
||||
'link' => ':link',
|
||||
'foreignId' => ':foreignId'
|
||||
);
|
||||
});
|
||||
}); */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
|
||||
class Route
|
||||
{
|
||||
protected $fileName = 'routes.json';
|
||||
protected $cacheFileName = 'application/routes.php';
|
||||
|
||||
protected $data = null;
|
||||
|
||||
private $fileManager;
|
||||
private $config;
|
||||
|
||||
public function __construct(Config $config, File\Manager $fileManager)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->fileManager = $fileManager;
|
||||
}
|
||||
|
||||
protected function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->fileManager;
|
||||
}
|
||||
|
||||
|
||||
public function get($key = '', $returns = null)
|
||||
{
|
||||
if (!isset($this->data)) {
|
||||
$this->init();
|
||||
}
|
||||
|
||||
if (empty($key)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$keys = explode('.', $key);
|
||||
|
||||
$lastRoute = $this->data;
|
||||
foreach($keys as $keyName) {
|
||||
if (isset($lastRoute[$keyName]) && is_array($lastRoute)) {
|
||||
$lastRoute = $lastRoute[$keyName];
|
||||
} else {
|
||||
return $returns;
|
||||
}
|
||||
}
|
||||
|
||||
return $lastRoute;
|
||||
}
|
||||
|
||||
|
||||
public function getAll()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$cacheFile = Util::concatPath($this->getConfig()->get('cachePath'), $this->cacheFileName);
|
||||
|
||||
if (file_exists($cacheFile) && $this->getConfig()->get('useCache')) {
|
||||
$this->data = $this->getFileManager()->getContent($cacheFile);
|
||||
} else {
|
||||
$this->data = $this->uniteFiles();
|
||||
|
||||
$result = $this->getFileManager()->setContentPHP($this->data, $cacheFile);
|
||||
if ($result == false) {
|
||||
$GLOBALS['log']->add('EXCEPTION', 'Route::init() - Cannot save Routes to a file');
|
||||
throw new \Espo\Core\Exceptions\Error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function uniteFiles($isCustom = false)
|
||||
{
|
||||
$dirName = $isCustom ? '/Custom' : '';
|
||||
|
||||
$data = array();
|
||||
|
||||
$moduleDir = 'application/Espo'.$dirName.'/Modules';
|
||||
if (file_exists($moduleDir)) {
|
||||
$dirList= $this->getFileManager()->getFileList($moduleDir, false, '', 'dir');
|
||||
|
||||
foreach($dirList as $currentDirName) {
|
||||
|
||||
$dirNameFull = Util::concatPath($moduleDir, $currentDirName);
|
||||
$routeFile = Util::concatPath($dirNameFull, $this->fileName);
|
||||
|
||||
$data = $this->getAddData($data, $routeFile);
|
||||
}
|
||||
}
|
||||
|
||||
//if need this path to high priority, move up this code
|
||||
$routeFile = Util::concatPath('application/Espo'.$dirName, $this->fileName);
|
||||
$data = $this->getAddData($data, $routeFile);
|
||||
|
||||
if (!$isCustom) {
|
||||
$data = $this->addToData($this->uniteFiles(true), $data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getAddData($currData, $routeFile)
|
||||
{
|
||||
if (file_exists($routeFile)) {
|
||||
$content= $this->getFileManager()->getContent($routeFile);
|
||||
$arrayContent = Json::getArrayData($content);
|
||||
if (empty($arrayContent)) {
|
||||
$GLOBALS['log']->add('ERROR', 'Route::uniteFiles() - Empty file or syntax error - ['.$routeFile.']');
|
||||
return $currData;
|
||||
}
|
||||
|
||||
$currData = $this->addToData($currData, $arrayContent);
|
||||
}
|
||||
|
||||
return $currData;
|
||||
}
|
||||
|
||||
|
||||
protected function addToData($data, $newData)
|
||||
{
|
||||
if (!is_array($newData)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach($newData as $route) {
|
||||
$data[] = $route;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
[
|
||||
]
|
||||
@@ -0,0 +1,140 @@
|
||||
[
|
||||
{
|
||||
"route":"/",
|
||||
"method":"get",
|
||||
"params":"<h1>EspoCRM REST API<\/h1>"
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/App/user/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":"App",
|
||||
"action":"user"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/Metadata/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":"Metadata"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/Settings/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":"Settings"
|
||||
},
|
||||
"conditions":{
|
||||
"auth":false
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/Settings/",
|
||||
"method":"patch",
|
||||
"params":{
|
||||
"controller":"Settings"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/layout/:name/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":"Layout",
|
||||
"scope":":controller"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/layout/:name/",
|
||||
"method":"put",
|
||||
"params":{
|
||||
"controller":"Layout",
|
||||
"scope":":controller"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/layout/:name/",
|
||||
"method":"patch",
|
||||
"params":{
|
||||
"controller":"Layout",
|
||||
"scope":":controller"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/Admin/rebuild/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":"Admin",
|
||||
"action":"rebuild"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/:id/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":":controller",
|
||||
"action":"read",
|
||||
"id":":id"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":":controller",
|
||||
"action":"index"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/",
|
||||
"method":"post",
|
||||
"params":{
|
||||
"controller":":controller",
|
||||
"action":"create"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/:id/",
|
||||
"method":"put",
|
||||
"params":{
|
||||
"controller":":controller",
|
||||
"action":"update",
|
||||
"id":":id"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/:id/",
|
||||
"method":"patch",
|
||||
"params":{
|
||||
"controller":":controller",
|
||||
"action":"patch",
|
||||
"id":":id"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"route":"/:controller/:id/:link/:foreignId/",
|
||||
"method":"get",
|
||||
"params":{
|
||||
"controller":":controller",
|
||||
"action":"readRelated",
|
||||
"id":":id",
|
||||
"link":":link",
|
||||
"foreignId":":foreignId"
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
Generated
+20
-17
@@ -554,21 +554,24 @@
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "2.2.0",
|
||||
"version": "2.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codeguy/Slim.git",
|
||||
"reference": "b8181de1112a1e2f565b40158b621c34ded38053"
|
||||
"reference": "ff7d7148848fa4f45712984d7b91ac3cbced586b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/codeguy/Slim/zipball/b8181de1112a1e2f565b40158b621c34ded38053",
|
||||
"reference": "b8181de1112a1e2f565b40158b621c34ded38053",
|
||||
"url": "https://api.github.com/repos/codeguy/Slim/zipball/ff7d7148848fa4f45712984d7b91ac3cbced586b",
|
||||
"reference": "ff7d7148848fa4f45712984d7b91ac3cbced586b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mcrypt": "Required for HTTP cookie encryption"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
@@ -593,21 +596,21 @@
|
||||
"rest",
|
||||
"router"
|
||||
],
|
||||
"time": "2012-12-13 02:15:50"
|
||||
"time": "2013-11-29 20:33:36"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v2.3.7",
|
||||
"version": "v2.4.0",
|
||||
"target-dir": "Symfony/Component/Console",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Console.git",
|
||||
"reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18"
|
||||
"reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/00848d3e13cf512e77c7498c2b3b0192f61f4b18",
|
||||
"reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
|
||||
"reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -622,7 +625,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -646,21 +649,21 @@
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "http://symfony.com",
|
||||
"time": "2013-11-13 21:27:40"
|
||||
"time": "2013-11-27 09:10:40"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.3.7",
|
||||
"version": "v2.4.0",
|
||||
"target-dir": "Symfony/Component/Yaml",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Yaml.git",
|
||||
"reference": "c1bda5b459d792cb253de12c65beba3040163b2b"
|
||||
"reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/c1bda5b459d792cb253de12c65beba3040163b2b",
|
||||
"reference": "c1bda5b459d792cb253de12c65beba3040163b2b",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
|
||||
"reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -669,7 +672,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -693,7 +696,7 @@
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "http://symfony.com",
|
||||
"time": "2013-10-17 11:48:01"
|
||||
"time": "2013-11-26 16:40:27"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
||||
Regular → Executable
BIN
Binary file not shown.
Vendored
+1
-1
@@ -4,4 +4,4 @@
|
||||
|
||||
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInitcb7c1594bf378622122ae8e77daf1532::getLoader();
|
||||
return ComposerAutoloaderInit1983a0e55fe28bbf984fa65ef179598e::getLoader();
|
||||
|
||||
Vendored
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInitcb7c1594bf378622122ae8e77daf1532
|
||||
class ComposerAutoloaderInit1983a0e55fe28bbf984fa65ef179598e
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@@ -19,9 +19,9 @@ class ComposerAutoloaderInitcb7c1594bf378622122ae8e77daf1532
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInitcb7c1594bf378622122ae8e77daf1532', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInit1983a0e55fe28bbf984fa65ef179598e', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitcb7c1594bf378622122ae8e77daf1532', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit1983a0e55fe28bbf984fa65ef179598e', 'loadClassLoader'));
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
Vendored
+115
-112
@@ -559,61 +559,6 @@
|
||||
"spl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v2.3.7",
|
||||
"version_normalized": "2.3.7.0",
|
||||
"target-dir": "Symfony/Component/Console",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Console.git",
|
||||
"reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/00848d3e13cf512e77c7498c2b3b0192f61f4b18",
|
||||
"reference": "00848d3e13cf512e77c7498c2b3b0192f61f4b18",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/event-dispatcher": "~2.1"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/event-dispatcher": ""
|
||||
},
|
||||
"time": "2013-11-13 21:27:40",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Symfony\\Component\\Console\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "http://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "http://symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
"version": "v2.4.1",
|
||||
@@ -760,55 +705,6 @@
|
||||
"orm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.3.7",
|
||||
"version_normalized": "2.3.7.0",
|
||||
"target-dir": "Symfony/Component/Yaml",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Yaml.git",
|
||||
"reference": "c1bda5b459d792cb253de12c65beba3040163b2b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/c1bda5b459d792cb253de12c65beba3040163b2b",
|
||||
"reference": "c1bda5b459d792cb253de12c65beba3040163b2b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"time": "2013-10-17 11:48:01",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "http://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "http://symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-token-stream",
|
||||
"version": "1.2.1",
|
||||
@@ -1048,24 +944,76 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "2.2.0",
|
||||
"version_normalized": "2.2.0.0",
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.4.0",
|
||||
"version_normalized": "2.4.0.0",
|
||||
"target-dir": "Symfony/Component/Yaml",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codeguy/Slim.git",
|
||||
"reference": "b8181de1112a1e2f565b40158b621c34ded38053"
|
||||
"url": "https://github.com/symfony/Yaml.git",
|
||||
"reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/codeguy/Slim/zipball/b8181de1112a1e2f565b40158b621c34ded38053",
|
||||
"reference": "b8181de1112a1e2f565b40158b621c34ded38053",
|
||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
|
||||
"reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"time": "2013-11-26 16:40:27",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "http://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "http://symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "2.4.0",
|
||||
"version_normalized": "2.4.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codeguy/Slim.git",
|
||||
"reference": "ff7d7148848fa4f45712984d7b91ac3cbced586b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/codeguy/Slim/zipball/ff7d7148848fa4f45712984d7b91ac3cbced586b",
|
||||
"reference": "ff7d7148848fa4f45712984d7b91ac3cbced586b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2012-12-13 02:15:50",
|
||||
"suggest": {
|
||||
"ext-mcrypt": "Required for HTTP cookie encryption"
|
||||
},
|
||||
"time": "2013-11-29 20:33:36",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@@ -1091,5 +1039,60 @@
|
||||
"rest",
|
||||
"router"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v2.4.0",
|
||||
"version_normalized": "2.4.0.0",
|
||||
"target-dir": "Symfony/Component/Console",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Console.git",
|
||||
"reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Console/zipball/3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
|
||||
"reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/event-dispatcher": "~2.1"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/event-dispatcher": ""
|
||||
},
|
||||
"time": "2013-11-27 09:10:40",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Symfony\\Component\\Console\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "http://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "http://symfony.com"
|
||||
}
|
||||
]
|
||||
|
||||
Vendored
+1
@@ -3,5 +3,6 @@ language: php
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
|
||||
script: phpunit --coverage-text
|
||||
|
||||
Vendored
+54
-5
@@ -1,6 +1,6 @@
|
||||
# Slim Framework
|
||||
|
||||
[](http://travis-ci.org/codeguy/Slim)
|
||||
[](http://travis-ci.org/codeguy/Slim)
|
||||
|
||||
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
|
||||
Slim is easy to use for both beginners and professionals. Slim favors cleanliness over terseness and common cases
|
||||
@@ -14,6 +14,7 @@ Thank you for choosing the Slim Framework for your next project. I think you're
|
||||
* Route parameters with wildcards and conditions
|
||||
* Route redirect, halt, and pass
|
||||
* Route middleware
|
||||
* Resource Locator and DI container
|
||||
* Template rendering with custom views
|
||||
* Flash messages
|
||||
* Secure cookies with AES-256 encryption
|
||||
@@ -29,7 +30,7 @@ Thank you for choosing the Slim Framework for your next project. I think you're
|
||||
|
||||
You may install the Slim Framework with Composer (recommended) or manually.
|
||||
|
||||
[Read how to install Slim](http://docs.slimframework.com/pages/getting-started-install)
|
||||
[Read how to install Slim](http://docs.slimframework.com/#Installation)
|
||||
|
||||
### System Requirements
|
||||
|
||||
@@ -64,12 +65,38 @@ should contain this code:
|
||||
|
||||
#### Nginx
|
||||
|
||||
Your nginx configuration file should contain this code (along with other settings you may need) in your `location` block:
|
||||
The nginx configuration file should contain this code (along with other settings you may need) in your `location` block:
|
||||
|
||||
try_files $uri $uri/ /index.php;
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
|
||||
This assumes that Slim's `index.php` is in the root folder of your project (www root).
|
||||
|
||||
#### HipHop Virtual Machine for PHP
|
||||
|
||||
Your HipHop Virtual Machine configuration file should contain this code (along with other settings you may need).
|
||||
Be sure you change the `ServerRoot` setting to point to your Slim app's document root directory.
|
||||
|
||||
Server {
|
||||
SourceRoot = /path/to/public/directory
|
||||
}
|
||||
|
||||
ServerVariables {
|
||||
SCRIPT_NAME = /index.php
|
||||
}
|
||||
|
||||
VirtualHost {
|
||||
* {
|
||||
Pattern = .*
|
||||
RewriteRules {
|
||||
* {
|
||||
pattern = ^(.*)$
|
||||
to = index.php/$1
|
||||
qsa = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#### lighttpd ####
|
||||
|
||||
Your lighttpd configuration file should contain this code (along with other settings you may need). This code requires
|
||||
@@ -79,6 +106,28 @@ lighttpd >= 1.4.24.
|
||||
|
||||
This assumes that Slim's `index.php` is in the root folder of your project (www root).
|
||||
|
||||
#### IIS
|
||||
|
||||
Ensure the `Web.config` and `index.php` files are in the same public-accessible directory. The `Web.config` file should contain this code:
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="slim" patternSyntax="Wildcard">
|
||||
<match url="*" />
|
||||
<conditions>
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="index.php" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
|
||||
## Documentation
|
||||
|
||||
<http://docs.slimframework.com/>
|
||||
@@ -118,7 +167,7 @@ Follow [@slimphp](http://www.twitter.com/slimphp) on Twitter to receive news and
|
||||
|
||||
## Author
|
||||
|
||||
The Slim Framework is created and maintained by [Josh Lockhart](https://www.joshlockhart.com). Josh is a senior
|
||||
The Slim Framework is created and maintained by [Josh Lockhart](http://www.joshlockhart.com). Josh is a senior
|
||||
web developer at [New Media Campaigns](http://www.newmediacampaigns.com/). Josh also created and maintains
|
||||
[PHP: The Right Way](http://www.phptherightway.com/), a popular movement in the PHP community to introduce new
|
||||
PHP programmers to best practices and good information.
|
||||
|
||||
+29
-42
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -87,7 +87,7 @@ class Environment implements \ArrayAccess, \IteratorAggregate
|
||||
*/
|
||||
public static function mock($userSettings = array())
|
||||
{
|
||||
self::$environment = new self(array_merge(array(
|
||||
$defaults = array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '',
|
||||
'PATH_INFO' => '',
|
||||
@@ -102,7 +102,8 @@ class Environment implements \ArrayAccess, \IteratorAggregate
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => @fopen('php://stderr', 'w')
|
||||
), $userSettings));
|
||||
);
|
||||
self::$environment = new self(array_merge($defaults, $userSettings));
|
||||
|
||||
return self::$environment;
|
||||
}
|
||||
@@ -125,35 +126,26 @@ class Environment implements \ArrayAccess, \IteratorAggregate
|
||||
//The IP
|
||||
$env['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
/**
|
||||
* Application paths
|
||||
*
|
||||
* This derives two paths: SCRIPT_NAME and PATH_INFO. The SCRIPT_NAME
|
||||
* is the real, physical path to the application, be it in the root
|
||||
* directory or a subdirectory of the public document root. The PATH_INFO is the
|
||||
* virtual path to the requested resource within the application context.
|
||||
*
|
||||
* With htaccess, the SCRIPT_NAME will be an absolute path (without file name);
|
||||
* if not using htaccess, it will also include the file name. If it is "/",
|
||||
* it is set to an empty string (since it cannot have a trailing slash).
|
||||
*
|
||||
* The PATH_INFO will be an absolute path with a leading slash; this will be
|
||||
* used for application routing.
|
||||
*/
|
||||
if (strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === 0) {
|
||||
$env['SCRIPT_NAME'] = $_SERVER['SCRIPT_NAME']; //Without URL rewrite
|
||||
} else {
|
||||
$env['SCRIPT_NAME'] = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']) ); //With URL rewrite
|
||||
}
|
||||
$env['PATH_INFO'] = substr_replace($_SERVER['REQUEST_URI'], '', 0, strlen($env['SCRIPT_NAME']));
|
||||
if (strpos($env['PATH_INFO'], '?') !== false) {
|
||||
$env['PATH_INFO'] = substr_replace($env['PATH_INFO'], '', strpos($env['PATH_INFO'], '?')); //query string is not removed automatically
|
||||
}
|
||||
$env['SCRIPT_NAME'] = rtrim($env['SCRIPT_NAME'], '/');
|
||||
$env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/');
|
||||
// Server params
|
||||
$scriptName = $_SERVER['SCRIPT_NAME']; // <-- "/foo/index.php"
|
||||
$requestUri = $_SERVER['REQUEST_URI']; // <-- "/foo/bar?test=abc" or "/foo/index.php/bar?test=abc"
|
||||
$queryString = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; // <-- "test=abc" or ""
|
||||
|
||||
//The portion of the request URI following the '?'
|
||||
$env['QUERY_STRING'] = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
|
||||
// Physical path
|
||||
if (strpos($requestUri, $scriptName) !== false) {
|
||||
$physicalPath = $scriptName; // <-- Without rewriting
|
||||
} else {
|
||||
$physicalPath = str_replace('\\', '', dirname($scriptName)); // <-- With rewriting
|
||||
}
|
||||
$env['SCRIPT_NAME'] = rtrim($physicalPath, '/'); // <-- Remove trailing slashes
|
||||
|
||||
// Virtual path
|
||||
$env['PATH_INFO'] = substr_replace($requestUri, '', 0, strlen($physicalPath)); // <-- Remove physical path
|
||||
$env['PATH_INFO'] = str_replace('?' . $queryString, '', $env['PATH_INFO']); // <-- Remove query string
|
||||
$env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/'); // <-- Ensure leading slash
|
||||
|
||||
// Query string (without leading "?")
|
||||
$env['QUERY_STRING'] = $queryString;
|
||||
|
||||
//Name of server host that is running the script
|
||||
$env['SERVER_NAME'] = $_SERVER['SERVER_NAME'];
|
||||
@@ -161,21 +153,16 @@ class Environment implements \ArrayAccess, \IteratorAggregate
|
||||
//Number of server port that is running the script
|
||||
$env['SERVER_PORT'] = $_SERVER['SERVER_PORT'];
|
||||
|
||||
//HTTP request headers
|
||||
$specialHeaders = array('CONTENT_TYPE', 'CONTENT_LENGTH', 'PHP_AUTH_USER', 'PHP_AUTH_PW', 'PHP_AUTH_DIGEST', 'AUTH_TYPE');
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
$value = is_string($value) ? trim($value) : $value;
|
||||
if (strpos($key, 'HTTP_') === 0) {
|
||||
$env[substr($key, 5)] = $value;
|
||||
} elseif (strpos($key, 'X_') === 0 || in_array($key, $specialHeaders)) {
|
||||
$env[$key] = $value;
|
||||
}
|
||||
//HTTP request headers (retains HTTP_ prefix to match $_SERVER)
|
||||
$headers = \Slim\Http\Headers::extract($_SERVER);
|
||||
foreach ($headers as $key => $value) {
|
||||
$env[$key] = $value;
|
||||
}
|
||||
|
||||
//Is the application running under HTTPS or HTTP protocol?
|
||||
$env['slim.url_scheme'] = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https';
|
||||
|
||||
//Input stream (readable one time only; not available for mutipart/form-data requests)
|
||||
//Input stream (readable one time only; not available for multipart/form-data requests)
|
||||
$rawInput = @file_get_contents('php://input');
|
||||
if (!$rawInput) {
|
||||
$rawInput = '';
|
||||
@@ -183,7 +170,7 @@ class Environment implements \ArrayAccess, \IteratorAggregate
|
||||
$env['slim.input'] = $rawInput;
|
||||
|
||||
//Error stream
|
||||
$env['slim.errors'] = fopen('php://stderr', 'w');
|
||||
$env['slim.errors'] = @fopen('php://stderr', 'w');
|
||||
|
||||
$this->properties = $env;
|
||||
}
|
||||
|
||||
+1
-2
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -46,5 +46,4 @@ namespace Slim\Exception;
|
||||
*/
|
||||
class Pass extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
+1
-2
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -44,5 +44,4 @@ namespace Slim\Exception;
|
||||
*/
|
||||
class Stop extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
+45
-122
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -35,147 +35,70 @@ namespace Slim\Http;
|
||||
/**
|
||||
* HTTP Headers
|
||||
*
|
||||
* This class is an abstraction of the HTTP response headers and
|
||||
* provides array access to the header list while automatically
|
||||
* stores and retrieves headers with lowercase canonical keys regardless
|
||||
* of the input format.
|
||||
*
|
||||
* This class also implements the `Iterator` and `Countable`
|
||||
* interfaces for even more convenient usage.
|
||||
*
|
||||
* @package Slim
|
||||
* @author Josh Lockhart
|
||||
* @since 1.6.0
|
||||
*/
|
||||
class Headers implements \ArrayAccess, \Iterator, \Countable
|
||||
class Headers extends \Slim\Helper\Set
|
||||
{
|
||||
/**
|
||||
* @var array HTTP headers
|
||||
*/
|
||||
protected $headers;
|
||||
/********************************************************************************
|
||||
* Static interface
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* @var array Map canonical header name to original header name
|
||||
* Special-case HTTP headers that are otherwise unidentifiable as HTTP headers.
|
||||
* 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
|
||||
*/
|
||||
protected $map;
|
||||
protected static $special = array(
|
||||
'CONTENT_TYPE',
|
||||
'CONTENT_LENGTH',
|
||||
'PHP_AUTH_USER',
|
||||
'PHP_AUTH_PW',
|
||||
'PHP_AUTH_DIGEST',
|
||||
'AUTH_TYPE'
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param array $headers
|
||||
* Extract HTTP headers from an array of data (e.g. $_SERVER)
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function __construct($headers = array())
|
||||
public static function extract($data)
|
||||
{
|
||||
$this->merge($headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge Headers
|
||||
* @param array $headers
|
||||
*/
|
||||
public function merge($headers)
|
||||
{
|
||||
foreach ($headers as $name => $value) {
|
||||
$this[$name] = $value;
|
||||
$results = array();
|
||||
foreach ($data as $key => $value) {
|
||||
$key = strtoupper($key);
|
||||
if (strpos($key, 'X_') === 0 || strpos($key, 'HTTP_') === 0 || in_array($key, static::$special)) {
|
||||
if ($key === 'HTTP_CONTENT_TYPE' || $key === 'HTTP_CONTENT_LENGTH') {
|
||||
continue;
|
||||
}
|
||||
$results[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Instance interface
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Transform header name into canonical form
|
||||
* @param string $name
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function canonical($name)
|
||||
protected function normalizeKey($key)
|
||||
{
|
||||
return strtolower(trim($name));
|
||||
}
|
||||
$key = strtolower($key);
|
||||
$key = str_replace(array('-', '_'), ' ', $key);
|
||||
$key = preg_replace('#^http #', '', $key);
|
||||
$key = ucwords($key);
|
||||
$key = str_replace(' ', '-', $key);
|
||||
|
||||
/**
|
||||
* Array Access: Offset Exists
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->headers[$this->canonical($offset)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array Access: Offset Get
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
$canonical = $this->canonical($offset);
|
||||
if (isset($this->headers[$canonical])) {
|
||||
return $this->headers[$canonical];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Array Access: Offset Set
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$canonical = $this->canonical($offset);
|
||||
$this->headers[$canonical] = $value;
|
||||
$this->map[$canonical] = $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array Access: Offset Unset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$canonical = $this->canonical($offset);
|
||||
unset($this->headers[$canonical], $this->map[$canonical]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Countable: Count
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: Rewind
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: Current
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return current($this->headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: Key
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
$key = key($this->headers);
|
||||
|
||||
return $this->map[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: Next
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
return next($this->headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: Valid
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return current($this->headers) !== false;
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
+112
-83
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -48,6 +48,7 @@ class Request
|
||||
const METHOD_GET = 'GET';
|
||||
const METHOD_POST = 'POST';
|
||||
const METHOD_PUT = 'PUT';
|
||||
const METHOD_PATCH = 'PATCH';
|
||||
const METHOD_DELETE = 'DELETE';
|
||||
const METHOD_OPTIONS = 'OPTIONS';
|
||||
const METHOD_OVERRIDE = '_METHOD';
|
||||
@@ -58,18 +59,32 @@ class Request
|
||||
protected static $formDataMediaTypes = array('application/x-www-form-urlencoded');
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* Application Environment
|
||||
* @var \Slim\Environment
|
||||
*/
|
||||
protected $env;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param array $env
|
||||
* @see \Slim\Environment
|
||||
* HTTP Headers
|
||||
* @var \Slim\Http\Headers
|
||||
*/
|
||||
public function __construct($env)
|
||||
public $headers;
|
||||
|
||||
/**
|
||||
* HTTP Cookies
|
||||
* @var \Slim\Helper\Set
|
||||
*/
|
||||
public $cookies;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param \Slim\Environment $env
|
||||
*/
|
||||
public function __construct(\Slim\Environment $env)
|
||||
{
|
||||
$this->env = $env;
|
||||
$this->headers = new \Slim\Http\Headers(\Slim\Http\Headers::extract($env));
|
||||
$this->cookies = new \Slim\Helper\Set(\Slim\Http\Util::parseCookieHeader($env['HTTP_COOKIE']));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,6 +123,15 @@ class Request
|
||||
return $this->getMethod() === self::METHOD_PUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a PATCH request?
|
||||
* @return bool
|
||||
*/
|
||||
public function isPatch()
|
||||
{
|
||||
return $this->getMethod() === self::METHOD_PATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a DELETE request?
|
||||
* @return bool
|
||||
@@ -143,7 +167,7 @@ class Request
|
||||
{
|
||||
if ($this->params('isajax')) {
|
||||
return true;
|
||||
} elseif (isset($this->env['X_REQUESTED_WITH']) && $this->env['X_REQUESTED_WITH'] === 'XMLHttpRequest') {
|
||||
} elseif (isset($this->headers['X_REQUESTED_WITH']) && $this->headers['X_REQUESTED_WITH'] === 'XMLHttpRequest') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -172,14 +196,10 @@ class Request
|
||||
{
|
||||
$union = array_merge($this->get(), $this->post());
|
||||
if ($key) {
|
||||
if (isset($union[$key])) {
|
||||
return $union[$key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return $union;
|
||||
return isset($union[$key]) ? $union[$key] : null;
|
||||
}
|
||||
|
||||
return $union;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,9 +209,10 @@ class Request
|
||||
* the value of the array key if requested; if the array key does not exist, NULL is returned.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default Default return value when key does not exist
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
public function get($key = null)
|
||||
public function get($key = null, $default = null)
|
||||
{
|
||||
if (!isset($this->env['slim.request.query_hash'])) {
|
||||
$output = array();
|
||||
@@ -206,7 +227,7 @@ class Request
|
||||
if (isset($this->env['slim.request.query_hash'][$key])) {
|
||||
return $this->env['slim.request.query_hash'][$key];
|
||||
} else {
|
||||
return null;
|
||||
return $default;
|
||||
}
|
||||
} else {
|
||||
return $this->env['slim.request.query_hash'];
|
||||
@@ -220,10 +241,11 @@ class Request
|
||||
* the value of a hash key if requested; if the array key does not exist, NULL is returned.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default Default return value when key does not exist
|
||||
* @return array|mixed|null
|
||||
* @throws \RuntimeException If environment input is not available
|
||||
*/
|
||||
public function post($key = null)
|
||||
public function post($key = null, $default = null)
|
||||
{
|
||||
if (!isset($this->env['slim.input'])) {
|
||||
throw new \RuntimeException('Missing slim.input in environment variables');
|
||||
@@ -246,7 +268,7 @@ class Request
|
||||
if (isset($this->env['slim.request.form_hash'][$key])) {
|
||||
return $this->env['slim.request.form_hash'][$key];
|
||||
} else {
|
||||
return null;
|
||||
return $default;
|
||||
}
|
||||
} else {
|
||||
return $this->env['slim.request.form_hash'];
|
||||
@@ -256,21 +278,34 @@ class Request
|
||||
/**
|
||||
* Fetch PUT data (alias for \Slim\Http\Request::post)
|
||||
* @param string $key
|
||||
* @param mixed $default Default return value when key does not exist
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
public function put($key = null)
|
||||
public function put($key = null, $default = null)
|
||||
{
|
||||
return $this->post($key);
|
||||
return $this->post($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch PATCH data (alias for \Slim\Http\Request::post)
|
||||
* @param string $key
|
||||
* @param mixed $default Default return value when key does not exist
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
public function patch($key = null, $default = null)
|
||||
{
|
||||
return $this->post($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch DELETE data (alias for \Slim\Http\Request::post)
|
||||
* @param string $key
|
||||
* @param mixed $default Default return value when key does not exist
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
public function delete($key = null)
|
||||
public function delete($key = null, $default = null)
|
||||
{
|
||||
return $this->post($key);
|
||||
return $this->post($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,23 +319,28 @@ class Request
|
||||
*/
|
||||
public function cookies($key = null)
|
||||
{
|
||||
if (!isset($this->env['slim.request.cookie_hash'])) {
|
||||
$cookieHeader = isset($this->env['COOKIE']) ? $this->env['COOKIE'] : '';
|
||||
$this->env['slim.request.cookie_hash'] = Util::parseCookieHeader($cookieHeader);
|
||||
}
|
||||
if ($key) {
|
||||
if (isset($this->env['slim.request.cookie_hash'][$key])) {
|
||||
return $this->env['slim.request.cookie_hash'][$key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return $this->env['slim.request.cookie_hash'];
|
||||
return $this->cookies->get($key);
|
||||
}
|
||||
|
||||
return $this->cookies;
|
||||
// if (!isset($this->env['slim.request.cookie_hash'])) {
|
||||
// $cookieHeader = isset($this->env['COOKIE']) ? $this->env['COOKIE'] : '';
|
||||
// $this->env['slim.request.cookie_hash'] = Util::parseCookieHeader($cookieHeader);
|
||||
// }
|
||||
// if ($key) {
|
||||
// if (isset($this->env['slim.request.cookie_hash'][$key])) {
|
||||
// return $this->env['slim.request.cookie_hash'][$key];
|
||||
// } else {
|
||||
// return null;
|
||||
// }
|
||||
// } else {
|
||||
// return $this->env['slim.request.cookie_hash'];
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the Request body contain parseable form data?
|
||||
* Does the Request body contain parsed form data?
|
||||
* @return bool
|
||||
*/
|
||||
public function isFormData()
|
||||
@@ -323,24 +363,29 @@ class Request
|
||||
public function headers($key = null, $default = null)
|
||||
{
|
||||
if ($key) {
|
||||
$key = strtoupper($key);
|
||||
$key = str_replace('-', '_', $key);
|
||||
$key = preg_replace('@^HTTP_@', '', $key);
|
||||
if (isset($this->env[$key])) {
|
||||
return $this->env[$key];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
} else {
|
||||
$headers = array();
|
||||
foreach ($this->env as $key => $value) {
|
||||
if (strpos($key, 'slim.') !== 0) {
|
||||
$headers[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
return $this->headers->get($key, $default);
|
||||
}
|
||||
|
||||
return $this->headers;
|
||||
// if ($key) {
|
||||
// $key = strtoupper($key);
|
||||
// $key = str_replace('-', '_', $key);
|
||||
// $key = preg_replace('@^HTTP_@', '', $key);
|
||||
// if (isset($this->env[$key])) {
|
||||
// return $this->env[$key];
|
||||
// } else {
|
||||
// return $default;
|
||||
// }
|
||||
// } else {
|
||||
// $headers = array();
|
||||
// foreach ($this->env as $key => $value) {
|
||||
// if (strpos($key, 'slim.') !== 0) {
|
||||
// $headers[$key] = $value;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return $headers;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,15 +399,11 @@ class Request
|
||||
|
||||
/**
|
||||
* Get Content Type
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
if (isset($this->env['CONTENT_TYPE'])) {
|
||||
return $this->env['CONTENT_TYPE'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return $this->headers->get('CONTENT_TYPE');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,9 +417,9 @@ class Request
|
||||
$contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType);
|
||||
|
||||
return strtolower($contentTypeParts[0]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,9 +451,9 @@ class Request
|
||||
$mediaTypeParams = $this->getMediaTypeParams();
|
||||
if (isset($mediaTypeParams['charset'])) {
|
||||
return $mediaTypeParams['charset'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,11 +462,7 @@ class Request
|
||||
*/
|
||||
public function getContentLength()
|
||||
{
|
||||
if (isset($this->env['CONTENT_LENGTH'])) {
|
||||
return (int) $this->env['CONTENT_LENGTH'];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return $this->headers->get('CONTENT_LENGTH', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,17 +471,17 @@ class Request
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
if (isset($this->env['HOST'])) {
|
||||
if (strpos($this->env['HOST'], ':') !== false) {
|
||||
$hostParts = explode(':', $this->env['HOST']);
|
||||
if (isset($this->env['HTTP_HOST'])) {
|
||||
if (strpos($this->env['HTTP_HOST'], ':') !== false) {
|
||||
$hostParts = explode(':', $this->env['HTTP_HOST']);
|
||||
|
||||
return $hostParts[0];
|
||||
}
|
||||
|
||||
return $this->env['HOST'];
|
||||
} else {
|
||||
return $this->env['SERVER_NAME'];
|
||||
return $this->env['HTTP_HOST'];
|
||||
}
|
||||
|
||||
return $this->env['SERVER_NAME'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -462,7 +499,7 @@ class Request
|
||||
*/
|
||||
public function getPort()
|
||||
{
|
||||
return (int) $this->env['SERVER_PORT'];
|
||||
return (int)$this->env['SERVER_PORT'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -554,11 +591,7 @@ class Request
|
||||
*/
|
||||
public function getReferrer()
|
||||
{
|
||||
if (isset($this->env['REFERER'])) {
|
||||
return $this->env['REFERER'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return $this->headers->get('HTTP_REFERER');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,10 +609,6 @@ class Request
|
||||
*/
|
||||
public function getUserAgent()
|
||||
{
|
||||
if (isset($this->env['USER_AGENT'])) {
|
||||
return $this->env['USER_AGENT'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return $this->headers->get('HTTP_USER_AGENT');
|
||||
}
|
||||
}
|
||||
|
||||
+110
-57
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -51,9 +51,14 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
protected $status;
|
||||
|
||||
/**
|
||||
* @var \Slim\Http\Headers List of HTTP response headers
|
||||
* @var \Slim\Http\Headers
|
||||
*/
|
||||
protected $header;
|
||||
public $headers;
|
||||
|
||||
/**
|
||||
* @var \Slim\Http\Cookies
|
||||
*/
|
||||
public $cookies;
|
||||
|
||||
/**
|
||||
* @var string HTTP response body
|
||||
@@ -108,6 +113,7 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
415 => '415 Unsupported Media Type',
|
||||
416 => '416 Requested Range Not Satisfiable',
|
||||
417 => '417 Expectation Failed',
|
||||
418 => '418 I\'m a teapot',
|
||||
422 => '422 Unprocessable Entity',
|
||||
423 => '423 Locked',
|
||||
//Server Error 5xx
|
||||
@@ -123,21 +129,30 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
* Constructor
|
||||
* @param string $body The HTTP response body
|
||||
* @param int $status The HTTP response status
|
||||
* @param \Slim\Http\Headers|array $header The HTTP response headers
|
||||
* @param \Slim\Http\Headers|array $headers The HTTP response headers
|
||||
*/
|
||||
public function __construct($body = '', $status = 200, $header = array())
|
||||
public function __construct($body = '', $status = 200, $headers = array())
|
||||
{
|
||||
$this->status = (int) $status;
|
||||
$headers = array();
|
||||
foreach ($header as $key => $value) {
|
||||
$headers[$key] = $value;
|
||||
}
|
||||
$this->header = new Headers(array_merge(array('Content-Type' => 'text/html'), $headers));
|
||||
$this->body = '';
|
||||
$this->setStatus($status);
|
||||
$this->headers = new \Slim\Http\Headers(array('Content-Type' => 'text/html'));
|
||||
$this->headers->replace($headers);
|
||||
$this->cookies = new \Slim\Http\Cookies();
|
||||
$this->write($body);
|
||||
}
|
||||
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus($status)
|
||||
{
|
||||
$this->status = (int)$status;
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! Use `getStatus` or `setStatus` instead.
|
||||
*
|
||||
* Get and set status
|
||||
* @param int|null $status
|
||||
* @return int
|
||||
@@ -152,6 +167,8 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! Access `headers` property directly.
|
||||
*
|
||||
* Get and set header
|
||||
* @param string $name Header name
|
||||
* @param string|null $value Header value
|
||||
@@ -160,22 +177,36 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
public function header($name, $value = null)
|
||||
{
|
||||
if (!is_null($value)) {
|
||||
$this[$name] = $value;
|
||||
$this->headers->set($name, $value);
|
||||
}
|
||||
|
||||
return $this[$name];
|
||||
return $this->headers->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! Access `headers` property directly.
|
||||
*
|
||||
* Get headers
|
||||
* @return \Slim\Http\Headers
|
||||
*/
|
||||
public function headers()
|
||||
{
|
||||
return $this->header;
|
||||
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
|
||||
@@ -190,6 +221,31 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
}
|
||||
|
||||
/**
|
||||
* Append HTTP response body
|
||||
* @param string $body Content to append to the current HTTP response body
|
||||
* @param bool $replace Overwrite existing response body?
|
||||
* @return string The updated HTTP response body
|
||||
*/
|
||||
public function write($body, $replace = false)
|
||||
{
|
||||
if ($replace) {
|
||||
$this->body = $body;
|
||||
} else {
|
||||
$this->body .= (string)$body;
|
||||
}
|
||||
$this->length = strlen($this->body);
|
||||
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
public function getLength()
|
||||
{
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! Use `getLength` or `write` or `body` instead.
|
||||
*
|
||||
* Get and set length
|
||||
* @param int|null $length
|
||||
* @return int
|
||||
@@ -203,24 +259,6 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append HTTP response body
|
||||
* @param string $body Content to append to the current HTTP response body
|
||||
* @param bool $replace Overwrite existing response body?
|
||||
* @return string The updated HTTP response body
|
||||
*/
|
||||
public function write($body, $replace = false)
|
||||
{
|
||||
if ($replace) {
|
||||
$this->body = $body;
|
||||
} else {
|
||||
$this->body .= (string) $body;
|
||||
}
|
||||
$this->length = strlen($this->body);
|
||||
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize
|
||||
*
|
||||
@@ -232,16 +270,19 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
*/
|
||||
public function finalize()
|
||||
{
|
||||
// Prepare response
|
||||
if (in_array($this->status, array(204, 304))) {
|
||||
unset($this['Content-Type'], $this['Content-Length']);
|
||||
|
||||
return array($this->status, $this->header, '');
|
||||
} else {
|
||||
return array($this->status, $this->header, $this->body);
|
||||
$this->headers->remove('Content-Type');
|
||||
$this->headers->remove('Content-Length');
|
||||
$this->setBody('');
|
||||
}
|
||||
|
||||
return array($this->status, $this->headers, $this->body);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! Access `cookies` property directly.
|
||||
*
|
||||
* Set cookie
|
||||
*
|
||||
* Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
|
||||
@@ -256,10 +297,13 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
*/
|
||||
public function setCookie($name, $value)
|
||||
{
|
||||
Util::setCookieHeader($this->header, $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`
|
||||
@@ -274,12 +318,13 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
* 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 $value Properties for cookie including: value, expire, path, domain, secure, httponly
|
||||
* @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, $value = array())
|
||||
public function deleteCookie($name, $settings = array())
|
||||
{
|
||||
Util::deleteCookieHeader($this->header, $name, $value);
|
||||
$this->cookies->remove($name, $settings);
|
||||
// Util::deleteCookieHeader($this->header, $name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,8 +338,8 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
*/
|
||||
public function redirect ($url, $status = 302)
|
||||
{
|
||||
$this->status = $status;
|
||||
$this['Location'] = $url;
|
||||
$this->setStatus($status);
|
||||
$this->headers->set('Location', $url);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,24 +432,25 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
return $this->status >= 500 && $this->status < 600;
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! ArrayAccess interface will be removed from \Slim\Http\Response.
|
||||
* Iterate `headers` or `cookies` properties directly.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Array Access: Offset Exists
|
||||
*/
|
||||
public function offsetExists( $offset )
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->header[$offset]);
|
||||
return isset($this->headers[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array Access: Offset Get
|
||||
*/
|
||||
public function offsetGet( $offset )
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if (isset($this->header[$offset])) {
|
||||
return $this->header[$offset];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return $this->headers[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,7 +458,7 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->header[$offset] = $value;
|
||||
$this->headers[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,18 +466,24 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->header[$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
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->header);
|
||||
return count($this->headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! IteratorAggregate interface will be removed from \Slim\Http\Response.
|
||||
* Iterate `headers` or `cookies` properties directly.
|
||||
*
|
||||
* Get Iterator
|
||||
*
|
||||
* This returns the contained `\Slim\Http\Headers` instance which
|
||||
@@ -441,11 +493,12 @@ class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return $this->header;
|
||||
return $this->headers->getIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message for HTTP status code
|
||||
* @param int $status
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getMessageForCode($status)
|
||||
|
||||
Vendored
+74
-29
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -51,14 +51,15 @@ class Util
|
||||
* override the magic quotes setting with either TRUE or FALSE as the send argument
|
||||
* to force this method to strip or not strip slashes from its input.
|
||||
*
|
||||
* @var array|string $rawData
|
||||
* @param array|string $rawData
|
||||
* @param bool $overrideStripSlashes
|
||||
* @return array|string
|
||||
*/
|
||||
public static function stripSlashesIfMagicQuotes($rawData, $overrideStripSlashes = null)
|
||||
{
|
||||
$strip = is_null($overrideStripSlashes) ? get_magic_quotes_gpc() : $overrideStripSlashes;
|
||||
if ($strip) {
|
||||
return self::_stripSlashes($rawData);
|
||||
return self::stripSlashes($rawData);
|
||||
} else {
|
||||
return $rawData;
|
||||
}
|
||||
@@ -69,9 +70,9 @@ class Util
|
||||
* @param array|string $rawData
|
||||
* @return array|string
|
||||
*/
|
||||
protected static function _stripSlashes($rawData)
|
||||
protected static function stripSlashes($rawData)
|
||||
{
|
||||
return is_array($rawData) ? array_map(array('self', '_stripSlashes'), $rawData) : stripslashes($rawData);
|
||||
return is_array($rawData) ? array_map(array('self', 'stripSlashes'), $rawData) : stripslashes($rawData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,10 +96,11 @@ class Util
|
||||
}
|
||||
|
||||
//Merge settings with defaults
|
||||
$settings = array_merge(array(
|
||||
$defaults = array(
|
||||
'algorithm' => MCRYPT_RIJNDAEL_256,
|
||||
'mode' => MCRYPT_MODE_CBC
|
||||
), $settings);
|
||||
);
|
||||
$settings = array_merge($defaults, $settings);
|
||||
|
||||
//Get module
|
||||
$module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
|
||||
@@ -144,10 +146,11 @@ class Util
|
||||
}
|
||||
|
||||
//Merge settings with defaults
|
||||
$settings = array_merge(array(
|
||||
$defaults = array(
|
||||
'algorithm' => MCRYPT_RIJNDAEL_256,
|
||||
'mode' => MCRYPT_MODE_CBC
|
||||
), $settings);
|
||||
);
|
||||
$settings = array_merge($defaults, $settings);
|
||||
|
||||
//Get module
|
||||
$module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
|
||||
@@ -167,12 +170,44 @@ class Util
|
||||
//Decrypt value
|
||||
mcrypt_generic_init($module, $key, $iv);
|
||||
$decryptedData = @mdecrypt_generic($module, $data);
|
||||
$res = str_replace("\x0", '', $decryptedData);
|
||||
$res = rtrim($decryptedData, "\0");
|
||||
mcrypt_generic_deinit($module);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize Response cookies into raw HTTP header
|
||||
* @param \Slim\Http\Headers $headers The Response headers
|
||||
* @param \Slim\Http\Cookies $cookies The Response cookies
|
||||
* @param array $config The Slim app settings
|
||||
*/
|
||||
public static function serializeCookies(\Slim\Http\Headers &$headers, \Slim\Http\Cookies $cookies, array $config)
|
||||
{
|
||||
if ($config['cookies.encrypt']) {
|
||||
foreach ($cookies as $name => $settings) {
|
||||
if (is_string($settings['expires'])) {
|
||||
$expires = strtotime($settings['expires']);
|
||||
} else {
|
||||
$expires = (int) $settings['expires'];
|
||||
}
|
||||
|
||||
$settings['value'] = static::encodeSecureCookie(
|
||||
$settings['value'],
|
||||
$expires,
|
||||
$config['cookies.secret_key'],
|
||||
$config['cookies.cipher'],
|
||||
$config['cookies.cipher_mode']
|
||||
);
|
||||
static::setCookieHeader($headers, $name, $settings);
|
||||
}
|
||||
} else {
|
||||
foreach ($cookies as $name => $settings) {
|
||||
static::setCookieHeader($headers, $name, $settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode secure cookie value
|
||||
*
|
||||
@@ -180,21 +215,28 @@ class Util
|
||||
* cookie value is encrypted and hashed so that its value is
|
||||
* secure and checked for integrity when read in subsequent requests.
|
||||
*
|
||||
* @param string $value The unsecure HTTP cookie value
|
||||
* @param string $value The insecure HTTP cookie value
|
||||
* @param int $expires The UNIX timestamp at which this cookie will expire
|
||||
* @param string $secret The secret key used to hash the cookie value
|
||||
* @param int $algorithm The algorithm to use for encryption
|
||||
* @param int $mode The algorithm mode to use for encryption
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
public static function encodeSecureCookie($value, $expires, $secret, $algorithm, $mode)
|
||||
{
|
||||
$key = hash_hmac('sha1', $expires, $secret);
|
||||
$iv = self::get_iv($expires, $secret);
|
||||
$secureString = base64_encode(self::encrypt($value, $key, $iv, array(
|
||||
'algorithm' => $algorithm,
|
||||
'mode' => $mode
|
||||
)));
|
||||
$iv = self::getIv($expires, $secret);
|
||||
$secureString = base64_encode(
|
||||
self::encrypt(
|
||||
$value,
|
||||
$key,
|
||||
$iv,
|
||||
array(
|
||||
'algorithm' => $algorithm,
|
||||
'mode' => $mode
|
||||
)
|
||||
)
|
||||
);
|
||||
$verificationString = hash_hmac('sha1', $expires . $value, $key);
|
||||
|
||||
return implode('|', array($expires, $secureString, $verificationString));
|
||||
@@ -208,11 +250,10 @@ class Util
|
||||
* secure and checked for integrity when read in subsequent requests.
|
||||
*
|
||||
* @param string $value The secure HTTP cookie value
|
||||
* @param int $expires The UNIX timestamp at which this cookie will expire
|
||||
* @param string $secret The secret key used to hash the cookie value
|
||||
* @param int $algorithm The algorithm to use for encryption
|
||||
* @param int $mode The algorithm mode to use for encryption
|
||||
* @param string
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function decodeSecureCookie($value, $secret, $algorithm, $mode)
|
||||
{
|
||||
@@ -220,11 +261,16 @@ class Util
|
||||
$value = explode('|', $value);
|
||||
if (count($value) === 3 && ((int) $value[0] === 0 || (int) $value[0] > time())) {
|
||||
$key = hash_hmac('sha1', $value[0], $secret);
|
||||
$iv = self::get_iv($value[0], $secret);
|
||||
$data = self::decrypt(base64_decode($value[1]), $key, $iv, array(
|
||||
'algorithm' => $algorithm,
|
||||
'mode' => $mode
|
||||
));
|
||||
$iv = self::getIv($value[0], $secret);
|
||||
$data = self::decrypt(
|
||||
base64_decode($value[1]),
|
||||
$key,
|
||||
$iv,
|
||||
array(
|
||||
'algorithm' => $algorithm,
|
||||
'mode' => $mode
|
||||
)
|
||||
);
|
||||
$verificationString = hash_hmac('sha1', $value[0] . $data, $key);
|
||||
if ($verificationString === $value[2]) {
|
||||
return $data;
|
||||
@@ -310,7 +356,7 @@ class Util
|
||||
*
|
||||
* @param array $header
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param array $value
|
||||
*/
|
||||
public static function deleteCookieHeader(&$header, $name, $value = array())
|
||||
{
|
||||
@@ -343,7 +389,7 @@ class Util
|
||||
/**
|
||||
* Parse cookie header
|
||||
*
|
||||
* This method will parse the HTTP requst's `Cookie` header
|
||||
* This method will parse the HTTP request's `Cookie` header
|
||||
* and extract cookies into an associative array.
|
||||
*
|
||||
* @param string
|
||||
@@ -376,14 +422,13 @@ class Util
|
||||
*
|
||||
* @param int $expires The UNIX timestamp at which this cookie will expire
|
||||
* @param string $secret The secret key used to hash the cookie value
|
||||
* @return binary string with length 40
|
||||
* @return string Hash
|
||||
*/
|
||||
private static function get_iv($expires, $secret)
|
||||
private static function getIv($expires, $secret)
|
||||
{
|
||||
$data1 = hash_hmac('sha1', 'a'.$expires.'b', $secret);
|
||||
$data2 = hash_hmac('sha1', 'z'.$expires.'y', $secret);
|
||||
|
||||
return pack("h*", $data1.$data2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vendored
+150
-38
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -39,11 +39,15 @@ namespace Slim;
|
||||
* a Log Writer in conjunction with this Log to write to various output
|
||||
* destinations (e.g. a file). This class provides this interface:
|
||||
*
|
||||
* debug( mixed $object )
|
||||
* info( mixed $object )
|
||||
* warn( mixed $object )
|
||||
* error( mixed $object )
|
||||
* fatal( mixed $object )
|
||||
* debug( mixed $object, array $context )
|
||||
* info( mixed $object, array $context )
|
||||
* notice( mixed $object, array $context )
|
||||
* warning( mixed $object, array $context )
|
||||
* error( mixed $object, array $context )
|
||||
* critical( mixed $object, array $context )
|
||||
* alert( mixed $object, array $context )
|
||||
* emergency( mixed $object, array $context )
|
||||
* log( mixed $level, mixed $object, array $context )
|
||||
*
|
||||
* This class assumes only that your Log Writer has a public `write()` method
|
||||
* that accepts any object as its one and only argument. The Log Writer
|
||||
@@ -56,21 +60,28 @@ namespace Slim;
|
||||
*/
|
||||
class Log
|
||||
{
|
||||
const FATAL = 0;
|
||||
const ERROR = 1;
|
||||
const WARN = 2;
|
||||
const INFO = 3;
|
||||
const DEBUG = 4;
|
||||
const EMERGENCY = 1;
|
||||
const ALERT = 2;
|
||||
const CRITICAL = 3;
|
||||
const FATAL = 3; //DEPRECATED replace with CRITICAL
|
||||
const ERROR = 4;
|
||||
const WARN = 5;
|
||||
const NOTICE = 6;
|
||||
const INFO = 7;
|
||||
const DEBUG = 8;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $levels = array(
|
||||
self::FATAL => 'FATAL',
|
||||
self::ERROR => 'ERROR',
|
||||
self::WARN => 'WARN',
|
||||
self::INFO => 'INFO',
|
||||
self::DEBUG => 'DEBUG'
|
||||
self::EMERGENCY => 'EMERGENCY',
|
||||
self::ALERT => 'ALERT',
|
||||
self::CRITICAL => 'CRITICAL',
|
||||
self::ERROR => 'ERROR',
|
||||
self::WARN => 'WARNING',
|
||||
self::NOTICE => 'NOTICE',
|
||||
self::INFO => 'INFO',
|
||||
self::DEBUG => 'DEBUG'
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -173,65 +184,166 @@ class Log
|
||||
/**
|
||||
* Log debug message
|
||||
* @param mixed $object
|
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function debug($object)
|
||||
public function debug($object, $context = array())
|
||||
{
|
||||
return $this->write($object, self::DEBUG);
|
||||
return $this->log(self::DEBUG, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log info message
|
||||
* @param mixed $object
|
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function info($object)
|
||||
public function info($object, $context = array())
|
||||
{
|
||||
return $this->write($object, self::INFO);
|
||||
return $this->log(self::INFO, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log warn message
|
||||
* Log notice message
|
||||
* @param mixed $object
|
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function warn($object)
|
||||
public function notice($object, $context = array())
|
||||
{
|
||||
return $this->write($object, self::WARN);
|
||||
return $this->log(self::NOTICE, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log warning message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function warning($object, $context = array())
|
||||
{
|
||||
return $this->log(self::WARN, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED for function warning
|
||||
* Log warning message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function warn($object, $context = array())
|
||||
{
|
||||
return $this->log(self::WARN, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log error message
|
||||
* @param mixed $object
|
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function error($object)
|
||||
public function error($object, $context = array())
|
||||
{
|
||||
return $this->write($object, self::ERROR);
|
||||
return $this->log(self::ERROR, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log critical message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function critical($object, $context = array())
|
||||
{
|
||||
return $this->log(self::CRITICAL, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED for function critical
|
||||
* Log fatal message
|
||||
* @param mixed $object
|
||||
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function fatal($object)
|
||||
public function fatal($object, $context = array())
|
||||
{
|
||||
return $this->write($object, self::FATAL);
|
||||
return $this->log(self::CRITICAL, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log alert message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function alert($object, $context = array())
|
||||
{
|
||||
return $this->log(self::ALERT, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log emergency message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function emergency($object, $context = array())
|
||||
{
|
||||
return $this->log(self::EMERGENCY, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log message
|
||||
* @param mixed The object to log
|
||||
* @param int The message level
|
||||
* @return int|false
|
||||
* @param mixed $level
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
* @throws \InvalidArgumentException If invalid log level
|
||||
*/
|
||||
protected function write($object, $level)
|
||||
public function log($level, $object, $context = array())
|
||||
{
|
||||
if ($this->enabled && $this->writer && $level <= $this->level) {
|
||||
return $this->writer->write($object, $level);
|
||||
if (!isset(self::$levels[$level])) {
|
||||
throw new \InvalidArgumentException('Invalid log level supplied to function');
|
||||
} else if ($this->enabled && $this->writer && $level <= $this->level) {
|
||||
$message = (string)$object;
|
||||
if (count($context) > 0) {
|
||||
if (isset($context['exception']) && $context['exception'] instanceof \Exception) {
|
||||
$message .= ' - ' . $context['exception'];
|
||||
unset($context['exception']);
|
||||
}
|
||||
$message = $this->interpolate($message, $context);
|
||||
}
|
||||
return $this->writer->write($message, $level);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED for function log
|
||||
* Log message
|
||||
* @param mixed $object The object to log
|
||||
* @param int $level The message level
|
||||
* @return int|bool
|
||||
*/
|
||||
protected function write($object, $level)
|
||||
{
|
||||
return $this->log($level, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate log message
|
||||
* @param mixed $message The log message
|
||||
* @param array $context An array of placeholder values
|
||||
* @return string The processed string
|
||||
*/
|
||||
protected function interpolate($message, $context = array())
|
||||
{
|
||||
$replace = array();
|
||||
foreach ($context as $key => $value) {
|
||||
$replace['{' . $key . '}'] = $value;
|
||||
}
|
||||
return strtr($message, $replace);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -66,7 +66,7 @@ class LogWriter
|
||||
* Write message
|
||||
* @param mixed $message
|
||||
* @param int $level
|
||||
* @return int|false
|
||||
* @return int|bool
|
||||
*/
|
||||
public function write($message, $level = null)
|
||||
{
|
||||
|
||||
Vendored
+5
-5
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -42,7 +42,7 @@ namespace Slim;
|
||||
abstract class Middleware
|
||||
{
|
||||
/**
|
||||
* @var \Slim Reference to the primary application instance
|
||||
* @var \Slim\Slim Reference to the primary application instance
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class Middleware
|
||||
* This method injects the primary Slim application instance into
|
||||
* this middleware.
|
||||
*
|
||||
* @param \Slim $application
|
||||
* @param \Slim\Slim $application
|
||||
*/
|
||||
final public function setApplication($application)
|
||||
{
|
||||
@@ -70,7 +70,7 @@ abstract class Middleware
|
||||
* This method retrieves the application previously injected
|
||||
* into this middleware.
|
||||
*
|
||||
* @return \Slim
|
||||
* @return \Slim\Slim
|
||||
*/
|
||||
final public function getApplication()
|
||||
{
|
||||
@@ -97,7 +97,7 @@ abstract class Middleware
|
||||
* This method retrieves the next downstream middleware
|
||||
* previously injected into this middleware.
|
||||
*
|
||||
* @return \Slim|\Slim\Middleware
|
||||
* @return \Slim\Slim|\Slim\Middleware
|
||||
*/
|
||||
final public function getNextMiddleware()
|
||||
{
|
||||
|
||||
+8
-4
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -58,12 +58,13 @@ class ContentTypes extends \Slim\Middleware
|
||||
*/
|
||||
public function __construct($settings = array())
|
||||
{
|
||||
$this->contentTypes = array_merge(array(
|
||||
$defaults = array(
|
||||
'application/json' => array($this, 'parseJson'),
|
||||
'application/xml' => array($this, 'parseXml'),
|
||||
'text/xml' => array($this, 'parseXml'),
|
||||
'text/csv' => array($this, 'parseCsv')
|
||||
), $settings);
|
||||
);
|
||||
$this->contentTypes = array_merge($defaults, $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +137,10 @@ class ContentTypes extends \Slim\Middleware
|
||||
{
|
||||
if (class_exists('SimpleXMLElement')) {
|
||||
try {
|
||||
return new \SimpleXMLElement($input);
|
||||
$backup = libxml_disable_entity_loader(true);
|
||||
$result = new \SimpleXMLElement($input);
|
||||
libxml_disable_entity_loader($backup);
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
+13
-3
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -45,7 +45,7 @@ namespace Slim\Middleware;
|
||||
* @author Josh Lockhart
|
||||
* @since 1.6.0
|
||||
*/
|
||||
class Flash extends \Slim\Middleware implements \ArrayAccess, \IteratorAggregate
|
||||
class Flash extends \Slim\Middleware implements \ArrayAccess, \IteratorAggregate, \Countable
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
@@ -59,7 +59,6 @@ class Flash extends \Slim\Middleware implements \ArrayAccess, \IteratorAggregate
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param \Slim $app
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct($settings = array())
|
||||
@@ -199,4 +198,15 @@ class Flash extends \Slim\Middleware implements \ArrayAccess, \IteratorAggregate
|
||||
|
||||
return new \ArrayIterator($messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Countable: Count
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->getMessages());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+4
-6
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -36,7 +36,7 @@ namespace Slim\Middleware;
|
||||
* HTTP Method Override
|
||||
*
|
||||
* This is middleware for a Slim application that allows traditional
|
||||
* desktop browsers to submit psuedo PUT and DELETE requests by relying
|
||||
* desktop browsers to submit pseudo PUT and DELETE requests by relying
|
||||
* on a pre-determined request parameter. Without this middleware,
|
||||
* desktop browsers are only able to submit GET and POST requests.
|
||||
*
|
||||
@@ -55,7 +55,6 @@ class MethodOverride extends \Slim\Middleware
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param \Slim $app
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct($settings = array())
|
||||
@@ -72,16 +71,15 @@ class MethodOverride extends \Slim\Middleware
|
||||
* modifies the environment settings so downstream middleware and/or the Slim
|
||||
* application will treat the request with the desired HTTP method.
|
||||
*
|
||||
* @param array $env
|
||||
* @return array[status, header, body]
|
||||
*/
|
||||
public function call()
|
||||
{
|
||||
$env = $this->app->environment();
|
||||
if (isset($env['X_HTTP_METHOD_OVERRIDE'])) {
|
||||
if (isset($env['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
|
||||
// Header commonly used by Backbone.js and others
|
||||
$env['slim.method_override.original_method'] = $env['REQUEST_METHOD'];
|
||||
$env['REQUEST_METHOD'] = strtoupper($env['X_HTTP_METHOD_OVERRIDE']);
|
||||
$env['REQUEST_METHOD'] = strtoupper($env['HTTP_X_HTTP_METHOD_OVERRIDE']);
|
||||
} elseif (isset($env['REQUEST_METHOD']) && $env['REQUEST_METHOD'] === 'POST') {
|
||||
// HTML Form Override
|
||||
$req = new \Slim\Http\Request($env);
|
||||
|
||||
+3
-1
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -66,7 +66,9 @@ class PrettyExceptions extends \Slim\Middleware
|
||||
try {
|
||||
$this->next->call();
|
||||
} catch (\Exception $e) {
|
||||
$log = $this->app->getLog(); // Force Slim to append log to env if not already
|
||||
$env = $this->app->environment();
|
||||
$env['slim.log'] = $log;
|
||||
$env['slim.log']->error($e);
|
||||
$this->app->contentType('text/html');
|
||||
$this->app->response()->status(500);
|
||||
|
||||
+47
-40
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -40,18 +40,14 @@ namespace Slim\Middleware;
|
||||
* and instead serializes/unserializes the $_SESSION global
|
||||
* variable to/from an HTTP cookie.
|
||||
*
|
||||
* If a secret key is provided with this middleware, the HTTP
|
||||
* cookie will be checked for integrity to ensure the client-side
|
||||
* cookie is not changed.
|
||||
*
|
||||
* You should NEVER store sensitive data in a client-side cookie
|
||||
* in any format, encrypted or not. If you need to store sensitive
|
||||
* user information in a session, you should rely on PHP's native
|
||||
* session implementation, or use other middleware to store
|
||||
* session data in a database or alternative server-side cache.
|
||||
* in any format, encrypted (with cookies.encrypt) or not. If you
|
||||
* need to store sensitive user information in a session, you should
|
||||
* rely on PHP's native session implementation, or use other middleware
|
||||
* to store session data in a database or alternative server-side cache.
|
||||
*
|
||||
* Because this class stores serialized session data in an HTTP cookie,
|
||||
* you are inherently limtied to 4 Kb. If you attempt to store
|
||||
* you are inherently limited to 4 Kb. If you attempt to store
|
||||
* more than this amount, serialization will fail.
|
||||
*
|
||||
* @package Slim
|
||||
@@ -68,21 +64,19 @@ class SessionCookie extends \Slim\Middleware
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $settings
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct($settings = array())
|
||||
{
|
||||
$this->settings = array_merge(array(
|
||||
$defaults = array(
|
||||
'expires' => '20 minutes',
|
||||
'path' => '/',
|
||||
'domain' => null,
|
||||
'secure' => false,
|
||||
'httponly' => false,
|
||||
'name' => 'slim_session',
|
||||
'secret' => 'CHANGE_ME',
|
||||
'cipher' => MCRYPT_RIJNDAEL_256,
|
||||
'cipher_mode' => MCRYPT_MODE_CBC
|
||||
), $settings);
|
||||
);
|
||||
$this->settings = array_merge($defaults, $settings);
|
||||
if (is_string($this->settings['expires'])) {
|
||||
$this->settings['expires'] = strtotime($this->settings['expires']);
|
||||
}
|
||||
@@ -119,7 +113,6 @@ class SessionCookie extends \Slim\Middleware
|
||||
|
||||
/**
|
||||
* Load session
|
||||
* @param array $env
|
||||
*/
|
||||
protected function loadSession()
|
||||
{
|
||||
@@ -127,14 +120,14 @@ class SessionCookie extends \Slim\Middleware
|
||||
session_start();
|
||||
}
|
||||
|
||||
$value = \Slim\Http\Util::decodeSecureCookie(
|
||||
$this->app->request()->cookies($this->settings['name']),
|
||||
$this->settings['secret'],
|
||||
$this->settings['cipher'],
|
||||
$this->settings['cipher_mode']
|
||||
);
|
||||
$value = $this->app->getCookie($this->settings['name']);
|
||||
|
||||
if ($value) {
|
||||
$_SESSION = unserialize($value);
|
||||
try {
|
||||
$_SESSION = unserialize($value);
|
||||
} catch (\Exception $e) {
|
||||
$this->app->getLog()->error('Error unserializing session cookie value! ' . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
$_SESSION = array();
|
||||
}
|
||||
@@ -145,57 +138,71 @@ class SessionCookie extends \Slim\Middleware
|
||||
*/
|
||||
protected function saveSession()
|
||||
{
|
||||
$value = \Slim\Http\Util::encodeSecureCookie(
|
||||
serialize($_SESSION),
|
||||
$this->settings['expires'],
|
||||
$this->settings['secret'],
|
||||
$this->settings['cipher'],
|
||||
$this->settings['cipher_mode']
|
||||
);
|
||||
$value = serialize($_SESSION);
|
||||
|
||||
if (strlen($value) > 4096) {
|
||||
$this->app->getLog()->error('WARNING! Slim\Middleware\SessionCookie data size is larger than 4KB. Content save failed.');
|
||||
} else {
|
||||
$this->app->response()->setCookie($this->settings['name'], array(
|
||||
'value' => $value,
|
||||
'domain' => $this->settings['domain'],
|
||||
'path' => $this->settings['path'],
|
||||
'expires' => $this->settings['expires'],
|
||||
'secure' => $this->settings['secure'],
|
||||
'httponly' => $this->settings['httponly']
|
||||
));
|
||||
$this->app->setCookie(
|
||||
$this->settings['name'],
|
||||
$value,
|
||||
$this->settings['expires'],
|
||||
$this->settings['path'],
|
||||
$this->settings['domain'],
|
||||
$this->settings['secure'],
|
||||
$this->settings['httponly']
|
||||
);
|
||||
}
|
||||
session_destroy();
|
||||
// session_destroy();
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Session Handler
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function write($id, $data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
|
||||
Vendored
+46
-18
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.0.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -92,8 +92,8 @@ class Route
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param string $pattern The URL pattern (e.g. "/books/:id")
|
||||
* @param mixed $callable Anything that returns TRUE for is_callable()
|
||||
* @param string $pattern The URL pattern (e.g. "/books/:id")
|
||||
* @param mixed $callable Anything that returns TRUE for is_callable()
|
||||
*/
|
||||
public function __construct($pattern, $callable)
|
||||
{
|
||||
@@ -154,6 +154,11 @@ class Route
|
||||
*/
|
||||
public function setCallable($callable)
|
||||
{
|
||||
$matches = array();
|
||||
if (is_string($callable) && preg_match('!^([^\:]+)\:([[:alnum:]]+)$!', $callable, $matches)) {
|
||||
$callable = array(new $matches[1], $matches[2]);
|
||||
}
|
||||
|
||||
if (!is_callable($callable)) {
|
||||
throw new \InvalidArgumentException('Route callable must be callable');
|
||||
}
|
||||
@@ -194,7 +199,7 @@ class Route
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = (string) $name;
|
||||
$this->name = (string)$name;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,7 +222,7 @@ class Route
|
||||
|
||||
/**
|
||||
* Get route parameter value
|
||||
* @param string $index Name of URL parameter
|
||||
* @param string $index Name of URL parameter
|
||||
* @return string
|
||||
* @throws \InvalidArgumentException If route parameter does not exist at index
|
||||
*/
|
||||
@@ -232,8 +237,8 @@ class Route
|
||||
|
||||
/**
|
||||
* Set route parameter value
|
||||
* @param string $index Name of URL parameter
|
||||
* @param mixed $value The new 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)
|
||||
@@ -285,6 +290,7 @@ class Route
|
||||
|
||||
/**
|
||||
* Detect support for an HTTP method
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsHttpMethod($method)
|
||||
@@ -320,7 +326,7 @@ class Route
|
||||
if (is_callable($middleware)) {
|
||||
$this->middleware[] = $middleware;
|
||||
} elseif (is_array($middleware)) {
|
||||
foreach($middleware as $callable) {
|
||||
foreach ($middleware as $callable) {
|
||||
if (!is_callable($callable)) {
|
||||
throw new \InvalidArgumentException('All Route middleware must be callable');
|
||||
}
|
||||
@@ -347,8 +353,11 @@ class Route
|
||||
public function matches($resourceUri)
|
||||
{
|
||||
//Convert URL params into regex patterns, construct a regex for this route, init params
|
||||
$patternAsRegex = preg_replace_callback('#:([\w]+)\+?#', array($this, 'matchesCallback'),
|
||||
str_replace(')', ')?', (string) $this->pattern));
|
||||
$patternAsRegex = preg_replace_callback(
|
||||
'#:([\w]+)\+?#',
|
||||
array($this, 'matchesCallback'),
|
||||
str_replace(')', ')?', (string)$this->pattern)
|
||||
);
|
||||
if (substr($this->pattern, -1) === '/') {
|
||||
$patternAsRegex .= '?';
|
||||
}
|
||||
@@ -359,7 +368,7 @@ class Route
|
||||
}
|
||||
foreach ($this->paramNames as $name) {
|
||||
if (isset($paramValues[$name])) {
|
||||
if (isset($this->paramNamesPath[ $name ])) {
|
||||
if (isset($this->paramNamesPath[$name])) {
|
||||
$this->params[$name] = explode('/', urldecode($paramValues[$name]));
|
||||
} else {
|
||||
$this->params[$name] = urldecode($paramValues[$name]);
|
||||
@@ -372,17 +381,17 @@ class Route
|
||||
|
||||
/**
|
||||
* Convert a URL parameter (e.g. ":id", ":id+") into a regular expression
|
||||
* @param array URL parameters
|
||||
* @return string Regular expression for URL parameter
|
||||
* @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 (isset($this->conditions[$m[1]])) {
|
||||
return '(?P<' . $m[1] . '>' . $this->conditions[$m[1]] . ')';
|
||||
}
|
||||
if (substr($m[0], -1) === '+') {
|
||||
$this->paramNamesPath[ $m[1] ] = 1;
|
||||
$this->paramNamesPath[$m[1]] = 1;
|
||||
|
||||
return '(?P<' . $m[1] . '>.+)';
|
||||
}
|
||||
@@ -392,7 +401,7 @@ class Route
|
||||
|
||||
/**
|
||||
* Set route name
|
||||
* @param string $name The name of the route
|
||||
* @param string $name The name of the route
|
||||
* @return \Slim\Route
|
||||
*/
|
||||
public function name($name)
|
||||
@@ -404,7 +413,7 @@ class Route
|
||||
|
||||
/**
|
||||
* Merge route conditions
|
||||
* @param array $conditions Key-value array of URL parameter conditions
|
||||
* @param array $conditions Key-value array of URL parameter conditions
|
||||
* @return \Slim\Route
|
||||
*/
|
||||
public function conditions(array $conditions)
|
||||
@@ -413,4 +422,23 @@ class Route
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch route
|
||||
*
|
||||
* This method invokes the route object's callable. If middleware is
|
||||
* registered for the route, each callable middleware is invoked in
|
||||
* the order specified.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch()
|
||||
{
|
||||
foreach ($this->middleware as $mw) {
|
||||
call_user_func_array($mw, array($this));
|
||||
}
|
||||
|
||||
$return = call_user_func_array($this->getCallable(), array_values($this->getParams()));
|
||||
return ($return === false) ? false : true;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+64
-42
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -63,12 +63,18 @@ class Router
|
||||
*/
|
||||
protected $matchedRoutes;
|
||||
|
||||
/**
|
||||
* @var array Array containing all route groups
|
||||
*/
|
||||
protected $routeGroups;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->routes = array();
|
||||
$this->routeGroups = array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +106,7 @@ class Router
|
||||
if ($reload || is_null($this->matchedRoutes)) {
|
||||
$this->matchedRoutes = array();
|
||||
foreach ($this->routes as $route) {
|
||||
if (!$route->supportsHttpMethod($httpMethod)) {
|
||||
if (!$route->supportsHttpMethod($httpMethod) && !$route->supportsHttpMethod("ANY")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -114,25 +120,66 @@ class Router
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a route object to a callback function
|
||||
* @param string $pattern The URL pattern (ie. "/books/:id")
|
||||
* @param mixed $callable Anything that returns TRUE for is_callable()
|
||||
* @return \Slim\Route
|
||||
* Add a route object to the router
|
||||
* @param \Slim\Route $route The Slim Route
|
||||
*/
|
||||
public function map($pattern, $callable)
|
||||
public function map(\Slim\Route $route)
|
||||
{
|
||||
$route = new \Slim\Route($pattern, $callable);
|
||||
list($groupPattern, $groupMiddleware) = $this->processGroups();
|
||||
|
||||
$route->setPattern($groupPattern . $route->getPattern());
|
||||
$this->routes[] = $route;
|
||||
|
||||
return $route;
|
||||
|
||||
foreach ($groupMiddleware as $middleware) {
|
||||
$route->setMiddleware($middleware);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function for processing the group's pattern and middleware
|
||||
* @return array Returns an array with the elements: pattern, middlewareArr
|
||||
*/
|
||||
protected function processGroups()
|
||||
{
|
||||
$pattern = "";
|
||||
$middleware = array();
|
||||
foreach ($this->routeGroups as $group) {
|
||||
$k = key($group);
|
||||
$pattern .= $k;
|
||||
if (is_array($group[$k])) {
|
||||
$middleware = array_merge($middleware, $group[$k]);
|
||||
}
|
||||
}
|
||||
return array($pattern, $middleware);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return int The index of the new group
|
||||
*/
|
||||
public function pushGroup($group, $middleware = array())
|
||||
{
|
||||
return array_push($this->routeGroups, array($group => $middleware));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last route group from the array
|
||||
* @return bool True if successful, else False
|
||||
*/
|
||||
public function popGroup()
|
||||
{
|
||||
return (array_pop($this->routeGroups) !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL for named route
|
||||
* @param string $name The name of the route
|
||||
* @param array 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
|
||||
* @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())
|
||||
{
|
||||
@@ -140,45 +187,20 @@ class Router
|
||||
throw new \RuntimeException('Named route not found for name: ' . $name);
|
||||
}
|
||||
$search = array();
|
||||
foreach (array_keys($params) as $key) {
|
||||
$search[] = '#:' . $key . '\+?(?!\w)#';
|
||||
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
|
||||
return preg_replace('#\(/?:.+\)|\(|\)#', '', $pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch route
|
||||
*
|
||||
* 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 \Slim\Route $route The route object
|
||||
* @return bool Was route callable invoked successfully?
|
||||
*/
|
||||
public function dispatch(\Slim\Route $route)
|
||||
{
|
||||
$this->currentRoute = $route;
|
||||
|
||||
//Invoke middleware
|
||||
foreach ($route->getMiddleware() as $mw) {
|
||||
call_user_func_array($mw, array($route));
|
||||
}
|
||||
|
||||
//Invoke callable
|
||||
call_user_func_array($route->getCallable(), array_values($route->getParams()));
|
||||
|
||||
return true;
|
||||
//Remove remnants of unpopulated, trailing optional pattern segments, escaped special characters
|
||||
return preg_replace('#\(/?:.+\)|\(|\)|\\\\#', '', $pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add named route
|
||||
* @param string $name The route name
|
||||
* @param \Slim\Route $route The route object
|
||||
* @throws \RuntimeException If a named route already exists with the same name
|
||||
* @throws \RuntimeException If a named route already exists with the same name
|
||||
*/
|
||||
public function addNamedRoute($name, \Slim\Route $route)
|
||||
{
|
||||
|
||||
Vendored
+233
-141
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -40,16 +40,26 @@ if (!extension_loaded('mcrypt')) {
|
||||
|
||||
/**
|
||||
* Slim
|
||||
* @package Slim
|
||||
* @author Josh Lockhart
|
||||
* @since 1.0.0
|
||||
* @package Slim
|
||||
* @author Josh Lockhart
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @property \Slim\Environment $environment
|
||||
* @property \Slim\Http\Response $response
|
||||
* @property \Slim\Http\Request $request
|
||||
* @property \Slim\Router $router
|
||||
*/
|
||||
class Slim
|
||||
{
|
||||
/**
|
||||
* @const string
|
||||
*/
|
||||
const VERSION = '2.2.0';
|
||||
const VERSION = '2.4.0';
|
||||
|
||||
/**
|
||||
* @var \Slim\Helper\Set
|
||||
*/
|
||||
public $container;
|
||||
|
||||
/**
|
||||
* @var array[\Slim]
|
||||
@@ -61,41 +71,6 @@ class Slim
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $environment;
|
||||
|
||||
/**
|
||||
* @var \Slim\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var \Slim\Http\Response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* @var \Slim\Router
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* @var \Slim\View
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $mode;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@@ -173,44 +148,111 @@ class Slim
|
||||
* Constructor
|
||||
* @param array $userSettings Associative array of application settings
|
||||
*/
|
||||
public function __construct($userSettings = array())
|
||||
public function __construct(array $userSettings = array())
|
||||
{
|
||||
// Setup Slim application
|
||||
$this->settings = array_merge(static::getDefaultSettings(), $userSettings);
|
||||
$this->environment = \Slim\Environment::getInstance();
|
||||
$this->request = new \Slim\Http\Request($this->environment);
|
||||
$this->response = new \Slim\Http\Response();
|
||||
$this->router = new \Slim\Router();
|
||||
// Setup IoC container
|
||||
$this->container = new \Slim\Helper\Set();
|
||||
$this->container['settings'] = array_merge(static::getDefaultSettings(), $userSettings);
|
||||
|
||||
// Default environment
|
||||
$this->container->singleton('environment', function ($c) {
|
||||
return \Slim\Environment::getInstance();
|
||||
});
|
||||
|
||||
// Default request
|
||||
$this->container->singleton('request', function ($c) {
|
||||
return new \Slim\Http\Request($c['environment']);
|
||||
});
|
||||
|
||||
// Default response
|
||||
$this->container->singleton('response', function ($c) {
|
||||
return new \Slim\Http\Response();
|
||||
});
|
||||
|
||||
// Default router
|
||||
$this->container->singleton('router', function ($c) {
|
||||
return new \Slim\Router();
|
||||
});
|
||||
|
||||
// Default view
|
||||
$this->container->singleton('view', function ($c) {
|
||||
$viewClass = $c['settings']['view'];
|
||||
$templatesPath = $c['settings']['templates.path'];
|
||||
|
||||
$view = ($viewClass instanceOf \Slim\View) ? $viewClass : new $viewClass;
|
||||
$view->setTemplatesDirectory($templatesPath);
|
||||
return $view;
|
||||
});
|
||||
|
||||
// Default log writer
|
||||
$this->container->singleton('logWriter', function ($c) {
|
||||
$logWriter = $c['settings']['log.writer'];
|
||||
|
||||
return is_object($logWriter) ? $logWriter : new \Slim\LogWriter($c['environment']['slim.errors']);
|
||||
});
|
||||
|
||||
// Default log
|
||||
$this->container->singleton('log', function ($c) {
|
||||
$log = new \Slim\Log($c['logWriter']);
|
||||
$log->setEnabled($c['settings']['log.enabled']);
|
||||
$log->setLevel($c['settings']['log.level']);
|
||||
$env = $c['environment'];
|
||||
$env['slim.log'] = $log;
|
||||
|
||||
return $log;
|
||||
});
|
||||
|
||||
// Default mode
|
||||
$this->container['mode'] = function ($c) {
|
||||
$mode = $c['settings']['mode'];
|
||||
|
||||
if (isset($_ENV['SLIM_MODE'])) {
|
||||
$mode = $_ENV['SLIM_MODE'];
|
||||
} else {
|
||||
$envMode = getenv('SLIM_MODE');
|
||||
if ($envMode !== false) {
|
||||
$mode = $envMode;
|
||||
}
|
||||
}
|
||||
|
||||
return $mode;
|
||||
};
|
||||
|
||||
// Define default middleware stack
|
||||
$this->middleware = array($this);
|
||||
$this->add(new \Slim\Middleware\Flash());
|
||||
$this->add(new \Slim\Middleware\MethodOverride());
|
||||
|
||||
// Determine application mode
|
||||
$this->getMode();
|
||||
|
||||
// Setup view
|
||||
$this->view($this->config('view'));
|
||||
|
||||
// Make default if first instance
|
||||
if (is_null(static::getInstance())) {
|
||||
$this->setName('default');
|
||||
}
|
||||
}
|
||||
|
||||
// Set default logger that writes to stderr (may be overridden with middleware)
|
||||
$logWriter = $this->config('log.writer');
|
||||
if (!$logWriter) {
|
||||
$logWriter = new \Slim\LogWriter($this->environment['slim.errors']);
|
||||
}
|
||||
$log = new \Slim\Log($logWriter);
|
||||
$log->setEnabled($this->config('log.enabled'));
|
||||
$log->setLevel($this->config('log.level'));
|
||||
$this->environment['slim.log'] = $log;
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->container[$name];
|
||||
}
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->container[$name] = $value;
|
||||
}
|
||||
|
||||
public function __isset($name)
|
||||
{
|
||||
return isset($this->container[$name]);
|
||||
}
|
||||
|
||||
public function __unset($name)
|
||||
{
|
||||
unset($this->container[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get application instance by name
|
||||
* @param string $name The name of the Slim application
|
||||
* @return \Slim|null
|
||||
* @return \Slim\Slim|null
|
||||
*/
|
||||
public static function getInstance($name = 'default')
|
||||
{
|
||||
@@ -255,6 +297,7 @@ class Slim
|
||||
'templates.path' => './templates',
|
||||
'view' => '\Slim\View',
|
||||
// Cookies
|
||||
'cookies.encrypt' => false,
|
||||
'cookies.lifetime' => '20 minutes',
|
||||
'cookies.path' => '/',
|
||||
'cookies.domain' => null,
|
||||
@@ -297,7 +340,9 @@ class Slim
|
||||
return isset($this->settings[$name]) ? $this->settings[$name] : null;
|
||||
}
|
||||
} else {
|
||||
$this->settings[$name] = $value;
|
||||
$settings = $this->settings;
|
||||
$settings[$name] = $value;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,19 +361,6 @@ class Slim
|
||||
*/
|
||||
public function getMode()
|
||||
{
|
||||
if (!isset($this->mode)) {
|
||||
if (isset($_ENV['SLIM_MODE'])) {
|
||||
$this->mode = $_ENV['SLIM_MODE'];
|
||||
} else {
|
||||
$envMode = getenv('SLIM_MODE');
|
||||
if ($envMode !== false) {
|
||||
$this->mode = $envMode;
|
||||
} else {
|
||||
$this->mode = $this->config('mode');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
@@ -361,7 +393,7 @@ class Slim
|
||||
*/
|
||||
public function getLog()
|
||||
{
|
||||
return $this->environment['slim.log'];
|
||||
return $this->log;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@@ -369,7 +401,7 @@ class Slim
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Add GET|POST|PUT|DELETE route
|
||||
* Add GET|POST|PUT|PATCH|DELETE route
|
||||
*
|
||||
* Adds a new route to the router with associated callable. This
|
||||
* route will only be invoked when the HTTP request's method matches
|
||||
@@ -402,7 +434,8 @@ class Slim
|
||||
{
|
||||
$pattern = array_shift($args);
|
||||
$callable = array_pop($args);
|
||||
$route = $this->router->map($pattern, $callable);
|
||||
$route = new \Slim\Route($pattern, $callable);
|
||||
$this->router->map($route);
|
||||
if (count($args) > 0) {
|
||||
$route->setMiddleware($args);
|
||||
}
|
||||
@@ -458,6 +491,18 @@ class Slim
|
||||
return $this->mapRoute($args)->via(\Slim\Http\Request::METHOD_PUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add PATCH route
|
||||
* @see mapRoute()
|
||||
* @return \Slim\Route
|
||||
*/
|
||||
public function patch()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
return $this->mapRoute($args)->via(\Slim\Http\Request::METHOD_PATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add DELETE route
|
||||
* @see mapRoute()
|
||||
@@ -482,6 +527,40 @@ class Slim
|
||||
return $this->mapRoute($args)->via(\Slim\Http\Request::METHOD_OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Accepts the same parameters as a standard route so:
|
||||
* (pattern, middleware1, middleware2, ..., $callback)
|
||||
*/
|
||||
public function group()
|
||||
{
|
||||
$args = func_get_args();
|
||||
$pattern = array_shift($args);
|
||||
$callable = array_pop($args);
|
||||
$this->router->pushGroup($pattern, $args);
|
||||
if (is_callable($callable)) {
|
||||
call_user_func($callable);
|
||||
}
|
||||
$this->router->popGroup();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add route for any HTTP method
|
||||
* @see mapRoute()
|
||||
* @return \Slim\Route
|
||||
*/
|
||||
public function any()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
return $this->mapRoute($args)->via("ANY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Found Handler
|
||||
*
|
||||
@@ -503,12 +582,13 @@ class Slim
|
||||
*
|
||||
* @param mixed $callable Anything that returns true for is_callable()
|
||||
*/
|
||||
public function notFound( $callable = null ) {
|
||||
if ( is_callable($callable) ) {
|
||||
public function notFound ($callable = null)
|
||||
{
|
||||
if (is_callable($callable)) {
|
||||
$this->notFound = $callable;
|
||||
} else {
|
||||
ob_start();
|
||||
if ( is_callable($this->notFound) ) {
|
||||
if (is_callable($this->notFound)) {
|
||||
call_user_func($this->notFound);
|
||||
} else {
|
||||
call_user_func(array($this, 'defaultNotFound'));
|
||||
@@ -566,7 +646,7 @@ class Slim
|
||||
protected function callErrorHandler($argument = null)
|
||||
{
|
||||
ob_start();
|
||||
if ( is_callable($this->error) ) {
|
||||
if (is_callable($this->error)) {
|
||||
call_user_func_array($this->error, array($argument));
|
||||
} else {
|
||||
call_user_func_array(array($this, 'defaultError'), array($argument));
|
||||
@@ -653,7 +733,7 @@ class Slim
|
||||
/**
|
||||
* Render a template
|
||||
*
|
||||
* Call this method within a GET, POST, PUT, DELETE, NOT FOUND, or ERROR
|
||||
* Call this method within a GET, POST, PUT, PATCH, DELETE, NOT FOUND, or ERROR
|
||||
* callable to render a template whose output is appended to the
|
||||
* current HTTP response body. How the template is rendered is
|
||||
* delegated to the current View.
|
||||
@@ -667,7 +747,6 @@ class Slim
|
||||
if (!is_null($status)) {
|
||||
$this->response->status($status);
|
||||
}
|
||||
$this->view->setTemplatesDirectory($this->config('templates.path'));
|
||||
$this->view->appendData($data);
|
||||
$this->view->display($template);
|
||||
}
|
||||
@@ -692,8 +771,8 @@ class Slim
|
||||
public function lastModified($time)
|
||||
{
|
||||
if (is_integer($time)) {
|
||||
$this->response['Last-Modified'] = date(DATE_RFC1123, $time);
|
||||
if ($time === strtotime($this->request->headers('IF_MODIFIED_SINCE'))) {
|
||||
$this->response->headers->set('Last-Modified', gmdate('D, d M Y H:i:s T', $time));
|
||||
if ($time === strtotime($this->request->headers->get('IF_MODIFIED_SINCE'))) {
|
||||
$this->halt(304);
|
||||
}
|
||||
} else {
|
||||
@@ -726,11 +805,13 @@ class Slim
|
||||
|
||||
//Set etag value
|
||||
$value = '"' . $value . '"';
|
||||
if ($type === 'weak') $value = 'W/'.$value;
|
||||
if ($type === 'weak') {
|
||||
$value = 'W/'.$value;
|
||||
}
|
||||
$this->response['ETag'] = $value;
|
||||
|
||||
//Check conditional GET
|
||||
if ($etagsHeader = $this->request->headers('IF_NONE_MATCH')) {
|
||||
if ($etagsHeader = $this->request->headers->get('IF_NONE_MATCH')) {
|
||||
$etags = preg_split('@\s*,\s*@', $etagsHeader);
|
||||
if (in_array($value, $etags) || in_array('*', $etags)) {
|
||||
$this->halt(304);
|
||||
@@ -756,7 +837,7 @@ class Slim
|
||||
if (is_string($time)) {
|
||||
$time = strtotime($time);
|
||||
}
|
||||
$this->response['Expires'] = gmdate(DATE_RFC1123, $time);
|
||||
$this->response->headers->set('Expires', gmdate('D, d M Y H:i:s T', $time));
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@@ -764,7 +845,7 @@ class Slim
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Set unencrypted HTTP cookie
|
||||
* Set HTTP cookie to be sent with the HTTP response
|
||||
*
|
||||
* @param string $name The cookie name
|
||||
* @param string $value The cookie value
|
||||
@@ -779,32 +860,52 @@ class Slim
|
||||
*/
|
||||
public function setCookie($name, $value, $time = null, $path = null, $domain = null, $secure = null, $httponly = null)
|
||||
{
|
||||
$this->response->setCookie($name, array(
|
||||
$settings = array(
|
||||
'value' => $value,
|
||||
'expires' => is_null($time) ? $this->config('cookies.lifetime') : $time,
|
||||
'path' => is_null($path) ? $this->config('cookies.path') : $path,
|
||||
'domain' => is_null($domain) ? $this->config('cookies.domain') : $domain,
|
||||
'secure' => is_null($secure) ? $this->config('cookies.secure') : $secure,
|
||||
'httponly' => is_null($httponly) ? $this->config('cookies.httponly') : $httponly
|
||||
));
|
||||
);
|
||||
$this->response->cookies->set($name, $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of unencrypted HTTP cookie
|
||||
* Get value of HTTP cookie from the current HTTP request
|
||||
*
|
||||
* Return the value of a cookie from the current HTTP request,
|
||||
* or return NULL if cookie does not exist. Cookies created during
|
||||
* the current request will not be available until the next request.
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $deleteIfInvalid
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCookie($name)
|
||||
public function getCookie($name, $deleteIfInvalid = true)
|
||||
{
|
||||
return $this->request->cookies($name);
|
||||
// Get cookie value
|
||||
$value = $this->request->cookies->get($name);
|
||||
|
||||
// Decode if encrypted
|
||||
if ($this->config('cookies.encrypt')) {
|
||||
$value = \Slim\Http\Util::decodeSecureCookie(
|
||||
$value,
|
||||
$this->config('cookies.secret_key'),
|
||||
$this->config('cookies.cipher'),
|
||||
$this->config('cookies.cipher_mode')
|
||||
);
|
||||
if ($value === false && $deleteIfInvalid) {
|
||||
$this->deleteCookie($name);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! Use `setCookie` with the `cookies.encrypt` app setting set to `true`.
|
||||
*
|
||||
* Set encrypted HTTP cookie
|
||||
*
|
||||
* @param string $name The cookie name
|
||||
@@ -818,23 +919,14 @@ class Slim
|
||||
* HTTPS connection from the client
|
||||
* @param bool $httponly When TRUE the cookie will be made accessible only through the HTTP protocol
|
||||
*/
|
||||
public function setEncryptedCookie($name, $value, $expires = null, $path = null, $domain = null, $secure = null, $httponly = null)
|
||||
public function setEncryptedCookie($name, $value, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false)
|
||||
{
|
||||
$expires = is_null($expires) ? $this->config('cookies.lifetime') : $expires;
|
||||
if (is_string($expires)) {
|
||||
$expires = strtotime($expires);
|
||||
}
|
||||
$secureValue = \Slim\Http\Util::encodeSecureCookie(
|
||||
$value,
|
||||
$expires,
|
||||
$this->config('cookies.secret_key'),
|
||||
$this->config('cookies.cipher'),
|
||||
$this->config('cookies.cipher_mode')
|
||||
);
|
||||
$this->setCookie($name, $secureValue, $expires, $path, $domain, $secure, $httponly);
|
||||
$this->setCookie($name, $value, $expires, $path, $domain, $secure, $httponly);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! Use `getCookie` with the `cookies.encrypt` app setting set to `true`.
|
||||
*
|
||||
* Get value of encrypted HTTP cookie
|
||||
*
|
||||
* Return the value of an encrypted cookie from the current HTTP request,
|
||||
@@ -842,21 +934,12 @@ class Slim
|
||||
* the current request will not be available until the next request.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string|false
|
||||
* @param bool $deleteIfInvalid
|
||||
* @return string|bool
|
||||
*/
|
||||
public function getEncryptedCookie($name, $deleteIfInvalid = true)
|
||||
{
|
||||
$value = \Slim\Http\Util::decodeSecureCookie(
|
||||
$this->request->cookies($name),
|
||||
$this->config('cookies.secret_key'),
|
||||
$this->config('cookies.cipher'),
|
||||
$this->config('cookies.cipher_mode')
|
||||
);
|
||||
if ($value === false && $deleteIfInvalid) {
|
||||
$this->deleteCookie($name);
|
||||
}
|
||||
|
||||
return $value;
|
||||
return $this->getCookie($name, $deleteIfInvalid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -877,12 +960,13 @@ class Slim
|
||||
*/
|
||||
public function deleteCookie($name, $path = null, $domain = null, $secure = null, $httponly = null)
|
||||
{
|
||||
$this->response->deleteCookie($name, array(
|
||||
$settings = array(
|
||||
'domain' => is_null($domain) ? $this->config('cookies.domain') : $domain,
|
||||
'path' => is_null($path) ? $this->config('cookies.path') : $path,
|
||||
'secure' => is_null($secure) ? $this->config('cookies.secure') : $secure,
|
||||
'httponly' => is_null($httponly) ? $this->config('cookies.httponly') : $httponly
|
||||
));
|
||||
);
|
||||
$this->response->cookies->remove($name, $settings);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@@ -968,16 +1052,16 @@ class Slim
|
||||
*/
|
||||
public function contentType($type)
|
||||
{
|
||||
$this->response['Content-Type'] = $type;
|
||||
$this->response->headers->set('Content-Type', $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HTTP response status code
|
||||
* @param int $status The HTTP response status code
|
||||
* @param int $code The HTTP response status code
|
||||
*/
|
||||
public function status($code)
|
||||
{
|
||||
$this->response->status($code);
|
||||
$this->response->setStatus($code);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1071,7 +1155,7 @@ class Slim
|
||||
/**
|
||||
* Invoke hook
|
||||
* @param string $name The hook name
|
||||
* @param mixed $hookArgs (Optional) Argument for hooked functions
|
||||
* @param mixed $hookArg (Optional) Argument for hooked functions
|
||||
*/
|
||||
public function applyHook($name, $hookArg = null)
|
||||
{
|
||||
@@ -1165,16 +1249,22 @@ class Slim
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
//set_error_handler(array('\Slim\Slim', 'handleErrors')); //Espo: no needs to use this handler
|
||||
//set_error_handler(array('\Slim\Slim', 'handleErrors')); //Espo: no needs to use this handler
|
||||
|
||||
//Apply final outer middleware layers
|
||||
//$this->add(new \Slim\Middleware\PrettyExceptions()); //Espo: no needs to use this handler
|
||||
if ($this->config('debug')) {
|
||||
//Apply pretty exceptions only in debug to avoid accidental information leakage in production
|
||||
//$this->add(new \Slim\Middleware\PrettyExceptions()); //Espo: no needs to use this handler
|
||||
}
|
||||
|
||||
//Invoke middleware and application stack
|
||||
$this->middleware[0]->call();
|
||||
|
||||
//Fetch status, header, and body
|
||||
list($status, $header, $body) = $this->response->finalize();
|
||||
list($status, $headers, $body) = $this->response->finalize();
|
||||
|
||||
// Serialize cookies (with optional encryption)
|
||||
\Slim\Http\Util::serializeCookies($headers, $this->response->cookies, $this->settings);
|
||||
|
||||
//Send headers
|
||||
if (headers_sent() === false) {
|
||||
@@ -1186,7 +1276,7 @@ class Slim
|
||||
}
|
||||
|
||||
//Send headers
|
||||
foreach ($header as $name => $value) {
|
||||
foreach ($headers as $name => $value) {
|
||||
$hValues = explode("\n", $value);
|
||||
foreach ($hValues as $hVal) {
|
||||
header("$name: $hVal", false);
|
||||
@@ -1194,8 +1284,10 @@ class Slim
|
||||
}
|
||||
}
|
||||
|
||||
//Send body
|
||||
echo $body;
|
||||
//Send body, but only if it isn't a HEAD request
|
||||
if (!$this->request->isHead()) {
|
||||
echo $body;
|
||||
}
|
||||
|
||||
restore_error_handler();
|
||||
}
|
||||
@@ -1219,7 +1311,7 @@ class Slim
|
||||
foreach ($matchedRoutes as $route) {
|
||||
try {
|
||||
$this->applyHook('slim.before.dispatch');
|
||||
$dispatched = $this->router->dispatch($route);
|
||||
$dispatched = $route->dispatch();
|
||||
$this->applyHook('slim.after.dispatch');
|
||||
if ($dispatched) {
|
||||
break;
|
||||
@@ -1229,7 +1321,7 @@ class Slim
|
||||
}
|
||||
}
|
||||
if (!$dispatched) {
|
||||
$this->notFound();
|
||||
$this->notFound();
|
||||
}
|
||||
$this->applyHook('slim.after.router');
|
||||
$this->stop();
|
||||
@@ -1264,16 +1356,16 @@ class Slim
|
||||
* @param string $errstr The error message
|
||||
* @param string $errfile The absolute path to the affected file
|
||||
* @param int $errline The line number of the error in the affected file
|
||||
* @return true
|
||||
* @return bool
|
||||
* @throws \ErrorException
|
||||
*/
|
||||
public static function handleErrors($errno, $errstr = '', $errfile = '', $errline = '')
|
||||
{
|
||||
if (error_reporting() & $errno) {
|
||||
throw new \ErrorException($errstr, $errno, 0, $errfile, $errline);
|
||||
if (!($errno & error_reporting())) {
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
throw new \ErrorException($errstr, $errno, 0, $errfile, $errline);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1304,6 +1396,6 @@ class Slim
|
||||
protected function defaultError($e)
|
||||
{
|
||||
$this->getLog()->error($e);
|
||||
echo self::generateTemplateMarkup('Error', '<p>A website error has occured. The website administrator has been notified of the issue. Sorry for the temporary inconvenience.</p>');
|
||||
echo self::generateTemplateMarkup('Error', '<p>A website error has occurred. The website administrator has been notified of the issue. Sorry for the temporary inconvenience.</p>');
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+159
-93
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
* @package Slim
|
||||
*
|
||||
* MIT LICENSE
|
||||
@@ -50,95 +50,166 @@ namespace Slim;
|
||||
class View
|
||||
{
|
||||
/**
|
||||
* @var string Absolute or relative filesystem path to a specific template
|
||||
*
|
||||
* DEPRECATION WARNING!
|
||||
* This variable will be removed in the near future
|
||||
* Data available to the view templates
|
||||
* @var \Slim\Helper\Set
|
||||
*/
|
||||
protected $templatePath = '';
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var array Associative array of template variables
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* @var string Absolute or relative path to the application's templates directory
|
||||
* Path to templates base directory (without trailing slash)
|
||||
* @var string
|
||||
*/
|
||||
protected $templatesDirectory;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* This is empty but may be implemented in a subclass
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->data = new \Slim\Helper\Set();
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Data methods
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Does view data have value with key?
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return $this->data->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data
|
||||
* @param string|null $key
|
||||
* @return mixed If key is null, array of template data;
|
||||
* If key exists, value of datum with key;
|
||||
* If key does not exist, null;
|
||||
* Return view data value with key
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->data->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set view data value with key
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->data->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set view data value as Closure with key
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function keep($key, Closure $value)
|
||||
{
|
||||
$this->data->keep($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return view data
|
||||
* @return array
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->data->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace view data
|
||||
* @param array $data
|
||||
*/
|
||||
public function replace(array $data)
|
||||
{
|
||||
$this->data->replace($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear view data
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->data->clear();
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Legacy data methods
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* Get data from view
|
||||
*/
|
||||
public function getData($key = null)
|
||||
{
|
||||
if (!is_null($key)) {
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||
} else {
|
||||
return $this->data;
|
||||
return $this->data->all();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* If two arguments:
|
||||
* A single datum with key is assigned value;
|
||||
*
|
||||
* $view->setData('color', 'red');
|
||||
*
|
||||
* If one argument:
|
||||
* Replace all data with provided array keys and values;
|
||||
*
|
||||
* $view->setData(array('color' => 'red', 'number' => 1));
|
||||
*
|
||||
* @param mixed
|
||||
* @param mixed
|
||||
* @throws InvalidArgumentException If incorrect method signature
|
||||
* Set data for view
|
||||
*/
|
||||
public function setData()
|
||||
{
|
||||
$args = func_get_args();
|
||||
if (count($args) === 1 && is_array($args[0])) {
|
||||
$this->data = $args[0];
|
||||
$this->data->replace($args[0]);
|
||||
} elseif (count($args) === 2) {
|
||||
$this->data[(string) $args[0]] = $args[1];
|
||||
// Ensure original behavior is maintained. DO NOT invoke stored Closures.
|
||||
if (is_object($args[1]) && method_exists($args[1], '__invoke')) {
|
||||
$this->data->set($args[0], $this->data->protect($args[1]));
|
||||
} else {
|
||||
$this->data->set($args[0], $args[1]);
|
||||
}
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Cannot set View data with provided arguments. Usage: `View::setData( $key, $value );` or `View::setData([ key => value, ... ]);`');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append new data to existing template data
|
||||
* @param array
|
||||
* @throws InvalidArgumentException If not given an array argument
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* Append data to view
|
||||
* @param array $data
|
||||
*/
|
||||
public function appendData($data)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
throw new \InvalidArgumentException('Cannot append view data. Expected array argument.');
|
||||
}
|
||||
$this->data = array_merge($this->data, $data);
|
||||
$this->data->replace($data);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Resolve template paths
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Set the base directory that contains view templates
|
||||
* @param string $directory
|
||||
* @throws \InvalidArgumentException If directory is not a directory
|
||||
*/
|
||||
public function setTemplatesDirectory($directory)
|
||||
{
|
||||
$this->templatesDirectory = rtrim($directory, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get templates directory
|
||||
* @return string|null Path to templates directory without trailing slash;
|
||||
* Returns null if templates directory not set;
|
||||
* Get templates base directory
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplatesDirectory()
|
||||
{
|
||||
@@ -146,70 +217,65 @@ class View
|
||||
}
|
||||
|
||||
/**
|
||||
* Set templates directory
|
||||
* @param string $dir
|
||||
* Get fully qualified path to template file using templates base directory
|
||||
* @param string $file The template file pathname relative to templates base directory
|
||||
* @return string
|
||||
*/
|
||||
public function setTemplatesDirectory($dir)
|
||||
public function getTemplatePathname($file)
|
||||
{
|
||||
$this->templatesDirectory = rtrim($dir, '/');
|
||||
return $this->templatesDirectory . DIRECTORY_SEPARATOR . ltrim($file, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set template
|
||||
* @param string $template
|
||||
* @throws RuntimeException If template file does not exist
|
||||
*
|
||||
* DEPRECATION WARNING!
|
||||
* This method will be removed in the near future.
|
||||
*/
|
||||
public function setTemplate($template)
|
||||
{
|
||||
$this->templatePath = $this->getTemplatesDirectory() . '/' . ltrim($template, '/');
|
||||
if (!file_exists($this->templatePath)) {
|
||||
throw new \RuntimeException('View cannot render template `' . $this->templatePath . '`. Template does not exist.');
|
||||
}
|
||||
}
|
||||
/********************************************************************************
|
||||
* Rendering
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Display template
|
||||
*
|
||||
* This method echoes the rendered template to the current output buffer
|
||||
*
|
||||
* @param string $template Pathname of template file relative to templates directoy
|
||||
*/
|
||||
public function display($template)
|
||||
{
|
||||
echo $this->fetch($template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch rendered template
|
||||
*
|
||||
* This method returns the rendered template
|
||||
*
|
||||
* @param string $template Pathname of template file relative to templates directory
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($template)
|
||||
{
|
||||
return $this->render($template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render template
|
||||
*
|
||||
* @param string $template Pathname of template file relative to templates directory
|
||||
* @return string
|
||||
*
|
||||
* DEPRECATION WARNING!
|
||||
* Use `\Slim\View::fetch` to return a rendered template instead of `\Slim\View::render`.
|
||||
* @param array $data Any additonal data to be passed to the template.
|
||||
*/
|
||||
public function render($template)
|
||||
public function display($template, $data = null)
|
||||
{
|
||||
$this->setTemplate($template);
|
||||
extract($this->data);
|
||||
echo $this->fetch($template, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the contents of a rendered template file
|
||||
*
|
||||
* @param string $template The template pathname, relative to the template base directory
|
||||
* @param array $data Any additonal data to be passed to the template.
|
||||
* @return string The rendered template
|
||||
*/
|
||||
public function fetch($template, $data = null)
|
||||
{
|
||||
return $this->render($template, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a template file
|
||||
*
|
||||
* NOTE: This method should be overridden by custom view subclasses
|
||||
*
|
||||
* @param string $template The template pathname, relative to the template base directory
|
||||
* @param array $data Any additonal data to be passed to the template.
|
||||
* @return string The rendered template
|
||||
* @throws \RuntimeException If resolved template pathname is not a valid file
|
||||
*/
|
||||
protected function render($template, $data = null)
|
||||
{
|
||||
$templatePathname = $this->getTemplatePathname($template);
|
||||
if (!is_file($templatePathname)) {
|
||||
throw new \RuntimeException("View cannot render `$template` because the template does not exist");
|
||||
}
|
||||
|
||||
$data = array_merge($this->data->all(), (array) $data);
|
||||
extract($data);
|
||||
ob_start();
|
||||
require $this->templatePath;
|
||||
require $templatePathname;
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
Vendored
+3
@@ -15,6 +15,9 @@
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mcrypt": "Required for HTTP cookie encryption"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Slim": "." }
|
||||
}
|
||||
|
||||
Vendored
+30
-13
@@ -26,13 +26,15 @@ $app = new \Slim\Slim();
|
||||
*
|
||||
* Here we define several Slim application routes that respond
|
||||
* to appropriate HTTP request methods. In this example, the second
|
||||
* argument for `Slim::get`, `Slim::post`, `Slim::put`, and `Slim::delete`
|
||||
* argument for `Slim::get`, `Slim::post`, `Slim::put`, `Slim::patch`, and `Slim::delete`
|
||||
* is an anonymous function.
|
||||
*/
|
||||
|
||||
// GET route
|
||||
$app->get('/', function () {
|
||||
$template = <<<EOT
|
||||
$app->get(
|
||||
'/',
|
||||
function () {
|
||||
$template = <<<EOT
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -125,23 +127,38 @@ $app->get('/', function () {
|
||||
</body>
|
||||
</html>
|
||||
EOT;
|
||||
echo $template;
|
||||
});
|
||||
echo $template;
|
||||
}
|
||||
);
|
||||
|
||||
// POST route
|
||||
$app->post('/post', function () {
|
||||
echo 'This is a POST route';
|
||||
});
|
||||
$app->post(
|
||||
'/post',
|
||||
function () {
|
||||
echo 'This is a POST route';
|
||||
}
|
||||
);
|
||||
|
||||
// PUT route
|
||||
$app->put('/put', function () {
|
||||
echo 'This is a PUT route';
|
||||
$app->put(
|
||||
'/put',
|
||||
function () {
|
||||
echo 'This is a PUT route';
|
||||
}
|
||||
);
|
||||
|
||||
// PATCH route
|
||||
$app->patch('/patch', function () {
|
||||
echo 'This is a PATCH route';
|
||||
});
|
||||
|
||||
// DELETE route
|
||||
$app->delete('/delete', function () {
|
||||
echo 'This is a DELETE route';
|
||||
});
|
||||
$app->delete(
|
||||
'/delete',
|
||||
function () {
|
||||
echo 'This is a DELETE route';
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Step 4: Run the Slim application
|
||||
|
||||
+22
-2
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -43,6 +43,8 @@ class EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$_SERVER['DOCUMENT_ROOT'] = '/var/www';
|
||||
$_SERVER['SCRIPT_FILENAME'] = '/var/www/foo/index.php';
|
||||
$_SERVER['SERVER_NAME'] = 'slim';
|
||||
$_SERVER['SERVER_PORT'] = '80';
|
||||
$_SERVER['SCRIPT_NAME'] = '/foo/index.php';
|
||||
@@ -106,6 +108,7 @@ class EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testParsesPathsWithoutUrlRewriteInRootDirectory()
|
||||
{
|
||||
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
|
||||
$_SERVER['REQUEST_URI'] = '/index.php/bar/xyz';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$env = \Slim\Environment::getInstance(true);
|
||||
@@ -123,6 +126,7 @@ class EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testParsesPathsWithoutUrlRewriteInRootDirectoryForAppRootUri()
|
||||
{
|
||||
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
|
||||
$_SERVER['REQUEST_URI'] = '/index.php';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
unset($_SERVER['PATH_INFO']);
|
||||
@@ -157,6 +161,7 @@ class EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testParsesPathsWithUrlRewriteInRootDirectory()
|
||||
{
|
||||
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['REQUEST_URI'] = '/bar/xyz';
|
||||
unset($_SERVER['PATH_INFO']);
|
||||
@@ -175,6 +180,7 @@ class EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testParsesPathsWithUrlRewriteInRootDirectoryForAppRootUri()
|
||||
{
|
||||
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
|
||||
$_SERVER['REQUEST_URI'] = '/';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
unset($_SERVER['PATH_INFO']);
|
||||
@@ -224,6 +230,7 @@ class EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testPathInfoRetainsUrlEncodedCharacters()
|
||||
{
|
||||
$_SERVER['SCRIPT_FILENAME'] = '/var/www/index.php';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
$_SERVER['REQUEST_URI'] = '/foo/%23bar'; //<-- URL-encoded "#bar"
|
||||
$env = \Slim\Environment::getInstance(true);
|
||||
@@ -292,7 +299,20 @@ class EnvironmentTest extends PHPUnit_Framework_TestCase
|
||||
$env = \Slim\Environment::getInstance(true);
|
||||
$this->assertEquals('text/csv', $env['CONTENT_TYPE']);
|
||||
$this->assertEquals('100', $env['CONTENT_LENGTH']);
|
||||
$this->assertEquals('XmlHttpRequest', $env['X_REQUESTED_WITH']);
|
||||
$this->assertEquals('XmlHttpRequest', $env['HTTP_X_REQUESTED_WITH']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests X-HTTP-Method-Override is allowed through unmolested.
|
||||
*
|
||||
* Pre-conditions:
|
||||
* X_HTTP_METHOD_OVERRIDE is sent in client HTTP request;
|
||||
* X_HTTP_METHOD_OVERRIDE is not empty;
|
||||
*/
|
||||
public function testSetsHttpMethodOverrideHeader() {
|
||||
$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'DELETE';
|
||||
$env = \Slim\Environment::getInstance(true);
|
||||
$this->assertEquals('DELETE', $env['HTTP_X_HTTP_METHOD_OVERRIDE']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+19
-103
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -32,112 +32,28 @@
|
||||
|
||||
class HeadersTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test constructor without args
|
||||
*/
|
||||
public function testConstructorWithoutArgs()
|
||||
public function testNormalizesKey()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$this->assertEquals(0, count($h));
|
||||
$h->set('Http_Content_Type', 'text/html');
|
||||
$prop = new \ReflectionProperty($h, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$this->assertArrayHasKey('Content-Type', $prop->getValue($h));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructor with args
|
||||
*/
|
||||
public function testConstructorWithArgs()
|
||||
public function testExtractHeaders()
|
||||
{
|
||||
$h = new \Slim\Http\Headers(array('Content-Type' => 'text/html'));
|
||||
$this->assertEquals(1, count($h));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get and set header
|
||||
*/
|
||||
public function testSetAndGetHeader()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$h['Content-Type'] = 'text/html';
|
||||
$this->assertEquals('text/html', $h['Content-Type']);
|
||||
$this->assertEquals('text/html', $h['Content-type']);
|
||||
$this->assertEquals('text/html', $h['content-type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get non-existent header
|
||||
*/
|
||||
public function testGetNonExistentHeader()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$this->assertNull($h['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isset header
|
||||
*/
|
||||
public function testHeaderIsSet()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$h['Content-Type'] = 'text/html';
|
||||
$this->assertTrue(isset($h['Content-Type']));
|
||||
$this->assertTrue(isset($h['Content-type']));
|
||||
$this->assertTrue(isset($h['content-type']));
|
||||
$this->assertFalse(isset($h['foo']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test unset header
|
||||
*/
|
||||
public function testUnsetHeader()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$h['Content-Type'] = 'text/html';
|
||||
$this->assertEquals(1, count($h));
|
||||
unset($h['Content-Type']);
|
||||
$this->assertEquals(0, count($h));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test merge headers
|
||||
*/
|
||||
public function testMergeHeaders()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$h['Content-Type'] = 'text/html';
|
||||
$this->assertEquals(1, count($h));
|
||||
$h->merge(array('Content-type' => 'text/csv', 'content-length' => 10));
|
||||
$this->assertEquals(2, count($h));
|
||||
$this->assertEquals('text/csv', $h['content-type']);
|
||||
$this->assertEquals(10, $h['Content-length']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test iteration
|
||||
*/
|
||||
public function testIteration()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$h['One'] = 'Foo';
|
||||
$h['Two'] = 'Bar';
|
||||
$output = '';
|
||||
foreach ($h as $key => $value) {
|
||||
$output .= $key . $value;
|
||||
}
|
||||
$this->assertEquals('OneFooTwoBar', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test outputs header name in original form, not canonical form
|
||||
*/
|
||||
public function testOutputsOriginalNotCanonicalName()
|
||||
{
|
||||
$h = new \Slim\Http\Headers();
|
||||
$h['X-Powered-By'] = 'Slim';
|
||||
$h['Content-Type'] = 'text/csv';
|
||||
$keys = array();
|
||||
foreach ($h as $name => $value) {
|
||||
$keys[] = $name;
|
||||
}
|
||||
$this->assertContains('X-Powered-By', $keys);
|
||||
$this->assertContains('Content-Type', $keys);
|
||||
$test = array(
|
||||
'HTTP_HOST' => 'foo.com',
|
||||
'SERVER_NAME' => 'foo',
|
||||
'CONTENT_TYPE' => 'text/html',
|
||||
'X_FORWARDED_FOR' => '127.0.0.1'
|
||||
);
|
||||
$results = \Slim\Http\Headers::extract($test);
|
||||
$this->assertEquals(array(
|
||||
'HTTP_HOST' => 'foo.com',
|
||||
'CONTENT_TYPE' => 'text/html',
|
||||
'X_FORWARDED_FOR' => '127.0.0.1'
|
||||
), $results);
|
||||
}
|
||||
}
|
||||
|
||||
+59
-53
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -54,11 +54,6 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertTrue($req->isGet());
|
||||
$this->assertFalse($req->isPost());
|
||||
$this->assertFalse($req->isPut());
|
||||
$this->assertFalse($req->isDelete());
|
||||
$this->assertFalse($req->isOptions());
|
||||
$this->assertFalse($req->isHead());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,12 +65,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertFalse($req->isGet());
|
||||
$this->assertTrue($req->isPost());
|
||||
$this->assertFalse($req->isPut());
|
||||
$this->assertFalse($req->isDelete());
|
||||
$this->assertFalse($req->isOptions());
|
||||
$this->assertFalse($req->isHead());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,12 +77,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => 'PUT',
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertFalse($req->isGet());
|
||||
$this->assertFalse($req->isPost());
|
||||
$this->assertTrue($req->isPut());
|
||||
$this->assertFalse($req->isDelete());
|
||||
$this->assertFalse($req->isOptions());
|
||||
$this->assertFalse($req->isHead());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,12 +89,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => 'DELETE',
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertFalse($req->isGet());
|
||||
$this->assertFalse($req->isPost());
|
||||
$this->assertFalse($req->isPut());
|
||||
$this->assertTrue($req->isDelete());
|
||||
$this->assertFalse($req->isOptions());
|
||||
$this->assertFalse($req->isHead());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,12 +101,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => 'OPTIONS',
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertFalse($req->isGet());
|
||||
$this->assertFalse($req->isPost());
|
||||
$this->assertFalse($req->isPut());
|
||||
$this->assertFalse($req->isDelete());
|
||||
$this->assertTrue($req->isOptions());
|
||||
$this->assertFalse($req->isHead());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,14 +113,21 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => 'HEAD',
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertFalse($req->isGet());
|
||||
$this->assertFalse($req->isPost());
|
||||
$this->assertFalse($req->isPut());
|
||||
$this->assertFalse($req->isDelete());
|
||||
$this->assertFalse($req->isOptions());
|
||||
$this->assertTrue($req->isHead());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test HTTP PATCH method detection
|
||||
*/
|
||||
public function testIsPatch()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'PATCH',
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertTrue($req->isPatch());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test AJAX method detection w/ header
|
||||
*/
|
||||
@@ -165,7 +147,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testIsAjaxWithQueryParameter()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3&isajax=1',
|
||||
'QUERY_STRING' => 'isajax=1',
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertTrue($req->isAjax());
|
||||
@@ -173,7 +155,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test AJAX method detection wihtout header or query paramter
|
||||
* Test AJAX method detection without header or query parameter
|
||||
*/
|
||||
public function testIsAjaxWithoutHeaderOrQueryParameter()
|
||||
{
|
||||
@@ -239,6 +221,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(3, count($req->get()));
|
||||
$this->assertEquals('1', $req->get('one'));
|
||||
$this->assertNull($req->get('foo'));
|
||||
$this->assertFalse($req->get('foo', false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,6 +237,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(3, count($req->get()));
|
||||
$this->assertEquals('1', $req->get('one'));
|
||||
$this->assertNull($req->get('foo'));
|
||||
$this->assertFalse($req->get('foo', false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,6 +255,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(2, count($req->post()));
|
||||
$this->assertEquals('bar', $req->post('foo'));
|
||||
$this->assertNull($req->post('xyz'));
|
||||
$this->assertFalse($req->post('xyz', false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,6 +274,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(2, count($req->post()));
|
||||
$this->assertEquals('bar', $req->post('foo'));
|
||||
$this->assertNull($req->post('xyz'));
|
||||
$this->assertFalse($req->post('xyz', false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -337,6 +323,26 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('bar', $req->put('foo'));
|
||||
$this->assertEquals('bar', $req->params('foo'));
|
||||
$this->assertNull($req->put('xyz'));
|
||||
$this->assertFalse($req->put('xyz', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fetch PATCH params
|
||||
*/
|
||||
public function testPatch()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'PATCH',
|
||||
'slim.input' => 'foo=bar&abc=123',
|
||||
'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
|
||||
'CONTENT_LENGTH' => 15
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertEquals(2, count($req->patch()));
|
||||
$this->assertEquals('bar', $req->patch('foo'));
|
||||
$this->assertEquals('bar', $req->params('foo'));
|
||||
$this->assertNull($req->patch('xyz'));
|
||||
$this->assertFalse($req->patch('xyz', false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,6 +361,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('bar', $req->delete('foo'));
|
||||
$this->assertEquals('bar', $req->params('foo'));
|
||||
$this->assertNull($req->delete('xyz'));
|
||||
$this->assertFalse($req->delete('xyz', false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,7 +370,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testCookies()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'COOKIE' => 'foo=bar; abc=123'
|
||||
'HTTP_COOKIE' => 'foo=bar; abc=123'
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertEquals(2, count($req->cookies()));
|
||||
@@ -431,12 +438,11 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testHeaders()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'ACCEPT_ENCODING' => 'gzip'
|
||||
'HTTP_ACCEPT_ENCODING' => 'gzip'
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$headers = $req->headers();
|
||||
$this->assertTrue(is_array($headers));
|
||||
$this->assertArrayHasKey('ACCEPT_ENCODING', $headers);
|
||||
$this->assertInstanceOf('\Slim\Http\Headers', $headers);
|
||||
$this->assertEquals('gzip', $req->headers('HTTP_ACCEPT_ENCODING'));
|
||||
$this->assertEquals('gzip', $req->headers('HTTP-ACCEPT-ENCODING'));
|
||||
$this->assertEquals('gzip', $req->headers('http_accept_encoding'));
|
||||
@@ -632,7 +638,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'SERVER_NAME' => 'slim',
|
||||
'HOST' => 'slimframework.com'
|
||||
'HTTP_HOST' => 'slimframework.com'
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertEquals('slimframework.com', $req->getHost()); //Uses HTTP_HOST if available
|
||||
@@ -645,7 +651,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'SERVER_NAME' => 'slim',
|
||||
'HOST' => 'slimframework.com:80'
|
||||
'HTTP_HOST' => 'slimframework.com:80'
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertEquals('slimframework.com', $req->getHost()); //Uses HTTP_HOST if available
|
||||
@@ -658,9 +664,9 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'SERVER_NAME' => 'slim',
|
||||
'HOST' => 'slimframework.com'
|
||||
'HTTP_HOST' => 'slimframework.com'
|
||||
));
|
||||
unset($env['HOST']);
|
||||
unset($env['HTTP_HOST']);
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertEquals('slim', $req->getHost()); //Uses SERVER_NAME as backup
|
||||
}
|
||||
@@ -671,7 +677,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testGetHostWithPort()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'HOST' => 'slimframework.com',
|
||||
'HTTP_HOST' => 'slimframework.com',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http'
|
||||
@@ -681,12 +687,12 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get host with port doesn't dulplicate port numbers
|
||||
* Test get host with port doesn't duplicate port numbers
|
||||
*/
|
||||
public function testGetHostDoesntDulplicatePort()
|
||||
public function testGetHostDoesntDuplicatePort()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'HOST' => 'slimframework.com:80',
|
||||
'HTTP_HOST' => 'slimframework.com:80',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http'
|
||||
@@ -806,7 +812,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testGetUrl()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'HOST' => 'slimframework.com',
|
||||
'HTTP_HOST' => 'slimframework.com',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http'
|
||||
@@ -821,7 +827,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testGetUrlWithCustomPort()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'HOST' => 'slimframework.com',
|
||||
'HTTP_HOST' => 'slimframework.com',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 8080,
|
||||
'slim.url_scheme' => 'http'
|
||||
@@ -836,7 +842,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testGetUrlWithHttps()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'HOST' => 'slimframework.com',
|
||||
'HTTP_HOST' => 'slimframework.com',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 443,
|
||||
'slim.url_scheme' => 'https'
|
||||
@@ -885,12 +891,12 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get refererer
|
||||
* Test get referer
|
||||
*/
|
||||
public function testGetReferrer()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'REFERER' => 'http://foo.com'
|
||||
'HTTP_REFERER' => 'http://foo.com'
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertEquals('http://foo.com', $req->getReferrer());
|
||||
@@ -898,7 +904,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get refererer
|
||||
* Test get referer
|
||||
*/
|
||||
public function testGetReferrerWhenNotExists()
|
||||
{
|
||||
@@ -914,7 +920,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testGetUserAgent()
|
||||
{
|
||||
$env = \Slim\Environment::mock(array(
|
||||
'USER_AGENT' => 'user-agent-string'
|
||||
'HTTP_USER_AGENT' => 'user-agent-string'
|
||||
));
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertEquals('user-agent-string', $req->getUserAgent());
|
||||
@@ -926,7 +932,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
||||
public function testGetUserAgentWhenNotExists()
|
||||
{
|
||||
$env = \Slim\Environment::mock();
|
||||
unset($env['USER_AGENT']);
|
||||
unset($env['HTTP_USER_AGENT']);
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$this->assertNull($req->getUserAgent());
|
||||
}
|
||||
|
||||
+95
-398
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -32,541 +32,238 @@
|
||||
|
||||
class ResponseTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test constructor without args
|
||||
*/
|
||||
public function testConstructorWithoutArgs()
|
||||
public function testConstructWithoutArgs()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$this->assertEquals('', $r->body());
|
||||
$this->assertEquals(200, $r->status());
|
||||
$this->assertEquals(0, $r->length());
|
||||
$this->assertEquals('text/html', $r['Content-Type']);
|
||||
$res = new \Slim\Http\Response();
|
||||
|
||||
$this->assertAttributeEquals(200, 'status', $res);
|
||||
$this->assertAttributeEquals('', 'body', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructor with args
|
||||
*/
|
||||
public function testConstructorWithArgs()
|
||||
public function testConstructWithArgs()
|
||||
{
|
||||
$r = new \Slim\Http\Response('Page Not Found', 404, array('Content-Type' => 'application/json', 'X-Created-By' => 'Slim'));
|
||||
$this->assertEquals('Page Not Found', $r->body());
|
||||
$this->assertEquals(404, $r->status());
|
||||
$this->assertEquals(14, $r->length());
|
||||
$this->assertEquals('application/json', $r['Content-Type']);
|
||||
$this->assertEquals('Slim', $r['X-Created-By']);
|
||||
$res = new \Slim\Http\Response('Foo', 201);
|
||||
|
||||
$this->assertAttributeEquals(201, 'status', $res);
|
||||
$this->assertAttributeEquals('Foo', 'body', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get status
|
||||
*/
|
||||
public function testGetStatus()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$this->assertEquals(200, $r->status());
|
||||
$res = new \Slim\Http\Response();
|
||||
|
||||
$this->assertEquals(200, $res->getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set status
|
||||
*/
|
||||
public function testSetStatus()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->status(500);
|
||||
$this->assertEquals(500, $r->status());
|
||||
$res = new \Slim\Http\Response();
|
||||
$res->setStatus(301);
|
||||
|
||||
$this->assertAttributeEquals(301, 'status', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get headers
|
||||
* DEPRECATION WARNING!
|
||||
*/
|
||||
public function testGetHeaders()
|
||||
public function testStatusGetOld()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$headers = $r->headers();
|
||||
$this->assertEquals(1, count($headers));
|
||||
$this->assertEquals('text/html', $headers['Content-Type']);
|
||||
$res = new \Slim\Http\Response('', 201);
|
||||
$this->assertEquals(201, $res->status());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get and set header (without Array Access)
|
||||
* DEPRECATION WARNING!
|
||||
*/
|
||||
public function testGetAndSetHeader()
|
||||
public function testStatusSetOld()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->header('X-Foo', 'Bar');
|
||||
$this->assertEquals('Bar', $r->header('X-Foo'));
|
||||
$res = new \Slim\Http\Response();
|
||||
$prop = new \ReflectionProperty($res, 'status');
|
||||
$prop->setAccessible(true);
|
||||
$res->status(301);
|
||||
|
||||
$this->assertEquals(301, $prop->getValue($res));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get body
|
||||
*/
|
||||
public function testGetBody()
|
||||
{
|
||||
$r = new \Slim\Http\Response('Foo');
|
||||
$this->assertEquals('Foo', $r->body());
|
||||
$res = new \Slim\Http\Response();
|
||||
$property = new \ReflectionProperty($res, 'body');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($res, 'foo');
|
||||
|
||||
$this->assertEquals('foo', $res->getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set body
|
||||
*/
|
||||
public function testSetBody()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->body('Foo');
|
||||
$this->assertEquals('Foo', $r->body());
|
||||
$res = new \Slim\Http\Response('bar');
|
||||
$res->setBody('foo'); // <-- Should replace body
|
||||
|
||||
$this->assertAttributeEquals('foo', 'body', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get length
|
||||
*/
|
||||
public function testGetLength()
|
||||
public function testWrite()
|
||||
{
|
||||
$r = new \Slim\Http\Response('Foo');
|
||||
$this->assertEquals(3, $r->length());
|
||||
$res = new \Slim\Http\Response();
|
||||
$property = new \ReflectionProperty($res, 'body');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($res, 'foo');
|
||||
$res->write('bar'); // <-- Should append to body
|
||||
|
||||
$this->assertAttributeEquals('foobar', 'body', $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set length
|
||||
*/
|
||||
public function testSetLength()
|
||||
public function testLength()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->length(3);
|
||||
$this->assertEquals(3, $r->length());
|
||||
$res = new \Slim\Http\Response('foo'); // <-- Sets body and length
|
||||
|
||||
$this->assertEquals(3, $res->getLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test write for appending
|
||||
*/
|
||||
public function testWriteAppend()
|
||||
{
|
||||
$r = new \Slim\Http\Response('Foo');
|
||||
$r->write('Bar');
|
||||
$this->assertEquals('FooBar', $r->body());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test write for replacing
|
||||
*/
|
||||
public function testWriteReplace()
|
||||
{
|
||||
$r = new \Slim\Http\Response('Foo');
|
||||
$r->write('Bar', true);
|
||||
$this->assertEquals('Bar', $r->body());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test finalize
|
||||
*/
|
||||
public function testFinalize()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->status(404);
|
||||
$r['Content-Type'] = 'application/json';
|
||||
$r->write('Foo');
|
||||
$result = $r->finalize();
|
||||
$this->assertEquals(3, count($result));
|
||||
$this->assertEquals(404, $result[0]);
|
||||
$this->assertFalse(is_null($result[1]['Content-Type']));
|
||||
$res = new \Slim\Http\Response();
|
||||
$resFinal = $res->finalize();
|
||||
|
||||
$this->assertTrue(is_array($resFinal));
|
||||
$this->assertEquals(3, count($resFinal));
|
||||
$this->assertEquals(200, $resFinal[0]);
|
||||
$this->assertInstanceOf('\Slim\Http\Headers', $resFinal[1]);
|
||||
$this->assertEquals('', $resFinal[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test finalize
|
||||
*/
|
||||
public function testFinalizeWithoutBody()
|
||||
public function testFinalizeWithEmptyBody()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->status(204);
|
||||
$r['Content-Type'] = 'application/json';
|
||||
$r->write('Foo');
|
||||
$result = $r->finalize();
|
||||
$this->assertEquals(3, count($result));
|
||||
$this->assertEquals('', $result[2]);
|
||||
$res = new \Slim\Http\Response('Foo', 304);
|
||||
$resFinal = $res->finalize();
|
||||
|
||||
$this->assertEquals('', $resFinal[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with only name and value
|
||||
*/
|
||||
public function testSetCookieWithNameAndValue()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', 'bar');
|
||||
$this->assertEquals('foo=bar', $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set multiple cookies with only name and value
|
||||
*/
|
||||
public function testSetMultipleCookiesWithNameAndValue()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', 'bar');
|
||||
$r->setCookie('abc', '123');
|
||||
$this->assertEquals("foo=bar\nabc=123", $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie only name and value and expires (as int)
|
||||
*/
|
||||
public function testSetMultipleCookiesWithNameAndValueAndExpiresAsInt()
|
||||
{
|
||||
$now = time();
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'expires' => $now
|
||||
));
|
||||
$this->assertEquals("foo=bar; expires=" . gmdate('D, d-M-Y H:i:s e', $now), $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with only name and value and expires (as string)
|
||||
*/
|
||||
public function testSetMultipleCookiesWithNameAndValueAndExpiresAsString()
|
||||
{
|
||||
$expires = 'next Tuesday';
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'expires' => $expires
|
||||
));
|
||||
$this->assertEquals("foo=bar; expires=" . gmdate('D, d-M-Y H:i:s e', strtotime($expires)), $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with name, value, domain
|
||||
*/
|
||||
public function testSetCookieWithNameAndValueAndDomain()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'domain' => '.slimframework.com'
|
||||
));
|
||||
$this->assertEquals('foo=bar; domain=.slimframework.com', $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with name, value, domain, path
|
||||
*/
|
||||
public function testSetCookieWithNameAndValueAndDomainAndPath()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'domain' => '.slimframework.com',
|
||||
'path' => '/foo'
|
||||
));
|
||||
$this->assertEquals($r['Set-Cookie'], 'foo=bar; domain=.slimframework.com; path=/foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with only name and value and secure flag
|
||||
*/
|
||||
public function testSetCookieWithNameAndValueAndSecureFlag()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'secure' => true
|
||||
));
|
||||
$this->assertEquals('foo=bar; secure', $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with only name and value and secure flag (as non-truthy)
|
||||
*/
|
||||
public function testSetCookieWithNameAndValueAndSecureFlagAsNonTruthy()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'secure' => 0
|
||||
));
|
||||
$this->assertEquals('foo=bar', $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with only name and value and httponly flag
|
||||
*/
|
||||
public function testSetCookieWithNameAndValueAndHttpOnlyFlag()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'httponly' => true
|
||||
));
|
||||
$this->assertEquals('foo=bar; HttpOnly', $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set cookie with only name and value and httponly flag (as non-truthy)
|
||||
*/
|
||||
public function testSetCookieWithNameAndValueAndHttpOnlyFlagAsNonTruthy()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'httponly' => 0
|
||||
));
|
||||
$this->assertEquals('foo=bar', $r['Set-Cookie']);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test delete cookie by name
|
||||
*/
|
||||
public function testDeleteCookieByName()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', 'bar');
|
||||
$r->setCookie('abc', '123');
|
||||
$r->deleteCookie('foo');
|
||||
$this->assertEquals(1, preg_match("@abc=123\nfoo=; expires=@", $r['Set-Cookie']));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test delete cookie by name and domain
|
||||
*/
|
||||
public function testDeleteCookieByNameAndDomain1()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', 'bar'); //Note: This does not have domain associated with it
|
||||
$r->setCookie('abc', '123');
|
||||
$r->deleteCookie('foo', array('domain' => '.slimframework.com')); //This SHOULD NOT remove the `foo` cookie
|
||||
$this->assertEquals(1, preg_match("@foo=bar\nabc=123\nfoo=; domain=.slimframework.com; expires=@", $r['Set-Cookie']));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test delete cookie by name and domain
|
||||
*/
|
||||
public function testDeleteCookieByNameAndDomain2()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', array(
|
||||
'value' => 'bar',
|
||||
'domain' => '.slimframework.com' //Note: This does have domain associated with it
|
||||
));
|
||||
$r->setCookie('abc', '123');
|
||||
$r->deleteCookie('foo', array('domain' => '.slimframework.com')); //This SHOULD remove the `foo` cookie
|
||||
$this->assertEquals(1, preg_match("@abc=123\nfoo=; domain=.slimframework.com; expires=@", $r['Set-Cookie']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test delete cookie by name and custom props
|
||||
*/
|
||||
public function testDeleteCookieByNameAndCustomProps()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->setCookie('foo', 'bar');
|
||||
$r->setCookie('abc', '123');
|
||||
$r->deleteCookie('foo', array(
|
||||
'secure' => true,
|
||||
'httponly' => true
|
||||
));
|
||||
$this->assertEquals(1, preg_match("@abc=123\nfoo=; expires=.*; secure; HttpOnly@", $r['Set-Cookie']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test redirect
|
||||
*/
|
||||
public function testRedirect()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->redirect('/foo');
|
||||
$this->assertEquals(302, $r->status());
|
||||
$this->assertEquals('/foo', $r['Location']);
|
||||
$res = new \Slim\Http\Response();
|
||||
$res->redirect('/foo');
|
||||
|
||||
$pStatus = new \ReflectionProperty($res, 'status');
|
||||
$pStatus->setAccessible(true);
|
||||
|
||||
$this->assertEquals(302, $pStatus->getValue($res));
|
||||
$this->assertEquals('/foo', $res->headers['Location']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test redirect with custom status
|
||||
*/
|
||||
public function testRedirectWithCustomStatus()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$r->redirect('/foo', 307);
|
||||
$this->assertEquals(307, $r->status());
|
||||
$this->assertEquals('/foo', $r['Location']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isEmpty
|
||||
*/
|
||||
public function testIsEmpty()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(404);
|
||||
$r2->status(201);
|
||||
$r1->setStatus(404);
|
||||
$r2->setStatus(201);
|
||||
$this->assertFalse($r1->isEmpty());
|
||||
$this->assertTrue($r2->isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isClientError
|
||||
*/
|
||||
public function testIsClientError()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(404);
|
||||
$r2->status(500);
|
||||
$r1->setStatus(404);
|
||||
$r2->setStatus(500);
|
||||
$this->assertTrue($r1->isClientError());
|
||||
$this->assertFalse($r2->isClientError());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isForbidden
|
||||
*/
|
||||
public function testIsForbidden()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(403);
|
||||
$r2->status(500);
|
||||
$r1->setStatus(403);
|
||||
$r2->setStatus(500);
|
||||
$this->assertTrue($r1->isForbidden());
|
||||
$this->assertFalse($r2->isForbidden());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isInformational
|
||||
*/
|
||||
public function testIsInformational()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(100);
|
||||
$r2->status(200);
|
||||
$r1->setStatus(100);
|
||||
$r2->setStatus(200);
|
||||
$this->assertTrue($r1->isInformational());
|
||||
$this->assertFalse($r2->isInformational());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isInformational
|
||||
*/
|
||||
public function testIsNotFound()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(404);
|
||||
$r2->status(200);
|
||||
$r1->setStatus(404);
|
||||
$r2->setStatus(200);
|
||||
$this->assertTrue($r1->isNotFound());
|
||||
$this->assertFalse($r2->isNotFound());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isOk
|
||||
*/
|
||||
public function testIsOk()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(200);
|
||||
$r2->status(201);
|
||||
$r1->setStatus(200);
|
||||
$r2->setStatus(201);
|
||||
$this->assertTrue($r1->isOk());
|
||||
$this->assertFalse($r2->isOk());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isSuccessful
|
||||
*/
|
||||
public function testIsSuccessful()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r3 = new \Slim\Http\Response();
|
||||
$r1->status(200);
|
||||
$r2->status(201);
|
||||
$r3->status(302);
|
||||
$r1->setStatus(200);
|
||||
$r2->setStatus(201);
|
||||
$r3->setStatus(302);
|
||||
$this->assertTrue($r1->isSuccessful());
|
||||
$this->assertTrue($r2->isSuccessful());
|
||||
$this->assertFalse($r3->isSuccessful());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isRedirect
|
||||
*/
|
||||
public function testIsRedirect()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(307);
|
||||
$r2->status(304);
|
||||
$r1->setStatus(307);
|
||||
$r2->setStatus(304);
|
||||
$this->assertTrue($r1->isRedirect());
|
||||
$this->assertFalse($r2->isRedirect());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isRedirection
|
||||
*/
|
||||
public function testIsRedirection()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r3 = new \Slim\Http\Response();
|
||||
$r1->status(307);
|
||||
$r2->status(304);
|
||||
$r3->status(200);
|
||||
$r1->setStatus(307);
|
||||
$r2->setStatus(304);
|
||||
$r3->setStatus(200);
|
||||
$this->assertTrue($r1->isRedirection());
|
||||
$this->assertTrue($r2->isRedirection());
|
||||
$this->assertFalse($r3->isRedirection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isServerError
|
||||
*/
|
||||
public function testIsServerError()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$r2 = new \Slim\Http\Response();
|
||||
$r1->status(500);
|
||||
$r2->status(400);
|
||||
$r1->setStatus(500);
|
||||
$r2->setStatus(400);
|
||||
$this->assertTrue($r1->isServerError());
|
||||
$this->assertFalse($r2->isServerError());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test offset exists and offset get
|
||||
*/
|
||||
public function testOffsetExistsAndGet()
|
||||
{
|
||||
$r = new \Slim\Http\Response();
|
||||
$this->assertFalse(empty($r['Content-Type']));
|
||||
$this->assertNull($r['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test iteration
|
||||
*/
|
||||
public function testIteration()
|
||||
{
|
||||
$h = new \Slim\Http\Response();
|
||||
$output = '';
|
||||
foreach ($h as $key => $value) {
|
||||
$output .= $key . $value;
|
||||
}
|
||||
$this->assertEquals('Content-Typetext/html', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test countable
|
||||
*/
|
||||
public function testCountable()
|
||||
{
|
||||
$r1 = new \Slim\Http\Response();
|
||||
$this->assertEquals(1, count($r1)); //Content-Type
|
||||
}
|
||||
|
||||
/**
|
||||
* Test message for code when message exists
|
||||
*/
|
||||
public function testMessageForCode()
|
||||
{
|
||||
$this->assertEquals('200 OK', \Slim\Http\Response::getMessageForCode(200));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test message for code when message exists
|
||||
*/
|
||||
public function testMessageForCodeWithInvalidCode()
|
||||
{
|
||||
$this->assertNull(\Slim\Http\Response::getMessageForCode(600));
|
||||
|
||||
+45
-1
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -324,6 +324,50 @@ class SlimHttpUtilTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('foo=bar; domain=foo.com; path=/foo; expires=' . $expiresFormat . '; secure; HttpOnly', $header['Set-Cookie']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serializeCookies and decrypt with string expires
|
||||
*
|
||||
* In this test a cookie with a string typed value for 'expires' is set,
|
||||
* which should be parsed by `strtotime` to a timestamp when it's added to
|
||||
* the headers; this timestamp should then be correctly parsed, and the
|
||||
* value correctly decrypted, by `decodeSecureCookie`.
|
||||
*/
|
||||
public function testSerializeCookiesAndDecryptWithStringExpires()
|
||||
{
|
||||
$value = 'bar';
|
||||
|
||||
$headers = new \Slim\Http\Headers();
|
||||
|
||||
$settings = array(
|
||||
'cookies.encrypt' => true,
|
||||
'cookies.secret_key' => 'secret',
|
||||
'cookies.cipher' => MCRYPT_RIJNDAEL_256,
|
||||
'cookies.cipher_mode' => MCRYPT_MODE_CBC
|
||||
);
|
||||
|
||||
$cookies = new \Slim\Http\Cookies();
|
||||
$cookies->set('foo', array(
|
||||
'value' => $value,
|
||||
'expires' => '1 hour'
|
||||
));
|
||||
|
||||
\Slim\Http\Util::serializeCookies($headers, $cookies, $settings);
|
||||
|
||||
$encrypted = $headers->get('Set-Cookie');
|
||||
$encrypted = strstr($encrypted, ';', true);
|
||||
$encrypted = urldecode(substr(strstr($encrypted, '='), 1));
|
||||
|
||||
$decrypted = \Slim\Http\Util::decodeSecureCookie(
|
||||
$encrypted,
|
||||
$settings['cookies.secret_key'],
|
||||
$settings['cookies.cipher'],
|
||||
$settings['cookies.cipher_mode']
|
||||
);
|
||||
|
||||
$this->assertEquals($value, $decrypted);
|
||||
$this->assertTrue($value !== $encrypted);
|
||||
}
|
||||
|
||||
public function testDeleteCookieHeaderWithSurvivingCookie()
|
||||
{
|
||||
$header = array('Set-Cookie' => "foo=bar\none=two");
|
||||
|
||||
Vendored
+63
-7
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -96,6 +96,21 @@ class LogTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
public function testLogInfoExcludedByLevel()
|
||||
{
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$log->setLevel(\Slim\Log::NOTICE);
|
||||
$this->assertFalse($log->info('Info'));
|
||||
}
|
||||
|
||||
public function testLogNotice()
|
||||
{
|
||||
$this->expectOutputString('Notice');
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$result = $log->notice('Notice');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testLogNoticeExcludedByLevel()
|
||||
{
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$log->setLevel(\Slim\Log::WARN);
|
||||
@@ -106,7 +121,7 @@ class LogTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$this->expectOutputString('Warn');
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$result = $log->warn('Warn');
|
||||
$result = $log->warning('Warn');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
@@ -114,7 +129,7 @@ class LogTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$log->setLevel(\Slim\Log::ERROR);
|
||||
$this->assertFalse($log->warn('Warn'));
|
||||
$this->assertFalse($log->warning('Warn'));
|
||||
}
|
||||
|
||||
public function testLogError()
|
||||
@@ -128,15 +143,56 @@ class LogTest extends PHPUnit_Framework_TestCase
|
||||
public function testLogErrorExcludedByLevel()
|
||||
{
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$log->setLevel(\Slim\Log::FATAL);
|
||||
$log->setLevel(\Slim\Log::CRITICAL);
|
||||
$this->assertFalse($log->error('Error'));
|
||||
}
|
||||
|
||||
public function testLogFatal()
|
||||
public function testLogCritical()
|
||||
{
|
||||
$this->expectOutputString('Fatal');
|
||||
$this->expectOutputString('Critical');
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$result = $log->fatal('Fatal');
|
||||
$result = $log->critical('Critical');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testLogCriticalExcludedByLevel()
|
||||
{
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$log->setLevel(\Slim\Log::ALERT);
|
||||
$this->assertFalse($log->critical('Critical'));
|
||||
}
|
||||
|
||||
public function testLogAlert()
|
||||
{
|
||||
$this->expectOutputString('Alert');
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$result = $log->alert('Alert');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testLogAlertExcludedByLevel()
|
||||
{
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$log->setLevel(\Slim\Log::EMERGENCY);
|
||||
$this->assertFalse($log->alert('Alert'));
|
||||
}
|
||||
|
||||
public function testLogEmergency()
|
||||
{
|
||||
$this->expectOutputString('Emergency');
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$result = $log->emergency('Emergency');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testInterpolateMessage()
|
||||
{
|
||||
$this->expectOutputString('Hello Slim !');
|
||||
$log = new \Slim\Log(new MyWriter());
|
||||
$result = $log->debug(
|
||||
'Hello {framework} !',
|
||||
array('framework' => "Slim")
|
||||
);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
|
||||
+5
-4
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -104,10 +104,11 @@ class ContentTypesTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testParsesXmlWithError()
|
||||
{
|
||||
libxml_use_internal_errors(true);
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'CONTENT_TYPE' => 'application/xml',
|
||||
'CONENT_LENGTH' => 68,
|
||||
'CONTENT_LENGTH' => 68,
|
||||
'slim.input' => '<books><book><id>1</id><author>Clive Cussler</book></books>' //<-- This should be incorrect!
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
@@ -126,7 +127,7 @@ class ContentTypesTest extends PHPUnit_Framework_TestCase
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'CONTENT_TYPE' => 'text/csv',
|
||||
'CONENT_LENGTH' => 44,
|
||||
'CONTENT_LENGTH' => 44,
|
||||
'slim.input' => "John,Doe,000-111-2222\nJane,Doe,111-222-3333"
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
@@ -148,7 +149,7 @@ class ContentTypesTest extends PHPUnit_Framework_TestCase
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'CONTENT_TYPE' => 'application/json; charset=ISO-8859-4',
|
||||
'CONENT_LENGTH' => 13,
|
||||
'CONTENT_LENGTH' => 13,
|
||||
'slim.input' => '{"foo":"bar"}'
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
|
||||
+15
-2
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -86,7 +86,7 @@ class SlimFlashTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test flash messages from preivous request do not persist to next request
|
||||
* Test flash messages from previous request do not persist to next request
|
||||
*/
|
||||
public function testFlashMessagesFromPreviousRequestDoNotPersist()
|
||||
{
|
||||
@@ -125,4 +125,17 @@ class SlimFlashTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
$this->assertEquals('infofooerrorbar', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test countable
|
||||
*/
|
||||
public function testCountable()
|
||||
{
|
||||
$_SESSION['slim.flash'] = array('info' => 'foo', 'error' => 'bar');
|
||||
$f = new \Slim\MiddleWare\Flash();
|
||||
$f->loadMessages();
|
||||
$this->assertEquals(2, count($f));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -64,7 +64,7 @@ class MethodOverrideTest extends PHPUnit_Framework_TestCase
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
|
||||
'CONENT_LENGTH' => 11,
|
||||
'CONTENT_LENGTH' => 11,
|
||||
'slim.input' => '_METHOD=PUT'
|
||||
));
|
||||
$app = new CustomAppMethod();
|
||||
@@ -98,7 +98,7 @@ class MethodOverrideTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test does not override method if no method ovveride parameter
|
||||
* Test does not override method if no method override parameter
|
||||
*/
|
||||
public function testDoesNotOverrideMethodAsPostWithoutParameter()
|
||||
{
|
||||
@@ -132,9 +132,9 @@ class MethodOverrideTest extends PHPUnit_Framework_TestCase
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
'CONENT_LENGTH' => 0,
|
||||
'CONTENT_LENGTH' => 0,
|
||||
'slim.input' => '',
|
||||
'X_HTTP_METHOD_OVERRIDE' => 'DELETE'
|
||||
'HTTP_X_HTTP_METHOD_OVERRIDE' => 'DELETE'
|
||||
));
|
||||
$app = new CustomAppMethod();
|
||||
$mw = new \Slim\Middleware\MethodOverride();
|
||||
|
||||
+29
-1
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -122,4 +122,32 @@ class PrettyExceptionsTest extends PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertContains('LogicException', $app->response()->body());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with custom log
|
||||
*/
|
||||
public function testWithCustomLogWriter()
|
||||
{
|
||||
$this->setExpectedException('\LogicException');
|
||||
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
'PATH_INFO' => '/foo'
|
||||
));
|
||||
$app = new \Slim\Slim(array(
|
||||
'log.enabled' => false
|
||||
));
|
||||
$app->container->singleton('log', function () use ($app) {
|
||||
return new \Slim\Log(new \Slim\LogWriter('php://temp'));
|
||||
});
|
||||
$app->get('/foo', function () use ($app) {
|
||||
throw new \LogicException('Test Message', 100);
|
||||
});
|
||||
$mw = new \Slim\Middleware\PrettyExceptions();
|
||||
$mw->setApplication($app);
|
||||
$mw->setNextMiddleware($app);
|
||||
$mw->call();
|
||||
|
||||
$this->assertContains('LogicException', $app->response()->body());
|
||||
}
|
||||
}
|
||||
|
||||
+371
-17
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -34,10 +34,6 @@ class SessionCookieTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if ( session_id() !== '' ) {
|
||||
session_unset();
|
||||
session_destroy();
|
||||
}
|
||||
$_SESSION = array();
|
||||
}
|
||||
|
||||
@@ -45,10 +41,11 @@ class SessionCookieTest extends PHPUnit_Framework_TestCase
|
||||
* Test session cookie is set and constructed correctly
|
||||
*
|
||||
* We test for two things:
|
||||
* 1) That the HTTP cookie is added to the `Set-Cookie:` response header;
|
||||
* 2) That the HTTP cookie is constructed in the expected format;
|
||||
*
|
||||
* 1) That the HTTP cookie exists with the correct name;
|
||||
* 2) That the HTTP cookie's value is the expected value;
|
||||
*/
|
||||
public function testSessionCookieIsCreatedAndEncrypted()
|
||||
public function testSessionCookieIsCreated()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
@@ -56,6 +53,7 @@ class SessionCookieTest extends PHPUnit_Framework_TestCase
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
$app->get('/foo', function () {
|
||||
$_SESSION['foo'] = 'bar';
|
||||
echo "Success";
|
||||
});
|
||||
$mw = new \Slim\Middleware\SessionCookie(array('expires' => '10 years'));
|
||||
@@ -63,26 +61,29 @@ class SessionCookieTest extends PHPUnit_Framework_TestCase
|
||||
$mw->setNextMiddleware($app);
|
||||
$mw->call();
|
||||
list($status, $header, $body) = $app->response()->finalize();
|
||||
$matches = array();
|
||||
preg_match_all('@^slim_session=.+|.+|.+; expires=@', $header['Set-Cookie'], $matches, PREG_SET_ORDER);
|
||||
$this->assertEquals(1, count($matches));
|
||||
$this->assertTrue($app->response->cookies->has('slim_session'));
|
||||
$cookie = $app->response->cookies->get('slim_session');
|
||||
$this->assertEquals(serialize(array('foo' => 'bar')), $cookie['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test $_SESSION is populated from HTTP cookie
|
||||
* Test $_SESSION is populated from an encrypted HTTP cookie
|
||||
*
|
||||
* The HTTP cookie in this test was created using the previous test; the encrypted cookie contains
|
||||
* the serialized array ['foo' => 'bar']. The middleware secret, cipher, and cipher mode are assumed
|
||||
* to be the default values.
|
||||
* The encrypted cookie contains the serialized array ['foo' => 'bar']. The
|
||||
* global secret, cipher, and cipher mode are assumed to be the default
|
||||
* values.
|
||||
*/
|
||||
public function testSessionIsPopulatedFromCookie()
|
||||
public function testSessionIsPopulatedFromEncryptedCookie()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
'PATH_INFO' => '/foo',
|
||||
'COOKIE' => 'slim_session=1644004961%7CLKkYPwqKIMvBK7MWl6D%2BxeuhLuMaW4quN%2F512ZAaVIY%3D%7Ce0f007fa852c7101e8224bb529e26be4d0dfbd63',
|
||||
'HTTP_COOKIE' => 'slim_session=1644004961%7CLKkYPwqKIMvBK7MWl6D%2BxeuhLuMaW4quN%2F512ZAaVIY%3D%7Ce0f007fa852c7101e8224bb529e26be4d0dfbd63',
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
// The cookie value in the test is encrypted, so cookies.encrypt must
|
||||
// be set to true
|
||||
$app->config('cookies.encrypt', true);
|
||||
$app->get('/foo', function () {
|
||||
echo "Success";
|
||||
});
|
||||
@@ -93,6 +94,66 @@ class SessionCookieTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(array('foo' => 'bar'), $_SESSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test $_SESSION is populated from an unencrypted HTTP cookie
|
||||
*
|
||||
* The unencrypted cookie contains the serialized array ['foo' => 'bar'].
|
||||
* The global cookies.encrypt setting is set to false
|
||||
*/
|
||||
public function testSessionIsPopulatedFromUnencryptedCookie()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
'PATH_INFO' => '/foo',
|
||||
'HTTP_COOKIE' => 'slim_session=a%3A1%3A%7Bs%3A3%3A%22foo%22%3Bs%3A3%3A%22bar%22%3B%7D',
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
// The cookie value in the test is unencrypted, so cookies.encrypt must
|
||||
// be set to false
|
||||
$app->config('cookies.encrypt', false);
|
||||
$app->get('/foo', function () {
|
||||
echo "Success";
|
||||
});
|
||||
$mw = new \Slim\Middleware\SessionCookie(array('expires' => '10 years'));
|
||||
$mw->setApplication($app);
|
||||
$mw->setNextMiddleware($app);
|
||||
$mw->call();
|
||||
$this->assertEquals(array('foo' => 'bar'), $_SESSION);
|
||||
}
|
||||
|
||||
public function testUnserializeErrorsAreCaughtAndLogged()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
'PATH_INFO' => '/foo',
|
||||
'HTTP_COOKIE' => 'slim_session=1644004961%7CLKkYPwqKIMvBK7MWl6D%2BxeuhLuMaW4quN%2F512ZAaVIY%3D%7Ce0f007fa852c7101e8224bb529e26be4d0dfbd63',
|
||||
));
|
||||
|
||||
$logWriter = $this->getMockBuilder('Slim\LogWriter')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$logWriter->expects($this->once())
|
||||
->method('write');
|
||||
$oldLevel = error_reporting(E_ALL);
|
||||
|
||||
$app = new \Slim\Slim(array(
|
||||
'log.writer' => $logWriter
|
||||
));
|
||||
// Unserializing an encrypted value fails if cookie not decrpyted
|
||||
$app->config('cookies.encrypt', false);
|
||||
$app->get('/foo', function () {
|
||||
echo "Success";
|
||||
});
|
||||
$mw = new \Slim\Middleware\SessionCookie(array('expires' => '10 years'));
|
||||
$mw->setApplication($app);
|
||||
$mw->setNextMiddleware($app);
|
||||
$mw->call();
|
||||
$this->assertEquals(array(), $_SESSION);
|
||||
|
||||
error_reporting($oldLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test $_SESSION is populated as empty array if no HTTP cookie
|
||||
*/
|
||||
@@ -112,4 +173,297 @@ class SessionCookieTest extends PHPUnit_Framework_TestCase
|
||||
$mw->call();
|
||||
$this->assertEquals(array(), $_SESSION);
|
||||
}
|
||||
|
||||
public function testSerializingTooLongValueWritesLogAndDoesntCreateCookie()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
'PATH_INFO' => '/foo'
|
||||
));
|
||||
|
||||
$logWriter = $this->getMockBuilder('Slim\LogWriter')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$logWriter->expects($this->once())
|
||||
->method('write')
|
||||
->with('WARNING! Slim\Middleware\SessionCookie data size is larger than 4KB. Content save failed.', \Slim\Log::ERROR);
|
||||
|
||||
$app = new \Slim\Slim(array(
|
||||
'log.writer' => $logWriter
|
||||
));
|
||||
|
||||
$tooLongValue = $this->getTooLongValue();
|
||||
|
||||
$app->get('/foo', function () use ($tooLongValue) {
|
||||
$_SESSION['test'] = $tooLongValue;
|
||||
echo "Success";
|
||||
});
|
||||
|
||||
$mw = new \Slim\Middleware\SessionCookie(array('expires' => '10 years'));
|
||||
$mw->setApplication($app);
|
||||
$mw->setNextMiddleware($app);
|
||||
$mw->call();
|
||||
list($status, $header, $body) = $app->response()->finalize();
|
||||
$this->assertFalse($app->response->cookies->has('slim_session'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated by http://www.random.org/strings/
|
||||
*/
|
||||
protected function getTooLongValue()
|
||||
{
|
||||
return <<<EOF
|
||||
8Y7WpaR3Fiyv0wF0QhKn
|
||||
hwgh0SYA5cNOh85lSY3E
|
||||
POUv7tHdFAKK0rmJnNUT
|
||||
dxVjXuDUlStKTiC6B2rE
|
||||
BMnchGCK2IIC83agjZ8t
|
||||
K5U9tmPok3z7n7qFJPp4
|
||||
YfMPI07qRBgZnYW3vvrj
|
||||
mY1082KeqiegFNwGiUSs
|
||||
HYE16N7PChio33DZWjsD
|
||||
urQLFxD1I0FsxPO7rora
|
||||
Nmas8nhLl1SiwnlL8eZX
|
||||
y2xe18BWfXcNHDGkfaih
|
||||
zXT7MxHXmnq0s4lowjcc
|
||||
5n8lrXmjYtIdHxl2QcMb
|
||||
emFTXQpPX9bw8WjulQCB
|
||||
Peq12lgmurt988RZiquy
|
||||
lQ5Dw86wMIcIm3uULhr7
|
||||
T8Obj45ubR8poc1l5sIs
|
||||
EG6kvcDIHVeQjUdrJuiw
|
||||
sBLmZnLll23QGK8hMFO1
|
||||
Pii0BXpzL9wpUt3hQnfe
|
||||
prkTuA8zuxU8vMOu5uSi
|
||||
Zynrx9BniMwYGPTOJVSd
|
||||
ygUsr1GQ1KGJu6ukLvgo
|
||||
7zrkBV0QM9jNqqvkzZwm
|
||||
ZnoKRJI1SbaSCqsAduCt
|
||||
q5RPtNVpHmtizY3QwiJs
|
||||
8tjGt9MG37zgKx8KhfYE
|
||||
ByoILEa2ceHjdrP6yd1G
|
||||
UMHeFx2kOCx2DVeVJIkt
|
||||
aiFdKMTE9rIbpObSp1fy
|
||||
Aei9bjwcWwHT2S22rYnj
|
||||
QHG7FEHSPdkw8acO393N
|
||||
Ip4rgim3NKanJXpfdthy
|
||||
yMh4EnoYBBoqSScfW4g5
|
||||
bVrXYt8JkyCuR5Og0JBN
|
||||
npKpr7obY4ZYVOnIF9Pe
|
||||
soEmhC8uCw73bXzMy4ui
|
||||
2oi4eFSXOoNDXZiAkz3c
|
||||
zshSls22jy5QBvEJDDtY
|
||||
C50qtymWnisOM1TIochg
|
||||
OOnMEtkUHJw21kuw6m91
|
||||
aqxRK1thCfPGBGytOmzG
|
||||
kyqvZE1oEzCONj7q4I3p
|
||||
rvbnRzZhXv21UXRJnR51
|
||||
QJyXbtzDGpSljtSt4Fxi
|
||||
SGiklrhWQCdRrnXuBExW
|
||||
mQFykwpVF07NRPet9LdT
|
||||
zOaOhwMfCeYQr2xqkKq7
|
||||
Ru2dsZdhHzhBDvV5nv1q
|
||||
qB7kVD0YDKB6RJyPcpX9
|
||||
MxvPmISfMJMFiAFD82Qf
|
||||
0idAAQxmd6fK9TkJPihp
|
||||
wp2mvp3yAHWKmdsgLcss
|
||||
OUqFt0BJoM7Iz4jJpF2d
|
||||
hiWTsF1jrgEhV07TInLp
|
||||
u7htseWgTDRY9UYp9wy6
|
||||
vnF0vsaFikqpjGkLy5oH
|
||||
ncvaoRPa5MDBNvXZoiG9
|
||||
gCMvsGG8eLW3u8UWvRrk
|
||||
bKgFBuy4zLhBF4RBuTVt
|
||||
Dz1QmbyQPqmmfjchF6u3
|
||||
myRkxQtSnHQZr0kUqSJS
|
||||
Ati7CBQq6LOPSVlAek5a
|
||||
7EOVTREQ52qOjKAibvAr
|
||||
etvEUy3CbsDiaeSPGlJH
|
||||
XyFey6LugF2UZfHDFjgV
|
||||
ByBaUrDz0yuvLOvECQuS
|
||||
5CoA6FBz8D71FwwebEYl
|
||||
5xQyEV5h7lNAsgbjBY6o
|
||||
N92xlCGjyNGWp1Y9HoNL
|
||||
mMhirp7mufNYVqIy8jBl
|
||||
nYSK8Rk6KybpAPspHXPd
|
||||
oemmqqxjF9g4ZjNk2pyL
|
||||
dqetI1RYqszZPZeH7WNW
|
||||
B1x1GSPdGXnefeNmxFxr
|
||||
vFTVOHqgOgZR0xHHUl8P
|
||||
RwFio0Cd8ZkaRIpcs7jh
|
||||
Ps0tGJgPyo1gRdm9wtlB
|
||||
j4hmInyIpAz1MjHYAQc1
|
||||
YIjnSirWsrItgqidgS3W
|
||||
LNT7DriU7wPyN6zV9G6d
|
||||
YFD19x1DDBwz57DegTsy
|
||||
rz72EblrUsP6wtN69GRo
|
||||
irhM6N9eNu8Bq9Qo5Tlc
|
||||
Cpb3Zl3FDttiW63KXQpL
|
||||
4ZQ7VGbfVjwBwhcGoOe7
|
||||
RgXxZ9OU0HJFQRpjvJDW
|
||||
lk3PpNhcHT4vVkgF9Q3V
|
||||
URiazjSe8G4zHrBBMaxM
|
||||
Gh7Xp4hqf9GTnIYyMe5E
|
||||
palqUjJhSGm7EZAR1b4i
|
||||
HN8qrHznKAyhlywYBw3N
|
||||
nV9Kla5KFWaRG4r3cCT1
|
||||
qHT7nPIbVjxNYdujh5WK
|
||||
CKg7BfQjwZtHk2oM1cyO
|
||||
RBPMpZxNpM3ZhiXNz5D2
|
||||
xZJM9ETPwABBqHirjTXA
|
||||
faI4irlrshHra2hg6mHE
|
||||
N0OLyZjmKpyzHRlAcC44
|
||||
oEMe1Mq85Kynyla7S3Lo
|
||||
Us9auTpKq33jAI51MUvC
|
||||
Vbu2qKSsmCrXu1WMDFfL
|
||||
WCCzzLqz2kfMy3IV0ngc
|
||||
ya4k4AoSjb2nd43VGRvt
|
||||
1FrWocIRfoyFj3igs8lF
|
||||
dQlTXv3jttgGmHVJtuJK
|
||||
zCHcfzABc5pNch7cEW4B
|
||||
r8jB0mL9ESrMHhvqGxbf
|
||||
qLUYdNrXNJNujy43WNLt
|
||||
GaQ6adUTFHErjRYFj7ws
|
||||
btv28UZlttBqlVAEpu7G
|
||||
1Se9HT2tp45a5iwbAHpA
|
||||
tXaOwMjaI3S1uxngaVVL
|
||||
saFZXdx4kExE3Y3SEMTA
|
||||
my9rhAEFcw4N1uBqa2Ts
|
||||
IRupwTKFoRIpPSBwnPPw
|
||||
qpxq4VIrOdESR4UZiOcw
|
||||
1n12beyYTUN0zNzV0nRf
|
||||
dkgrmnaeWbrxA2QQaHDq
|
||||
o1f6VCap62NxJI2Wd0F7
|
||||
eyYYL6mY0XUmuCdV2v9e
|
||||
SPBqa552akcetnRViZD9
|
||||
cqLrX89ouNlDcjC7hmYk
|
||||
3vAcrwlseFDYDYzrCXXx
|
||||
tkyJUeJjORVXoFKaoEmi
|
||||
o1JoqBFpSPyRT6RwFTXC
|
||||
IMW657539XCcn0Tvx3iJ
|
||||
rW9ZUNBSHNHjR0wfbr1R
|
||||
x7Ez1Br1T9VG4wEetwfY
|
||||
Xj9s0ipdQDEeYG3eCkBG
|
||||
xQCp4J0a7BEqEEVPJvYY
|
||||
S46aXD70Ur3BiokRfeJK
|
||||
kEQcqPCP9kmWxXboESOB
|
||||
VjADYs7ZwJUvWNAk0Msc
|
||||
5cSrhWsbizSwo31NsPKj
|
||||
PHKG7ui9gU0F5fXKXtWz
|
||||
8FxjchkHJ3jQQSWKfkSu
|
||||
pN8e9d71IVYA1vLyQGqV
|
||||
Hh3QE3o9tmNsJMEBoRK8
|
||||
QBLTFWWfkGSOI3Vp3y6c
|
||||
5gwll5qdcgnaF4tDvdRd
|
||||
NDYpacWX4hnFsrO73OOo
|
||||
GaenbdbDOUp0iClZKlTU
|
||||
79UJvctLD86KC2mwxSqc
|
||||
jbwmzM4oZZ7zuYo769YY
|
||||
B7Ssx6qbITbIqaJJboMK
|
||||
7tLwsE3FhBphBJBKP4Bk
|
||||
aumHnttxOXpiX3b5ivlk
|
||||
gsvWRKCd1KLYkucRdW1j
|
||||
j0TSXNoMGXlIK9X6YjX1
|
||||
4zvHH7QEPlgK4AaRWw6r
|
||||
eXSVfE2X2nbn1wzA3bdw
|
||||
exrWkKQ8v87kzzxpzdF7
|
||||
wL9B42yeyA6SgfnZ0SnW
|
||||
hyO53wkaJNQnK2rzndcA
|
||||
8jSesmehxaHL39QUdlEo
|
||||
oAQMANsGVewC4cYhdjpk
|
||||
tBVMFz1LMIg8nj5acoKx
|
||||
4IxsrP4UrdaHa2QlFZ38
|
||||
OMg0erS6Mg2nVY9PBLGu
|
||||
WLybJJlrNJ3ZKgftRyOb
|
||||
s392j4FVZuxnLc8Euq2g
|
||||
2AB9ceeOXHrw6dJeqImY
|
||||
q8Gqy9rzsKyp9vEg13h3
|
||||
UhWoiMQuE8i38vd5HZuO
|
||||
CjLfC9MtQY7wou4YGl1f
|
||||
bQGFeV3I1YVsyh1zjdYX
|
||||
E4yS7PXLT2pTvq9aTuPc
|
||||
41Vm8F6tc6mnYCc0gfCY
|
||||
nmKOUzThbGpqnSkJzmr5
|
||||
E5izT37qIM1PJ1IotRnw
|
||||
X0rD7K2rUN47XeLXW3x2
|
||||
3taWQ4GMNGQgjuD7MPwX
|
||||
u7AyGdUWFG25ZaeZSyrt
|
||||
mLPs4NU5ayAgrj9L089E
|
||||
5mWnKfJ8OoAbhjb9XpY5
|
||||
cBv75uTcpezbnWe5C7YC
|
||||
DWikoIaaJQebFW2tddw2
|
||||
qMyIzbkUJxyTheONxBjJ
|
||||
WyWqJmTW5uniw9ofX84U
|
||||
JaFGtu4y24UGSmPrIjVj
|
||||
SDFz3iRvf2FG65m8brV9
|
||||
0mpT6dWL4p59cdTs0n1c
|
||||
jw7rIgu3VFnkuOp8mZR3
|
||||
F1PPQYZfZkqbyiu7Tvl6
|
||||
tXT8EPpH39oB9Qe3SI6C
|
||||
DwL6cklHbnOyEOO5jNOo
|
||||
vEORF3tEYRngOowzuOEY
|
||||
6XY27pGEG9L9MvwvHinw
|
||||
rEMyl7S9eFk554yHvCa3
|
||||
pLToqRXBWIPK51roFlKs
|
||||
AXfdbVdGkGqwlKn68k01
|
||||
ecFbbnvrpmcLF2gL3GbC
|
||||
aWJf90PECBF0qqZ1jVC3
|
||||
WjMuah0gZjryj7zsZKMB
|
||||
1J9koTowUYguyp4MBGmp
|
||||
rnjhybC8RQSEvmYpqkGR
|
||||
Qdj2QlGYXN1H8A1315QJ
|
||||
amycQeWwXnrdI3duyqTa
|
||||
H2YwgIStIGQlWNigfiIZ
|
||||
btR0CdDnkwGt0hlCtQF0
|
||||
O37vtIvVgCKVbcXbBexH
|
||||
xhkbsShz4onN4CeGf7Ox
|
||||
1vJfx422pUnxtjG5Laag
|
||||
3IV5ib20qSYZW3Wr2LiH
|
||||
zmvoTLblxTX3EpYPlHxC
|
||||
U0Ceix4L3dMomXzn7OAC
|
||||
JyzkRGfIi8j4EnKfoWPG
|
||||
gMUXWXZZgJzLBfZ4y9FV
|
||||
7ClYOAd9EoWspOWQ1MmO
|
||||
1CIKB3Ei846C1rmXS8Zc
|
||||
ARLDXFpaHp1VlbEMF8fk
|
||||
KrQa28U3gbHs9B5oGhxS
|
||||
WHc9LmQiINcUglo8cKPs
|
||||
3WMYJ8TAtvlMswUPOd6t
|
||||
s81Cy4B2oLrc4E5XSa5p
|
||||
QA6pDUiKipuWFXZ4BMUF
|
||||
E03CQbBiZ27GpJekftsF
|
||||
pqGkJifdjVLuuIu0xBej
|
||||
V27rk0vIwp1Q8p4DvJ1F
|
||||
TPhvHNooyU6Rrmcx8GIK
|
||||
81nRsYYsvVo3LCmuOnX5
|
||||
uY6xGTes3UOMXkXwEfGj
|
||||
T5LfaSyWP5y4L7vvLBjS
|
||||
dHO7dVB1bmIA40fEgk3i
|
||||
KHJxU6C0rUVtPtIR1slm
|
||||
YdhTz1mwWi2z2GDzzRJB
|
||||
TIzFqPkKrgCgkiv2RzCg
|
||||
Z0qY4Wjpfug51zXzU51H
|
||||
nWm3mJnVLAKv9RNkdThl
|
||||
xk28IMKOGOPdQuXjGDB6
|
||||
eEG3ndIRXnmmLilygHop
|
||||
jE6u88nWi30Yos79canx
|
||||
b0VuROFF04rZuOTo5Fue
|
||||
yt4fSpHN7v4uZ7uNPMA9
|
||||
0sENIYeLlIbBWhqTjXCp
|
||||
m7qMMX3acdRtTTVNp7Qt
|
||||
s8XKOJmCQr7YGk47jGMn
|
||||
6o1kxMmoUgWCW8rEtnWA
|
||||
kxXj1hKRFBJmX8ErM6Zp
|
||||
FZBIPSbNt5hmXoC1M92l
|
||||
UxeirI2PCJnQcAJVmNVJ
|
||||
FaJ9L5K0u1J9JKGl2Aew
|
||||
bHGX5QLvkGXSFY5OCezp
|
||||
5cnbOjU1j8Fuvtuuk9d0
|
||||
7Oz2IIi69WB5J14n9iWQ
|
||||
XgCpDLURX3urpiYDFf3P
|
||||
7xeWOS4yTMUQ0EbLkZOU
|
||||
AzKM3Dp7nGr9SYPI4xmi
|
||||
EOF;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-38
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -30,57 +30,50 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
class My_Middleware extends \Slim\Middleware
|
||||
class MyMiddleware extends \Slim\Middleware
|
||||
{
|
||||
public function call()
|
||||
{
|
||||
echo "Before";
|
||||
$this->next->call();
|
||||
echo "After";
|
||||
}
|
||||
}
|
||||
|
||||
class My_Application
|
||||
{
|
||||
public function call()
|
||||
{
|
||||
echo "Application";
|
||||
}
|
||||
public function call() {}
|
||||
}
|
||||
|
||||
class MiddlewareTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Get and set application
|
||||
*/
|
||||
public function testGetAndSetApplication()
|
||||
public function testSetApplication()
|
||||
{
|
||||
$app = new My_Application();
|
||||
$mw = new My_Middleware();
|
||||
$app = new stdClass();
|
||||
$mw = new MyMiddleware();
|
||||
$mw->setApplication($app);
|
||||
|
||||
$this->assertAttributeSame($app, 'app', $mw);
|
||||
}
|
||||
|
||||
public function testGetApplication()
|
||||
{
|
||||
$app = new stdClass();
|
||||
$mw = new MyMiddleware();
|
||||
$property = new \ReflectionProperty($mw, 'app');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($mw, $app);
|
||||
|
||||
$this->assertSame($app, $mw->getApplication());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and set next middleware
|
||||
*/
|
||||
public function testGetAndSetNextMiddleware()
|
||||
public function testSetNextMiddleware()
|
||||
{
|
||||
$mw1 = new My_Middleware();
|
||||
$mw2 = new My_Middleware();
|
||||
$mw1 = new MyMiddleware();
|
||||
$mw2 = new MyMiddleware();
|
||||
$mw1->setNextMiddleware($mw2);
|
||||
$this->assertSame($mw2, $mw1->getNextMiddleware());
|
||||
|
||||
$this->assertAttributeSame($mw2, 'next', $mw1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test call
|
||||
*/
|
||||
public function testCall()
|
||||
public function testGetNextMiddleware()
|
||||
{
|
||||
$this->expectOutputString('BeforeApplicationAfter');
|
||||
$app = new My_Application();
|
||||
$mw = new My_Middleware();
|
||||
$mw->setNextMiddleware($app);
|
||||
$mw->call();
|
||||
$mw1 = new MyMiddleware();
|
||||
$mw2 = new MyMiddleware();
|
||||
$property = new \ReflectionProperty($mw1, 'next');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($mw1, $mw2);
|
||||
|
||||
$this->assertSame($mw2, $mw1->getNextMiddleware());
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+375
-399
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -29,292 +29,202 @@
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Used for passing callable via string
|
||||
function testCallable() {}
|
||||
|
||||
class RouteTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Route should set name
|
||||
*/
|
||||
public function testRouteSetsName()
|
||||
public function testGetPattern()
|
||||
{
|
||||
$route = new \Slim\Route('/foo/bar', function () {});
|
||||
$route->name('foo');
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$this->assertEquals('/foo', $route->getPattern());
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($route, 'name');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, 'foo');
|
||||
|
||||
$this->assertEquals('foo', $route->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Route should set pattern
|
||||
*/
|
||||
public function testRouteSetsPattern()
|
||||
public function testSetName()
|
||||
{
|
||||
$route1 = new \Slim\Route('/foo/bar', function () {});
|
||||
$this->assertEquals('/foo/bar', $route1->getPattern());
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$route->name('foo'); // <-- Alias for `setName()`
|
||||
|
||||
$this->assertAttributeEquals('foo', 'name', $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route sets pattern with params
|
||||
*/
|
||||
public function testRouteSetsPatternWithParams()
|
||||
public function testGetCallable()
|
||||
{
|
||||
$route = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
$this->assertEquals('/hello/:first/:last', $route->getPattern());
|
||||
}
|
||||
$callable = function () {
|
||||
echo 'Foo';
|
||||
};
|
||||
$route = new \Slim\Route('/foo', $callable);
|
||||
|
||||
/**
|
||||
* Route sets custom pattern that overrides pattern
|
||||
*/
|
||||
public function testRouteSetsCustomTemplate()
|
||||
{
|
||||
$route = new \Slim\Route('/hello/*', function () {});
|
||||
$route->setPattern('/hello/:name');
|
||||
$this->assertEquals('/hello/:name', $route->getPattern());
|
||||
}
|
||||
|
||||
/**
|
||||
* Route should store a reference to the callable
|
||||
* anonymous function.
|
||||
*/
|
||||
public function testRouteSetsCallableAsFunction()
|
||||
{
|
||||
$callable = function () { echo "Foo!"; };
|
||||
$route = new \Slim\Route('/foo/bar', $callable);
|
||||
$this->assertSame($callable, $route->getCallable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Route should store a reference to the callable
|
||||
* regular function (for PHP 5 < 5.3)
|
||||
*/
|
||||
public function testRouteSetsCallableAsString()
|
||||
public function testGetCallableAsClass()
|
||||
{
|
||||
$route = new \Slim\Route('/foo/bar', 'testCallable');
|
||||
$this->assertEquals('testCallable', $route->getCallable());
|
||||
$route = new \Slim\Route('/foo', '\Slim\Router:getCurrentRoute');
|
||||
|
||||
$callable = $route->getCallable();
|
||||
$this->assertInstanceOf('\Slim\Router', $callable[0]);
|
||||
$this->assertEquals('getCurrentRoute', $callable[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route should throw exception when creating with an invalid callable
|
||||
*/
|
||||
public function testRouteThrowsExecptionWithInvalidCallable()
|
||||
public function testGetCallableAsStaticMethod()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
$route = new \Slim\Route('/foo/bar', 'fnDoesNotExist');
|
||||
$route = new \Slim\Route('/bar', '\Slim\Slim::getInstance');
|
||||
|
||||
$callable = $route->getCallable();
|
||||
$this->assertEquals('\Slim\Slim::getInstance', $callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route should throw exception when setting an invalid callable
|
||||
*/
|
||||
public function testRouteThrowsExecptionWhenSettingInvalidCallable()
|
||||
public function testSetCallable()
|
||||
{
|
||||
$route = new \Slim\Route('/foo/bar', function () {});
|
||||
try
|
||||
{
|
||||
$route->setCallable('fnDoesNotExist');
|
||||
$this->fail('Did not catch InvalidArgumentException when setting invalid callable');
|
||||
} catch(\InvalidArgumentException $e) {}
|
||||
$callable = function () {
|
||||
echo 'Foo';
|
||||
};
|
||||
$route = new \Slim\Route('/foo', $callable); // <-- Called inside __construct()
|
||||
|
||||
$this->assertAttributeSame($callable, 'callable', $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test gets all params
|
||||
*/
|
||||
public function testGetRouteParams()
|
||||
public function testSetCallableWithInvalidArgument()
|
||||
{
|
||||
$this->setExpectedException('\InvalidArgumentException');
|
||||
$route = new \Slim\Route('/foo', 'doesNotExist'); // <-- Called inside __construct()
|
||||
}
|
||||
|
||||
public function testGetParams()
|
||||
{
|
||||
// Prepare route
|
||||
$requestUri = '/hello/mr/anderson';
|
||||
$route = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
$route->matches('/hello/mr/anderson'); // <-- Parses params from argument
|
||||
|
||||
// Parse route params
|
||||
$this->assertTrue($route->matches($requestUri));
|
||||
|
||||
// Get params
|
||||
$params = $route->getParams();
|
||||
$this->assertEquals(2, count($params));
|
||||
$this->assertEquals('mr', $params['first']);
|
||||
$this->assertEquals('anderson', $params['last']);
|
||||
$this->assertEquals(array(
|
||||
'first' => 'mr',
|
||||
'last' => 'anderson'
|
||||
), $route->getParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sets all params
|
||||
*/
|
||||
public function testSetRouteParams()
|
||||
public function testSetParams()
|
||||
{
|
||||
// Prepare route
|
||||
$requestUri = '/hello/mr/anderson';
|
||||
$route = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
|
||||
// Parse route params
|
||||
$this->assertTrue($route->matches($requestUri));
|
||||
|
||||
// Get params
|
||||
$params = $route->getParams();
|
||||
$this->assertEquals(2, count($params));
|
||||
$this->assertEquals('mr', $params['first']);
|
||||
$this->assertEquals('anderson', $params['last']);
|
||||
|
||||
// Replace params
|
||||
$route->matches('/hello/mr/anderson'); // <-- Parses params from argument
|
||||
$route->setParams(array(
|
||||
'first' => 'john',
|
||||
'first' => 'agent',
|
||||
'last' => 'smith'
|
||||
));
|
||||
|
||||
// Get new params
|
||||
$params = $route->getParams();
|
||||
$this->assertEquals(2, count($params));
|
||||
$this->assertEquals('john', $params['first']);
|
||||
$this->assertEquals('smith', $params['last']);
|
||||
$this->assertAttributeEquals(array(
|
||||
'first' => 'agent',
|
||||
'last' => 'smith'
|
||||
), 'params', $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test gets param when exists
|
||||
*/
|
||||
public function testGetRouteParamWhenExists()
|
||||
public function testGetParam()
|
||||
{
|
||||
// Prepare route
|
||||
$requestUri = '/hello/mr/anderson';
|
||||
$route = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
|
||||
// Parse route params
|
||||
$this->assertTrue($route->matches($requestUri));
|
||||
$property = new \ReflectionProperty($route, 'params');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, array(
|
||||
'first' => 'foo',
|
||||
'last' => 'bar'
|
||||
));
|
||||
|
||||
// Get param
|
||||
$this->assertEquals('anderson', $route->getParam('last'));
|
||||
$this->assertEquals('foo', $route->getParam('first'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test gets param when not exists
|
||||
*/
|
||||
public function testGetRouteParamWhenNotExists()
|
||||
public function testGetParamThatDoesNotExist()
|
||||
{
|
||||
// Prepare route
|
||||
$requestUri = '/hello/mr/anderson';
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$route = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
|
||||
// Parse route params
|
||||
$this->assertTrue($route->matches($requestUri));
|
||||
$property = new \ReflectionProperty($route, 'params');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, array(
|
||||
'first' => 'foo',
|
||||
'last' => 'bar'
|
||||
));
|
||||
|
||||
// Get param
|
||||
try {
|
||||
$param = $route->getParam('foo');
|
||||
$this->fail('Did not catch expected InvalidArgumentException');
|
||||
} catch ( \InvalidArgumentException $e ) {}
|
||||
$route->getParam('middle');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sets param when exists
|
||||
*/
|
||||
public function testSetRouteParamWhenExists()
|
||||
public function testSetParam()
|
||||
{
|
||||
// Prepare route
|
||||
$requestUri = '/hello/mr/anderson';
|
||||
$route = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
|
||||
// Parse route params
|
||||
$this->assertTrue($route->matches($requestUri));
|
||||
|
||||
// Get param
|
||||
$this->assertEquals('anderson', $route->getParam('last'));
|
||||
|
||||
// Set param
|
||||
$route->matches('/hello/mr/anderson'); // <-- Parses params from argument
|
||||
$route->setParam('last', 'smith');
|
||||
|
||||
// Get new param
|
||||
$this->assertEquals('smith', $route->getParam('last'));
|
||||
$this->assertAttributeEquals(array(
|
||||
'first' => 'mr',
|
||||
'last' => 'smith'
|
||||
), 'params', $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sets param when not exists
|
||||
*/
|
||||
public function testSetRouteParamWhenNotExists()
|
||||
public function testSetParamThatDoesNotExist()
|
||||
{
|
||||
// Prepare route
|
||||
$requestUri = '/hello/mr/anderson';
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$route = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
|
||||
// Parse route params
|
||||
$this->assertTrue($route->matches($requestUri));
|
||||
|
||||
// Get param
|
||||
try {
|
||||
$param = $route->setParam('foo', 'bar');
|
||||
$this->fail('Did not catch expected InvalidArgumentException');
|
||||
} catch ( \InvalidArgumentException $e ) {}
|
||||
$route->matches('/hello/mr/anderson'); // <-- Parses params from argument
|
||||
$route->setParam('middle', 'smith'); // <-- Should trigger InvalidArgumentException
|
||||
}
|
||||
|
||||
/**
|
||||
* If route matches a resource URI, param should be extracted.
|
||||
*/
|
||||
public function testRouteMatchesAndParamExtracted()
|
||||
public function testMatches()
|
||||
{
|
||||
$resource = '/hello/Josh';
|
||||
$route = new \Slim\Route('/hello/:name', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('name' => 'Josh'), $route->getParams());
|
||||
|
||||
$this->assertTrue($route->matches('/hello/josh'));
|
||||
}
|
||||
|
||||
/**
|
||||
* If route matches a resource URI, multiple params should be extracted.
|
||||
*/
|
||||
public function testRouteMatchesAndMultipleParamsExtracted()
|
||||
public function testMatchesIsFalse()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$this->assertFalse($route->matches('/bar'));
|
||||
}
|
||||
|
||||
public function testMatchesPatternWithTrailingSlash()
|
||||
{
|
||||
$route = new \Slim\Route('/foo/', function () {});
|
||||
|
||||
$this->assertTrue($route->matches('/foo/'));
|
||||
$this->assertTrue($route->matches('/foo'));
|
||||
}
|
||||
|
||||
public function testMatchesPatternWithoutTrailingSlash()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$this->assertFalse($route->matches('/foo/'));
|
||||
$this->assertTrue($route->matches('/foo'));
|
||||
}
|
||||
|
||||
public function testMatchesWithConditions()
|
||||
{
|
||||
$resource = '/hello/Josh/and/John';
|
||||
$route = new \Slim\Route('/hello/:first/and/:second', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('first' => 'Josh', 'second' => 'John'), $route->getParams());
|
||||
$route->conditions(array(
|
||||
'first' => '[a-zA-Z]{3,}'
|
||||
));
|
||||
|
||||
$this->assertTrue($route->matches('/hello/Josh/and/John'));
|
||||
}
|
||||
|
||||
/**
|
||||
* If route does not match a resource URI, params remain an empty array
|
||||
*/
|
||||
public function testRouteDoesNotMatchAndParamsNotExtracted()
|
||||
public function testMatchesWithConditionsIsFalse()
|
||||
{
|
||||
$resource = '/foo/bar';
|
||||
$route = new \Slim\Route('/hello/:name', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals(array(), $route->getParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Route matches URI with trailing slash
|
||||
*
|
||||
*/
|
||||
public function testRouteMatchesWithTrailingSlash()
|
||||
{
|
||||
$resource1 = '/foo/bar/';
|
||||
$resource2 = '/foo/bar';
|
||||
$route = new \Slim\Route('/foo/:one/', function () {});
|
||||
$this->assertTrue($route->matches($resource1));
|
||||
$this->assertTrue($route->matches($resource2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Route matches URI with conditions
|
||||
*/
|
||||
public function testRouteMatchesResourceWithConditions()
|
||||
{
|
||||
$resource = '/hello/Josh/and/John';
|
||||
$route = new \Slim\Route('/hello/:first/and/:second', function () {});
|
||||
$route->conditions(array('first' => '[a-zA-Z]{3,}'));
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('first' => 'Josh', 'second' => 'John'), $route->getParams());
|
||||
}
|
||||
$route->conditions(array(
|
||||
'first' => '[a-z]{3,}'
|
||||
));
|
||||
|
||||
/**
|
||||
* Route does not match URI with conditions
|
||||
*/
|
||||
public function testRouteDoesNotMatchResourceWithConditions()
|
||||
{
|
||||
$resource = '/hello/Josh/and/John';
|
||||
$route = new \Slim\Route('/hello/:first/and/:second', function () {});
|
||||
$route->conditions(array('first' => '[a-z]{3,}'));
|
||||
$result = $route->matches($resource);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals(array(), $route->getParams());
|
||||
$this->assertFalse($route->matches('/hello/Josh/and/John'));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -324,14 +234,12 @@ class RouteTest extends PHPUnit_Framework_TestCase
|
||||
*
|
||||
* Excludes "+" which is valid but decodes into a space character
|
||||
*/
|
||||
public function testRouteMatchesResourceWithValidRfc2396PathComponent()
|
||||
public function testMatchesWithValidRfc2396PathComponent()
|
||||
{
|
||||
$symbols = ':@&=$,';
|
||||
$resource = '/rfc2386/' . $symbols;
|
||||
$route = new \Slim\Route('/rfc2386/:symbols', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('symbols' => $symbols), $route->getParams());
|
||||
|
||||
$this->assertTrue($route->matches('/rfc2386/' . $symbols));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -339,221 +247,289 @@ class RouteTest extends PHPUnit_Framework_TestCase
|
||||
*
|
||||
* "Uniform Resource Identifiers (URI): Generic Syntax" http://www.ietf.org/rfc/rfc2396.txt
|
||||
*/
|
||||
public function testRouteMatchesResourceWithUnreservedMarks()
|
||||
public function testMatchesWithUnreservedMarks()
|
||||
{
|
||||
$marks = "-_.!~*'()";
|
||||
$resource = '/marks/' . $marks;
|
||||
$route = new \Slim\Route('/marks/:marks', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('marks' => $marks), $route->getParams());
|
||||
|
||||
$this->assertTrue($route->matches('/marks/' . $marks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Route optional parameters
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Route pattern requires :year, optionally accepts :month and :day
|
||||
*
|
||||
* Post-conditions:
|
||||
* All: Year is 2010
|
||||
* Case A: Month and day default values are used
|
||||
* Case B: Month is "05" and day default value is used
|
||||
* Case C: Month is "05" and day is "13"
|
||||
*/
|
||||
public function testRouteOptionalParameters()
|
||||
public function testMatchesOptionalParameters()
|
||||
{
|
||||
$pattern = '/archive/:year(/:month(/:day))';
|
||||
|
||||
//Case A
|
||||
$routeA = new \Slim\Route($pattern, function () {});
|
||||
$resourceA = '/archive/2010';
|
||||
$resultA = $routeA->matches($resourceA);
|
||||
$this->assertTrue($resultA);
|
||||
$this->assertEquals(array('year' => '2010'), $routeA->getParams());
|
||||
$route1 = new \Slim\Route($pattern, function () {});
|
||||
$this->assertTrue($route1->matches('/archive/2010'));
|
||||
$this->assertEquals(array('year' => '2010'), $route1->getParams());
|
||||
|
||||
//Case B
|
||||
$routeB = new \Slim\Route($pattern, function () {});
|
||||
$resourceB = '/archive/2010/05';
|
||||
$resultB = $routeB->matches($resourceB);
|
||||
$this->assertTrue($resultB);
|
||||
$this->assertEquals(array('year' => '2010', 'month' => '05'), $routeB->getParams());
|
||||
$route2 = new \Slim\Route($pattern, function () {});
|
||||
$this->assertTrue($route2->matches('/archive/2010/05'));
|
||||
$this->assertEquals(array('year' => '2010', 'month' => '05'), $route2->getParams());
|
||||
|
||||
//Case C
|
||||
$routeC = new \Slim\Route($pattern, function () {});
|
||||
$resourceC = '/archive/2010/05/13';
|
||||
$resultC = $routeC->matches($resourceC);
|
||||
$this->assertTrue($resultC);
|
||||
$this->assertEquals(array('year' => '2010', 'month' => '05', 'day' => '13'), $routeC->getParams());
|
||||
$route3 = new \Slim\Route($pattern, function () {});
|
||||
$this->assertTrue($route3->matches('/archive/2010/05/13'));
|
||||
$this->assertEquals(array('year' => '2010', 'month' => '05', 'day' => '13'), $route3->getParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test route default conditions
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Route class has default conditions;
|
||||
*
|
||||
* Post-conditions:
|
||||
* Case A: Route instance has default conditions;
|
||||
* Case B: Route instance has newly merged conditions;
|
||||
*/
|
||||
public function testRouteDefaultConditions()
|
||||
public function testGetConditions()
|
||||
{
|
||||
\Slim\Route::setDefaultConditions(array('id' => '\d+'));
|
||||
$r = new \Slim\Route('/foo', function () {});
|
||||
//Case A
|
||||
$this->assertEquals(\Slim\Route::getDefaultConditions(), $r->getConditions());
|
||||
//Case B
|
||||
$r->conditions(array('name' => '[a-z]{2,5}'));
|
||||
$c = $r->getConditions();
|
||||
$this->assertArrayHasKey('id', $c);
|
||||
$this->assertArrayHasKey('name', $c);
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($route, 'conditions');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, array('foo' => '\d{3}'));
|
||||
|
||||
$this->assertEquals(array('foo' => '\d{3}'), $route->getConditions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Route matches URI with wildcard
|
||||
*/
|
||||
public function testRouteMatchesResourceWithWildcard()
|
||||
public function testSetDefaultConditions()
|
||||
{
|
||||
\Slim\Route::setDefaultConditions(array(
|
||||
'id' => '\d+'
|
||||
));
|
||||
|
||||
$property = new \ReflectionProperty('\Slim\Route', 'defaultConditions');
|
||||
$property->setAccessible(true);
|
||||
|
||||
$this->assertEquals(array(
|
||||
'id' => '\d+'
|
||||
), $property->getValue());
|
||||
}
|
||||
|
||||
public function testGetDefaultConditions()
|
||||
{
|
||||
$property = new \ReflectionProperty('\Slim\Route', 'defaultConditions');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue(array(
|
||||
'id' => '\d+'
|
||||
));
|
||||
|
||||
$this->assertEquals(array(
|
||||
'id' => '\d+'
|
||||
), \Slim\Route::getDefaultConditions());
|
||||
}
|
||||
|
||||
public function testDefaultConditionsAssignedToInstance()
|
||||
{
|
||||
$staticProperty = new \ReflectionProperty('\Slim\Route', 'defaultConditions');
|
||||
$staticProperty->setAccessible(true);
|
||||
$staticProperty->setValue(array(
|
||||
'id' => '\d+'
|
||||
));
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$this->assertAttributeEquals(array(
|
||||
'id' => '\d+'
|
||||
), 'conditions', $route);
|
||||
}
|
||||
|
||||
public function testMatchesWildcard()
|
||||
{
|
||||
$resource = '/hello/foo/bar/world';
|
||||
$route = new \Slim\Route('/hello/:path+/world', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('path'=>array('foo', 'bar')), $route->getParams());
|
||||
|
||||
$this->assertTrue($route->matches('/hello/foo/bar/world'));
|
||||
$this->assertAttributeEquals(array(
|
||||
'path' => array('foo', 'bar')
|
||||
), 'params', $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route matches URI with more than one wildcard
|
||||
*/
|
||||
public function testRouteMatchesResourceWithMultipleWildcards()
|
||||
public function testMatchesMultipleWildcards()
|
||||
{
|
||||
$resource = '/hello/foo/bar/world/2012/03/10';
|
||||
$route = new \Slim\Route('/hello/:path+/world/:date+', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('path'=>array('foo', 'bar'), 'date'=>array('2012', '03', '10')), $route->getParams());
|
||||
|
||||
$this->assertTrue($route->matches('/hello/foo/bar/world/2012/03/10'));
|
||||
$this->assertAttributeEquals(array(
|
||||
'path' => array('foo', 'bar'),
|
||||
'date' => array('2012', '03', '10')
|
||||
), 'params', $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route matches URI with wildcards and parameters
|
||||
*/
|
||||
public function testRouteMatchesResourceWithWildcardsAndParams()
|
||||
public function testMatchesParamsAndWildcards()
|
||||
{
|
||||
$resource = '/hello/foo/bar/world/2012/03/10/first/second';
|
||||
$route = new \Slim\Route('/hello/:path+/world/:year/:month/:day/:path2+', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(array('path'=>array('foo', 'bar'), 'year'=>'2012', 'month'=>'03', 'day'=>'10', 'path2'=>array('first', 'second')), $route->getParams());
|
||||
|
||||
$this->assertTrue($route->matches('/hello/foo/bar/world/2012/03/10/first/second'));
|
||||
$this->assertAttributeEquals(array(
|
||||
'path' => array('foo', 'bar'),
|
||||
'year' => '2012',
|
||||
'month' => '03',
|
||||
'day' => '10',
|
||||
'path2' => array('first', 'second')
|
||||
), 'params', $route);
|
||||
}
|
||||
|
||||
public function testMatchesParamsWithOptionalWildcard()
|
||||
{
|
||||
$route = new \Slim\Route('/hello(/:foo(/:bar+))', function () {});
|
||||
|
||||
$this->assertTrue($route->matches('/hello'));
|
||||
$this->assertTrue($route->matches('/hello/world'));
|
||||
$this->assertTrue($route->matches('/hello/world/foo'));
|
||||
$this->assertTrue($route->matches('/hello/world/foo/bar'));
|
||||
}
|
||||
|
||||
public function testSetMiddleware()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$mw = function () {
|
||||
echo 'Foo';
|
||||
};
|
||||
$route->setMiddleware($mw);
|
||||
|
||||
$this->assertAttributeContains($mw, 'middleware', $route);
|
||||
}
|
||||
|
||||
public function testSetMiddlewareMultipleTimes()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$mw1 = function () {
|
||||
echo 'Foo';
|
||||
};
|
||||
$mw2 = function () {
|
||||
echo 'Bar';
|
||||
};
|
||||
$route->setMiddleware($mw1);
|
||||
$route->setMiddleware($mw2);
|
||||
|
||||
$this->assertAttributeContains($mw1, 'middleware', $route);
|
||||
$this->assertAttributeContains($mw2, 'middleware', $route);
|
||||
}
|
||||
|
||||
public function testSetMiddlewareWithArray()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$mw1 = function () {
|
||||
echo 'Foo';
|
||||
};
|
||||
$mw2 = function () {
|
||||
echo 'Bar';
|
||||
};
|
||||
$route->setMiddleware(array($mw1, $mw2));
|
||||
|
||||
$this->assertAttributeContains($mw1, 'middleware', $route);
|
||||
$this->assertAttributeContains($mw2, 'middleware', $route);
|
||||
}
|
||||
|
||||
public function testSetMiddlewareWithInvalidArgument()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$route->setMiddleware('doesNotExist'); // <-- Should throw InvalidArgumentException
|
||||
}
|
||||
|
||||
public function testSetMiddlewareWithArrayWithInvalidArgument()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$route->setMiddleware(array('doesNotExist'));
|
||||
}
|
||||
|
||||
public function testGetMiddleware()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($route, 'middleware');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, array('foo' => 'bar'));
|
||||
|
||||
$this->assertEquals(array('foo' => 'bar'), $route->getMiddleware());
|
||||
}
|
||||
|
||||
public function testSetHttpMethods()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$route->setHttpMethods('GET', 'POST');
|
||||
|
||||
$this->assertAttributeEquals(array('GET', 'POST'), 'methods', $route);
|
||||
}
|
||||
|
||||
public function testGetHttpMethods()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($route, 'methods');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, array('GET', 'POST'));
|
||||
|
||||
$this->assertEquals(array('GET', 'POST'), $route->getHttpMethods());
|
||||
}
|
||||
|
||||
public function testAppendHttpMethods()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($route, 'methods');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, array('GET', 'POST'));
|
||||
|
||||
$route->appendHttpMethods('PUT');
|
||||
|
||||
$this->assertAttributeEquals(array('GET', 'POST', 'PUT'), 'methods', $route);
|
||||
}
|
||||
|
||||
public function testAppendHttpMethodsWithVia()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$route->via('PUT');
|
||||
|
||||
$this->assertAttributeContains('PUT', 'methods', $route);
|
||||
}
|
||||
|
||||
public function testSupportsHttpMethod()
|
||||
{
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($route, 'methods');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($route, array('POST'));
|
||||
|
||||
$this->assertTrue($route->supportsHttpMethod('POST'));
|
||||
$this->assertFalse($route->supportsHttpMethod('PUT'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Route matches URI with optional wildcard and parameter
|
||||
* Test dispatch with params
|
||||
*/
|
||||
public function testRouteMatchesResourceWithOptionalWildcardsAndParams()
|
||||
public function testDispatch()
|
||||
{
|
||||
$resourceA = '/hello/world/foo/bar';
|
||||
$routeA = new \Slim\Route('/hello(/:world(/:path+))', function () {});
|
||||
$this->assertTrue($routeA->matches($resourceA));
|
||||
$this->assertEquals(array('world'=>'world', 'path'=>array('foo', 'bar')), $routeA->getParams());
|
||||
|
||||
$resourceB = '/hello/world';
|
||||
$routeB = new \Slim\Route('/hello(/:world(/:path))', function () {});
|
||||
$this->assertTrue($routeB->matches($resourceB));
|
||||
$this->assertEquals(array('world'=>'world'), $routeB->getParams());
|
||||
$this->expectOutputString('Hello josh');
|
||||
$route = new \Slim\Route('/hello/:name', function ($name) { echo "Hello $name"; });
|
||||
$route->matches('/hello/josh'); //<-- Extracts params from resource URI
|
||||
$route->dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Route does not match URI with wildcard
|
||||
* Test dispatch with middleware
|
||||
*/
|
||||
public function testRouteDoesNotMatchResourceWithWildcard()
|
||||
public function testDispatchWithMiddleware()
|
||||
{
|
||||
$resource = '/hello';
|
||||
$route = new \Slim\Route('/hello/:path+', function () {});
|
||||
$result = $route->matches($resource);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals(array(), $route->getParams());
|
||||
$this->expectOutputString('First! Second! Hello josh');
|
||||
$route = new \Slim\Route('/hello/:name', function ($name) { echo "Hello $name"; });
|
||||
$route->setMiddleware(function () {
|
||||
echo "First! ";
|
||||
});
|
||||
$route->setMiddleware(function () {
|
||||
echo "Second! ";
|
||||
});
|
||||
$route->matches('/hello/josh'); //<-- Extracts params from resource URI
|
||||
$route->dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test route sets and gets middleware
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Route instantiated
|
||||
*
|
||||
* Post-conditions:
|
||||
* Case A: Middleware set as callable, not array
|
||||
* Case B: Middleware set after other middleware already set
|
||||
* Case C: Middleware set as array of callables
|
||||
* Case D: Middleware set as a callable array
|
||||
* Case E: Middleware is invalid; throws InvalidArgumentException
|
||||
* Case F: Middleware is an array with one invalid callable; throws InvalidArgumentException
|
||||
* Test middleware with arguments
|
||||
*/
|
||||
public function testRouteMiddleware()
|
||||
public function testRouteMiddlwareArguments()
|
||||
{
|
||||
$callable1 = function () {};
|
||||
$callable2 = function () {};
|
||||
//Case A
|
||||
$r1 = new \Slim\Route('/foo', function () {});
|
||||
$r1->setMiddleware($callable1);
|
||||
$mw = $r1->getMiddleware();
|
||||
$this->assertInternalType('array', $mw);
|
||||
$this->assertEquals(1, count($mw));
|
||||
//Case B
|
||||
$r1->setMiddleware($callable2);
|
||||
$mw = $r1->getMiddleware();
|
||||
$this->assertEquals(2, count($mw));
|
||||
//Case C
|
||||
$r2 = new \Slim\Route('/foo', function () {});
|
||||
$r2->setMiddleware(array($callable1, $callable2));
|
||||
$mw = $r2->getMiddleware();
|
||||
$this->assertInternalType('array', $mw);
|
||||
$this->assertEquals(2, count($mw));
|
||||
//Case D
|
||||
$r3 = new \Slim\Route('/foo', function () {});
|
||||
$r3->setMiddleware(array($this, 'callableTestFunction'));
|
||||
$mw = $r3->getMiddleware();
|
||||
$this->assertInternalType('array', $mw);
|
||||
$this->assertEquals(1, count($mw));
|
||||
//Case E
|
||||
try {
|
||||
$r3->setMiddleware('sdjfsoi788');
|
||||
$this->fail('Did not catch InvalidArgumentException when setting invalid route middleware');
|
||||
} catch ( \InvalidArgumentException $e ) {}
|
||||
//Case F
|
||||
try {
|
||||
$r3->setMiddleware(array($callable1, $callable2, 'sdjfsoi788'));
|
||||
$this->fail('Did not catch InvalidArgumentException when setting an array with one invalid route middleware');
|
||||
} catch ( \InvalidArgumentException $e ) {}
|
||||
}
|
||||
|
||||
public function callableTestFunction() {}
|
||||
|
||||
/**
|
||||
* Test that a Route manages the HTTP methods that it supports
|
||||
*
|
||||
* Case A: Route initially supports no HTTP methods
|
||||
* Case B: Route can set its supported HTTP methods
|
||||
* Case C: Route can append supported HTTP methods
|
||||
* Case D: Route can test if it supports an HTTP method
|
||||
* Case E: Route can lazily declare supported HTTP methods with `via`
|
||||
*/
|
||||
public function testHttpMethods()
|
||||
{
|
||||
//Case A
|
||||
$r = new \Slim\Route('/foo', function () {});
|
||||
$this->assertEmpty($r->getHttpMethods());
|
||||
//Case B
|
||||
$r->setHttpMethods('GET');
|
||||
$this->assertEquals(array('GET'), $r->getHttpMethods());
|
||||
//Case C
|
||||
$r->appendHttpMethods('POST', 'PUT');
|
||||
$this->assertEquals(array('GET', 'POST', 'PUT'), $r->getHttpMethods());
|
||||
//Case D
|
||||
$this->assertTrue($r->supportsHttpMethod('GET'));
|
||||
$this->assertFalse($r->supportsHttpMethod('DELETE'));
|
||||
//Case E
|
||||
$viaResult = $r->via('DELETE');
|
||||
$this->assertTrue($viaResult instanceof \Slim\Route);
|
||||
$this->assertTrue($r->supportsHttpMethod('DELETE'));
|
||||
$this->expectOutputString('foobar');
|
||||
$route = new \Slim\Route('/foo', function () { echo "bar"; });
|
||||
$route->setName('foo');
|
||||
$route->setMiddleware(function ($route) {
|
||||
echo $route->getName();
|
||||
});
|
||||
$route->matches('/foo'); //<-- Extracts params from resource URI
|
||||
$route->dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
+160
-512
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -32,571 +32,219 @@
|
||||
|
||||
class RouterTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $env;
|
||||
protected $req;
|
||||
protected $res;
|
||||
|
||||
public function setUp()
|
||||
/**
|
||||
* Constructor should initialize routes as empty array
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$this->env = \Slim\Environment::getInstance();
|
||||
$this->req = new \Slim\Http\Request($this->env);
|
||||
$this->res = new \Slim\Http\Response();
|
||||
$router = new \Slim\Router();
|
||||
|
||||
$this->assertAttributeEquals(array(), 'routes', $router);
|
||||
}
|
||||
|
||||
/**
|
||||
* Router::urlFor should return a full route pattern
|
||||
* even if no params data is provided.
|
||||
* Map should set and return instance of \Slim\Route
|
||||
*/
|
||||
public function testUrlForNamedRouteWithoutParams()
|
||||
public function testMap()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
$route = $router->map('/foo/bar', function () {})->via('GET');
|
||||
$route = new \Slim\Route('/foo', function() {});
|
||||
$router->map($route);
|
||||
|
||||
$this->assertAttributeContains($route, 'routes', $router);
|
||||
}
|
||||
|
||||
/**
|
||||
* Named route should be added and indexed by name
|
||||
*/
|
||||
public function testAddNamedRoute()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$router->addNamedRoute('foo', $route);
|
||||
$this->assertEquals('/foo/bar', $router->urlFor('foo'));
|
||||
|
||||
$property = new \ReflectionProperty($router, 'namedRoutes');
|
||||
$property->setAccessible(true);
|
||||
|
||||
$rV = $property->getValue($router);
|
||||
$this->assertSame($route, $rV['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Router::urlFor should return a full route pattern if
|
||||
* param data is provided.
|
||||
* Named route should have unique name
|
||||
*/
|
||||
public function testUrlForNamedRouteWithParams()
|
||||
public function testAddNamedRouteWithDuplicateKey()
|
||||
{
|
||||
$this->setExpectedException('RuntimeException');
|
||||
|
||||
$router = new \Slim\Router();
|
||||
$route = $router->map('/foo/:one/and/:two', function ($one, $two) {})->via('GET');
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
$router->addNamedRoute('foo', $route);
|
||||
$router->addNamedRoute('foo', $route);
|
||||
$this->assertEquals('/foo/Josh/and/John', $router->urlFor('foo', array('one' => 'Josh', 'two' => 'John')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Router::urlFor should throw an exception if Route with name
|
||||
* does not exist.
|
||||
* @expectedException \RuntimeException
|
||||
* Router should return named route by name, or null if not found
|
||||
*/
|
||||
public function testUrlForNamedRouteThatDoesNotExist()
|
||||
public function testGetNamedRoute()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
$route = $router->map('/foo/bar', function () {})->via('GET');
|
||||
$router->addNamedRoute('bar', $route);
|
||||
$router->urlFor('foo');
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($router, 'namedRoutes');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($router, array('foo' => $route));
|
||||
|
||||
$this->assertSame($route, $router->getNamedRoute('foo'));
|
||||
$this->assertNull($router->getNamedRoute('bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Router::addNamedRoute should throw an exception if named Route
|
||||
* with same name already exists.
|
||||
* Router should determine named routes and cache results
|
||||
*/
|
||||
public function testNamedRouteWithExistingName()
|
||||
public function testGetNamedRoutes()
|
||||
{
|
||||
$this->setExpectedException('\RuntimeException');
|
||||
$router = new \Slim\Router();
|
||||
$route1 = $router->map('/foo/bar', function () {})->via('GET');
|
||||
$route2 = $router->map('/foo/bar/2', function () {})->via('GET');
|
||||
$router->addNamedRoute('bar', $route1);
|
||||
$router->addNamedRoute('bar', $route2);
|
||||
$route1 = new \Slim\Route('/foo', function () {});
|
||||
$route2 = new \Slim\Route('/bar', function () {});
|
||||
|
||||
// Init router routes to array
|
||||
$propertyRouterRoutes = new \ReflectionProperty($router, 'routes');
|
||||
$propertyRouterRoutes->setAccessible(true);
|
||||
$propertyRouterRoutes->setValue($router, array($route1, $route2));
|
||||
|
||||
// Init router named routes to null
|
||||
$propertyRouterNamedRoutes = new \ReflectionProperty($router, 'namedRoutes');
|
||||
$propertyRouterNamedRoutes->setAccessible(true);
|
||||
$propertyRouterNamedRoutes->setValue($router, null);
|
||||
|
||||
// Init route name
|
||||
$propertyRouteName = new \ReflectionProperty($route2, 'name');
|
||||
$propertyRouteName->setAccessible(true);
|
||||
$propertyRouteName->setValue($route2, 'bar');
|
||||
|
||||
$namedRoutes = $router->getNamedRoutes();
|
||||
$this->assertCount(1, $namedRoutes);
|
||||
$this->assertSame($route2, $namedRoutes['bar']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if named route exists
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Slim app instantiated;
|
||||
* Named route created;
|
||||
*
|
||||
* Post-conditions:
|
||||
* Named route found to exist;
|
||||
* Non-existant route found not to exist;
|
||||
* Router should detect presence of a named route by name
|
||||
*/
|
||||
public function testHasNamedRoute()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
$route = $router->map('/foo', function () {})->via('GET');
|
||||
$router->addNamedRoute('foo', $route);
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($router, 'namedRoutes');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($router, array('foo' => $route));
|
||||
|
||||
$this->assertTrue($router->hasNamedRoute('foo'));
|
||||
$this->assertFalse($router->hasNamedRoute('bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Router gets named route
|
||||
*
|
||||
* Pre-conditions;
|
||||
* Slim app instantiated;
|
||||
* Named route created;
|
||||
*
|
||||
* Post-conditions:
|
||||
* Named route fetched by named;
|
||||
* NULL is returned if named route does not exist;
|
||||
*/
|
||||
public function testGetNamedRoute()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
$route1 = $router->map('/foo', function () {})->via('GET');
|
||||
$router->addNamedRoute('foo', $route1);
|
||||
$this->assertSame($route1, $router->getNamedRoute('foo'));
|
||||
$this->assertNull($router->getNamedRoute('bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test external iterator for Router's named routes
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Slim app instantiated;
|
||||
* Named routes created;
|
||||
*
|
||||
* Post-conditions:
|
||||
* Array iterator returned for named routes;
|
||||
*/
|
||||
public function testGetNamedRoutes()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
$route1 = $router->map('/foo', function () {})->via('GET');
|
||||
$route2 = $router->map('/bar', function () {})->via('POST');
|
||||
$router->addNamedRoute('foo', $route1);
|
||||
$router->addNamedRoute('bar', $route2);
|
||||
$namedRoutesIterator = $router->getNamedRoutes();
|
||||
$this->assertInstanceOf('ArrayIterator', $namedRoutesIterator);
|
||||
$this->assertEquals(2, $namedRoutesIterator->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Router considers HEAD requests as GET requests
|
||||
*/
|
||||
public function testRouterConsidersHeadAsGet()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'HEAD',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$this->env = \Slim\Environment::getInstance();
|
||||
$this->req = new \Slim\Http\Request($this->env);
|
||||
$this->res = new \Slim\Http\Response();
|
||||
$router = new \Slim\Router();
|
||||
$route = $router->map('/bar', function () {})->via('GET', 'HEAD');
|
||||
$numberOfMatchingRoutes = count($router->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri()));
|
||||
$this->assertEquals(1, $numberOfMatchingRoutes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Router::urlFor
|
||||
*/
|
||||
public function testRouterUrlFor()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
$route1 = $router->map('/foo/bar', function () {})->via('GET');
|
||||
$route2 = $router->map('/foo/:one/:two', function () {})->via('GET');
|
||||
$route3 = $router->map('/foo/:one(/:two)', function () {})->via('GET');
|
||||
$route4 = $router->map('/foo/:one/(:two/)', function () {})->via('GET');
|
||||
$route5 = $router->map('/foo/:one/(:two/(:three/))', function () {})->via('GET');
|
||||
$route6 = $router->map('/foo/:path+/bar', function (){})->via('GET');
|
||||
$route7 = $router->map('/foo/:path+/:path2+/bar', function (){})->via('GET');
|
||||
$route8 = $router->map('/foo/:path+', function (){})->via('GET');
|
||||
$route9 = $router->map('/foo/:var/:var2', function (){})->via('GET');
|
||||
$route1->setName('route1');
|
||||
$route2->setName('route2');
|
||||
$route3->setName('route3');
|
||||
$route4->setName('route4');
|
||||
$route5->setName('route5');
|
||||
$route6->setName('route6');
|
||||
$route7->setName('route7');
|
||||
$route8->setName('route8');
|
||||
$route9->setName('route9');
|
||||
//Route
|
||||
$this->assertEquals('/foo/bar', $router->urlFor('route1'));
|
||||
//Route with params
|
||||
$this->assertEquals('/foo/foo/bar', $router->urlFor('route2', array('one' => 'foo', 'two' => 'bar')));
|
||||
$this->assertEquals('/foo/foo/:two', $router->urlFor('route2', array('one' => 'foo')));
|
||||
$this->assertEquals('/foo/:one/bar', $router->urlFor('route2', array('two' => 'bar')));
|
||||
//Route with params and optional segments
|
||||
$this->assertEquals('/foo/foo/bar', $router->urlFor('route3', array('one' => 'foo', 'two' => 'bar')));
|
||||
$this->assertEquals('/foo/foo', $router->urlFor('route3', array('one' => 'foo')));
|
||||
$this->assertEquals('/foo/:one/bar', $router->urlFor('route3', array('two' => 'bar')));
|
||||
$this->assertEquals('/foo/:one', $router->urlFor('route3'));
|
||||
//Route with params and optional segments
|
||||
$this->assertEquals('/foo/foo/bar/', $router->urlFor('route4', array('one' => 'foo', 'two' => 'bar')));
|
||||
$this->assertEquals('/foo/foo/', $router->urlFor('route4', array('one' => 'foo')));
|
||||
$this->assertEquals('/foo/:one/bar/', $router->urlFor('route4', array('two' => 'bar')));
|
||||
$this->assertEquals('/foo/:one/', $router->urlFor('route4'));
|
||||
//Route with params and optional segments
|
||||
$this->assertEquals('/foo/foo/bar/what/', $router->urlFor('route5', array('one' => 'foo', 'two' => 'bar', 'three' => 'what')));
|
||||
$this->assertEquals('/foo/foo/', $router->urlFor('route5', array('one' => 'foo')));
|
||||
$this->assertEquals('/foo/:one/bar/', $router->urlFor('route5', array('two' => 'bar')));
|
||||
$this->assertEquals('/foo/:one/bar/what/', $router->urlFor('route5', array('two' => 'bar', 'three' => 'what')));
|
||||
$this->assertEquals('/foo/:one/', $router->urlFor('route5'));
|
||||
//Route with wildcard params
|
||||
$this->assertEquals('/foo/bar/bar', $router->urlFor('route6', array('path'=>'bar')));
|
||||
$this->assertEquals('/foo/foo/bar/bar', $router->urlFor('route7', array('path'=>'foo', 'path2'=>'bar')));
|
||||
$this->assertEquals('/foo/bar', $router->urlFor('route8', array('path'=>'bar')));
|
||||
//Route with similar param names, test greedy matching
|
||||
$this->assertEquals('/foo/1/2', $router->urlFor('route9', array('var2'=>'2', 'var'=>'1')));
|
||||
$this->assertEquals('/foo/1/2', $router->urlFor('route9', array('var'=>'1', 'var2'=>'2')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that router returns no matches when neither HTTP method nor URI match.
|
||||
*/
|
||||
public function testRouterMatchesRoutesNone()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$this->env = \Slim\Environment::getInstance();
|
||||
$this->req = new \Slim\Http\Request($this->env);
|
||||
$this->res = new \Slim\Http\Response();
|
||||
$router = new \Slim\Router();
|
||||
$router->map('/bar', function () {})->via('POST');
|
||||
$router->map('/foo', function () {})->via('POST');
|
||||
$router->map('/foo', function () {})->via('PUT');
|
||||
$router->map('/foo/bar/xyz', function () {})->via('DELETE');
|
||||
$this->assertEquals(0, count($router->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that router returns no matches when HTTP method matches but URI does not.
|
||||
*/
|
||||
public function testRouterMatchesRoutesNoneWhenMethodMatchesUriDoesNot()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$this->env = \Slim\Environment::getInstance();
|
||||
$this->req = new \Slim\Http\Request($this->env);
|
||||
$this->res = new \Slim\Http\Response();
|
||||
$router = new \Slim\Router();
|
||||
$router->map('/fooNOMATCH', function () {})->via('GET');
|
||||
$router->map('/foo', function () {})->via('POST');
|
||||
$router->map('/foo', function () {})->via('PUT');
|
||||
$router->map('/foo/bar/xyz', function () {})->via('DELETE');
|
||||
$this->assertEquals(0, count($router->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that router returns no matches when HTTP method does not match but URI does.
|
||||
*/
|
||||
public function testRouterMatchesRoutesNoneWhenMethodDoesNotMatchUriMatches()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$this->env = \Slim\Environment::getInstance();
|
||||
$this->req = new \Slim\Http\Request($this->env);
|
||||
$this->res = new \Slim\Http\Response();
|
||||
$router = new \Slim\Router();
|
||||
$router->map('/foo', function () {})->via('OPTIONS');
|
||||
$router->map('/foo', function () {})->via('POST');
|
||||
$router->map('/foo', function () {})->via('PUT');
|
||||
$router->map('/foo/bar/xyz', function () {})->via('DELETE');
|
||||
$this->assertEquals(0, count($router->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that router returns matched routes based on HTTP method and URI.
|
||||
*/
|
||||
public function testRouterMatchesRoutes()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$this->env = \Slim\Environment::getInstance();
|
||||
$this->req = new \Slim\Http\Request($this->env);
|
||||
$this->res = new \Slim\Http\Response();
|
||||
$router = new \Slim\Router();
|
||||
$router->map('/foo', function () {})->via('GET');
|
||||
$router->map('/foo', function () {})->via('POST');
|
||||
$router->map('/foo', function () {})->via('PUT');
|
||||
$router->map('/foo/bar/xyz', function () {})->via('DELETE');
|
||||
$this->assertEquals(1, count($router->getMatchedRoutes($this->req->getMethod(), $this->req->getResourceUri())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get current route
|
||||
* Router should return current route if set during iteration
|
||||
*/
|
||||
public function testGetCurrentRoute()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo' //<-- Virtual
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
$route1 = $app->get('/bar', function () {
|
||||
echo "Bar";
|
||||
});
|
||||
$route2 = $app->get('/foo', function () {
|
||||
echo "Foo";
|
||||
});
|
||||
$app->call();
|
||||
$this->assertSame($route2, $app->router()->getCurrentRoute());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test calling get current route before routing doesn't cause errors
|
||||
*/
|
||||
public function testGetCurrentRouteBeforeRoutingDoesntError()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo' //<-- Virtual
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
$route1 = $app->get('/bar', function () {
|
||||
echo "Bar";
|
||||
});
|
||||
$route2 = $app->get('/foo', function () {
|
||||
echo "Foo";
|
||||
});
|
||||
|
||||
$app->router()->getCurrentRoute();
|
||||
|
||||
$app->call();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get current route before routing returns null
|
||||
*/
|
||||
public function testGetCurrentRouteBeforeRoutingReturnsNull()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo' //<-- Virtual
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
$route1 = $app->get('/bar', function () {
|
||||
echo "Bar";
|
||||
});
|
||||
$route2 = $app->get('/foo', function () {
|
||||
echo "Foo";
|
||||
});
|
||||
|
||||
$this->assertSame(null, $app->router()->getCurrentRoute());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get current route during slim.before.dispatch hook
|
||||
*/
|
||||
public function testGetCurrentRouteDuringBeforeDispatchHook()
|
||||
{
|
||||
$route = null;
|
||||
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo' //<-- Virtual
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
$app->hook('slim.before.dispatch', function() use(&$route, $app) {
|
||||
$route = $app->router()->getCurrentRoute();
|
||||
});
|
||||
$route1 = $app->get('/bar', function () {
|
||||
echo "Bar";
|
||||
});
|
||||
$route2 = $app->get('/foo', function () {
|
||||
echo "Foo";
|
||||
});
|
||||
|
||||
$app->call();
|
||||
$this->assertSame($route2, $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get current route during routing
|
||||
*/
|
||||
public function testGetCurrentRouteDuringRouting()
|
||||
{
|
||||
$route = null;
|
||||
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo' //<-- Virtual
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
$route1 = $app->get('/bar', function () {
|
||||
echo "Bar";
|
||||
});
|
||||
$route2 = $app->get('/foo', function () use (&$route, $app) {
|
||||
echo "Foo";
|
||||
$route = $app->router()->getCurrentRoute();
|
||||
});
|
||||
|
||||
$app->call();
|
||||
$this->assertSame($route2, $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get current route after routing
|
||||
*/
|
||||
public function testGetCurrentRouteAfterRouting()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo' //<-- Virtual
|
||||
));
|
||||
$app = new \Slim\Slim();
|
||||
$route1 = $app->get('/bar', function () {
|
||||
echo "Bar";
|
||||
});
|
||||
$route2 = $app->get('/foo', function () {
|
||||
echo "Foo";
|
||||
});
|
||||
$app->call();
|
||||
$this->assertSame($route2, $app->router()->getCurrentRoute());
|
||||
}
|
||||
|
||||
public function testDispatch()
|
||||
{
|
||||
$this->expectOutputString('Hello josh');
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/hello/josh', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$env = \Slim\Environment::getInstance();
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$router = new \Slim\Router();
|
||||
$route = new \Slim\Route('/hello/:name', function ($name) { echo "Hello $name"; });
|
||||
$route->matches($req->getResourceUri()); //<-- Extracts params from resource URI
|
||||
$router->dispatch($route);
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$property = new \ReflectionProperty($router, 'currentRoute');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($router, $route);
|
||||
|
||||
$this->assertSame($route, $router->getCurrentRoute());
|
||||
}
|
||||
|
||||
public function testDispatchWithMiddlware()
|
||||
/**
|
||||
* Router should return first matching route if current route not set yet by iteration
|
||||
*/
|
||||
public function testGetCurrentRouteIfMatchedRoutes()
|
||||
{
|
||||
$this->expectOutputString('First! Second! Hello josh');
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/hello/josh', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$env = \Slim\Environment::getInstance();
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$router = new \Slim\Router();
|
||||
$route = new \Slim\Route('/hello/:name', function ($name) { echo "Hello $name"; });
|
||||
$route->setMiddleware(function () {
|
||||
echo "First! ";
|
||||
});
|
||||
$route->setMiddleware(function () {
|
||||
echo "Second! ";
|
||||
});
|
||||
$route->matches($req->getResourceUri()); //<-- Extracts params from resource URI
|
||||
$router->dispatch($route);
|
||||
$route = new \Slim\Route('/foo', function () {});
|
||||
|
||||
$propertyMatchedRoutes = new \ReflectionProperty($router, 'matchedRoutes');
|
||||
$propertyMatchedRoutes->setAccessible(true);
|
||||
$propertyMatchedRoutes->setValue($router, array($route));
|
||||
|
||||
$propertyCurrentRoute = new \ReflectionProperty($router, 'currentRoute');
|
||||
$propertyCurrentRoute->setAccessible(true);
|
||||
$propertyCurrentRoute->setValue($router, null);
|
||||
|
||||
$this->assertSame($route, $router->getCurrentRoute());
|
||||
}
|
||||
|
||||
public function testRouteMiddlwareArguments()
|
||||
/**
|
||||
* Router should return `null` if current route not set yet and there are no matching routes
|
||||
*/
|
||||
public function testGetCurrentRouteIfNoMatchedRoutes()
|
||||
{
|
||||
$this->expectOutputString('foobar');
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/foo' //<-- Virtual
|
||||
));
|
||||
$env = \Slim\Environment::getInstance();
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$router = new \Slim\Router();
|
||||
$route = new \Slim\Route('/foo', function () { echo "bar"; });
|
||||
$route->setName('foo');
|
||||
$route->setMiddleware(function ($route) {
|
||||
echo $route->getName();
|
||||
});
|
||||
$route->matches($req->getResourceUri()); //<-- Extracts params from resource URI
|
||||
$router->dispatch($route);
|
||||
|
||||
$propertyMatchedRoutes = new \ReflectionProperty($router, 'matchedRoutes');
|
||||
$propertyMatchedRoutes->setAccessible(true);
|
||||
$propertyMatchedRoutes->setValue($router, array());
|
||||
|
||||
$propertyCurrentRoute = new \ReflectionProperty($router, 'currentRoute');
|
||||
$propertyCurrentRoute->setAccessible(true);
|
||||
$propertyCurrentRoute->setValue($router, null);
|
||||
|
||||
$this->assertNull($router->getCurrentRoute());
|
||||
}
|
||||
|
||||
public function testDispatchWithoutCallable()
|
||||
public function testGetMatchedRoutes()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'SCRIPT_NAME' => '', //<-- Physical
|
||||
'PATH_INFO' => '/hello/josh', //<-- Virtual
|
||||
'QUERY_STRING' => 'one=1&two=2&three=3',
|
||||
'SERVER_NAME' => 'slim',
|
||||
'SERVER_PORT' => 80,
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => fopen('php://stderr', 'w'),
|
||||
'HTTP_HOST' => 'slim'
|
||||
));
|
||||
$env = \Slim\Environment::getInstance();
|
||||
$req = new \Slim\Http\Request($env);
|
||||
$router = new \Slim\Router();
|
||||
$route = new \Slim\Route('/hello/:name', 'foo'); // <-- Fail fast
|
||||
|
||||
$route1 = new \Slim\Route('/foo', function () {});
|
||||
$route1 = $route1->via('GET');
|
||||
|
||||
$route2 = new \Slim\Route('/foo', function () {});
|
||||
$route2 = $route2->via('POST');
|
||||
|
||||
$route3 = new \Slim\Route('/bar', function () {});
|
||||
$route3 = $route3->via('PUT');
|
||||
|
||||
$routes = new \ReflectionProperty($router, 'routes');
|
||||
$routes->setAccessible(true);
|
||||
$routes->setValue($router, array($route1, $route2, $route3));
|
||||
|
||||
$matchedRoutes = $router->getMatchedRoutes('GET', '/foo');
|
||||
$this->assertSame($route1, $matchedRoutes[0]);
|
||||
}
|
||||
|
||||
// Test url for named route
|
||||
|
||||
public function testUrlFor()
|
||||
{
|
||||
$router = new \Slim\Router();
|
||||
|
||||
$route1 = new \Slim\Route('/hello/:first/:last', function () {});
|
||||
$route1 = $route1->via('GET')->name('hello');
|
||||
|
||||
$route2 = new \Slim\Route('/path/(:foo\.:bar)', function () {});
|
||||
$route2 = $route2->via('GET')->name('regexRoute');
|
||||
|
||||
$routes = new \ReflectionProperty($router, 'namedRoutes');
|
||||
$routes->setAccessible(true);
|
||||
$routes->setValue($router, array(
|
||||
'hello' => $route1,
|
||||
'regexRoute' => $route2
|
||||
));
|
||||
|
||||
$this->assertEquals('/hello/Josh/Lockhart', $router->urlFor('hello', array('first' => 'Josh', 'last' => 'Lockhart')));
|
||||
$this->assertEquals('/path/Hello.Josh', $router->urlFor('regexRoute', array('foo' => 'Hello', 'bar' => 'Josh')));
|
||||
}
|
||||
|
||||
public function testUrlForIfNoSuchRoute()
|
||||
{
|
||||
$this->setExpectedException('RuntimeException');
|
||||
|
||||
$router = new \Slim\Router();
|
||||
$router->urlFor('foo', array('abc' => '123'));
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+131
-85
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -33,7 +33,7 @@
|
||||
//Mock custom view
|
||||
class CustomView extends \Slim\View
|
||||
{
|
||||
public function render($template) { echo "Custom view"; }
|
||||
public function render($template, $data = null) { echo "Custom view"; }
|
||||
}
|
||||
|
||||
//Echo Logger
|
||||
@@ -371,6 +371,27 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertSame($callable, $route->getCallable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test PATCH route
|
||||
*/
|
||||
public function testPatchRoute()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'PATCH',
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$mw1 = function () { echo "foo"; };
|
||||
$mw2 = function () { echo "bar"; };
|
||||
$callable = function () { echo "xyz"; };
|
||||
$route = $s->patch('/bar', $mw1, $mw2, $callable);
|
||||
$s->call();
|
||||
$this->assertEquals('foobarxyz', $s->response()->body());
|
||||
$this->assertEquals('/bar', $route->getPattern());
|
||||
$this->assertSame($callable, $route->getCallable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DELETE route
|
||||
*/
|
||||
@@ -413,6 +434,51 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertSame($callable, $route->getCallable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test route groups
|
||||
*/
|
||||
public function testRouteGroups()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar/baz', //<-- Virtual'
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$mw1 = function () { echo "foo"; };
|
||||
$mw2 = function () { echo "bar"; };
|
||||
$callable = function () { echo "xyz"; };
|
||||
$s->group('/bar', $mw1, function () use ($s, $mw2, $callable) {
|
||||
$s->get('/baz', $mw2, $callable);
|
||||
});
|
||||
$s->call();
|
||||
$this->assertEquals('foobarxyz', $s->response()->body());
|
||||
}
|
||||
|
||||
/*
|
||||
* Test ANY route
|
||||
*/
|
||||
public function testAnyRoute()
|
||||
{
|
||||
$mw1 = function () { echo "foo"; };
|
||||
$mw2 = function () { echo "bar"; };
|
||||
$callable = function () { echo "xyz"; };
|
||||
$methods = array('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS');
|
||||
foreach ($methods as $i => $method) {
|
||||
\Slim\Environment::mock(array(
|
||||
'REQUEST_METHOD' => $method,
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$route = $s->any('/bar', $mw1, $mw2, $callable);
|
||||
$s->call();
|
||||
$this->assertEquals('foobarxyz', $s->response()->body());
|
||||
$this->assertEquals('/bar', $route->getPattern());
|
||||
$this->assertSame($callable, $route->getCallable());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if route does NOT expect trailing slash and URL has one
|
||||
*/
|
||||
@@ -485,6 +551,16 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
* RENDERING
|
||||
************************************************/
|
||||
|
||||
/**
|
||||
* Test template path is passed to view
|
||||
*/
|
||||
public function testViewGetsTemplatesPath()
|
||||
{
|
||||
$path = dirname(__FILE__) . '/templates';
|
||||
$s = new \Slim\Slim(array('templates.path' => $path));
|
||||
$this->assertEquals($s->view->getTemplatesDirectory(), $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test render with template and data
|
||||
*/
|
||||
@@ -545,7 +621,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
'IF_MODIFIED_SINCE' => 'Sun, 03 Oct 2010 17:00:52 -0400',
|
||||
'HTTP_IF_MODIFIED_SINCE' => 'Sun, 03 Oct 2010 21:00:52 GMT',
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$s->get('/bar', function () use ($s) {
|
||||
@@ -563,7 +639,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
'IF_MODIFIED_SINCE' => 'Sun, 03 Oct 2010 17:00:52 -0400',
|
||||
'IF_MODIFIED_SINCE' => 'Sun, 03 Oct 2010 21:00:52 GMT',
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$s->get('/bar', function () use ($s) {
|
||||
@@ -587,6 +663,25 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$s->call();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Last Modified header format
|
||||
*/
|
||||
public function testLastModifiedHeaderFormat()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$s->get('/bar', function () use ($s) {
|
||||
$s->lastModified(1286139652);
|
||||
});
|
||||
$s->call();
|
||||
list($status, $header, $body) = $s->response()->finalize();
|
||||
$this->assertTrue(isset($header['Last-Modified']));
|
||||
$this->assertEquals('Sun, 03 Oct 2010 21:00:52 GMT', $header['Last-Modified']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ETag matches
|
||||
*/
|
||||
@@ -595,7 +690,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
'IF_NONE_MATCH' => '"abc123"',
|
||||
'HTTP_IF_NONE_MATCH' => '"abc123"',
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$s->get('/bar', function () use ($s) {
|
||||
@@ -650,7 +745,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
));
|
||||
$expectedDate = gmdate('D, d M Y', strtotime('5 days')); //Just the day, month, and year
|
||||
$expectedDate = gmdate('D, d M Y H:i:s T', strtotime('5 days'));
|
||||
$s = new \Slim\Slim();
|
||||
$s->get('/bar', function () use ($s) {
|
||||
$s->expires('5 days');
|
||||
@@ -658,7 +753,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$s->call();
|
||||
list($status, $header, $body) = $s->response()->finalize();
|
||||
$this->assertTrue(isset($header['Expires']));
|
||||
$this->assertEquals(0, strpos($header['Expires'], $expectedDate));
|
||||
$this->assertEquals($header['Expires'], $expectedDate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -671,7 +766,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
));
|
||||
$fiveDaysFromNow = time() + (60 * 60 * 24 * 5);
|
||||
$expectedDate = gmdate('D, d M Y', $fiveDaysFromNow); //Just the day, month, and year
|
||||
$expectedDate = gmdate('D, d M Y H:i:s T', $fiveDaysFromNow);
|
||||
$s = new \Slim\Slim();
|
||||
$s->get('/bar', function () use ($s, $fiveDaysFromNow) {
|
||||
$s->expires($fiveDaysFromNow);
|
||||
@@ -679,7 +774,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$s->call();
|
||||
list($status, $header, $body) = $s->response()->finalize();
|
||||
$this->assertTrue(isset($header['Expires']));
|
||||
$this->assertEquals(0, strpos($header['Expires'], $expectedDate));
|
||||
$this->assertEquals($header['Expires'], $expectedDate);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
@@ -706,11 +801,11 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$s->setCookie('foo1', 'bar1', '2 days');
|
||||
});
|
||||
$s->call();
|
||||
list($status, $header, $body) = $s->response()->finalize();
|
||||
$cookies = explode("\n", $header['Set-Cookie']);
|
||||
$this->assertEquals(2, count($cookies));
|
||||
$this->assertEquals(1, preg_match('@foo=bar@', $cookies[0]));
|
||||
$this->assertEquals(1, preg_match('@foo1=bar1@', $cookies[1]));
|
||||
$cookie1 = $s->response->cookies->get('foo');
|
||||
$cookie2 = $s->response->cookies->get('foo1');
|
||||
$this->assertEquals(2, count($s->response->cookies));
|
||||
$this->assertEquals('bar', $cookie1['value']);
|
||||
$this->assertEquals('bar1', $cookie2['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -730,7 +825,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
'QUERY_STRING' => 'one=foo&two=bar',
|
||||
'SERVER_NAME' => 'slimframework.com',
|
||||
'SERVER_PORT' => 80,
|
||||
'COOKIE' => 'foo=bar; foo2=bar2',
|
||||
'HTTP_COOKIE' => 'foo=bar; foo2=bar2',
|
||||
'slim.url_scheme' => 'http',
|
||||
'slim.input' => '',
|
||||
'slim.errors' => @fopen('php://stderr', 'w')
|
||||
@@ -773,60 +868,10 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$s->deleteCookie('foo');
|
||||
});
|
||||
$s->call();
|
||||
list($status, $header, $body) = $s->response()->finalize();
|
||||
$cookies = explode("\n", $header['Set-Cookie']);
|
||||
$this->assertEquals(1, count($cookies));
|
||||
$this->assertEquals(1, preg_match('@^foo=;@', $cookies[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set encrypted cookie
|
||||
*
|
||||
* This method ensures that the `Set-Cookie:` HTTP request
|
||||
* header is set. The implementation is tested in a separate file.
|
||||
*/
|
||||
public function testSetEncryptedCookie()
|
||||
{
|
||||
$s = new \Slim\Slim();
|
||||
$s->setEncryptedCookie('foo', 'bar');
|
||||
$r = $s->response();
|
||||
$this->assertEquals(1, preg_match("@^foo=.+%7C.+%7C.+@", $r['Set-Cookie'])); //<-- %7C is a url-encoded pipe
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get encrypted cookie
|
||||
*
|
||||
* This only tests that this method runs without error. The implementation of
|
||||
* fetching the encrypted cookie is tested separately.
|
||||
*/
|
||||
public function testGetEncryptedCookieAndDeletingIt()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$r = $s->response();
|
||||
$this->assertFalse($s->getEncryptedCookie('foo'));
|
||||
$this->assertEquals(1, preg_match("@foo=;.*@", $r['Set-Cookie']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get encrypted cookie WITHOUT deleting it
|
||||
*
|
||||
* This only tests that this method runs without error. The implementation of
|
||||
* fetching the encrypted cookie is tested separately.
|
||||
*/
|
||||
public function testGetEncryptedCookieWithoutDeletingIt()
|
||||
{
|
||||
\Slim\Environment::mock(array(
|
||||
'SCRIPT_NAME' => '/foo', //<-- Physical
|
||||
'PATH_INFO' => '/bar', //<-- Virtual
|
||||
));
|
||||
$s = new \Slim\Slim();
|
||||
$r = $s->response();
|
||||
$this->assertFalse($s->getEncryptedCookie('foo', false));
|
||||
$this->assertEquals(0, preg_match("@foo=;.*@", $r['Set-Cookie']));
|
||||
$cookie = $s->response->cookies->get('foo');
|
||||
$this->assertEquals(1, count($s->response->cookies));
|
||||
$this->assertEquals('', $cookie['value']);
|
||||
$this->assertLessThan(time(), $cookie['expires']);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
@@ -1195,7 +1240,9 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testSlimError()
|
||||
{
|
||||
$s = new \Slim\Slim();
|
||||
$s = new \Slim\Slim(array(
|
||||
"log.enabled" => false
|
||||
));
|
||||
$s->get('/bar', function () use ($s) {
|
||||
$s->error();
|
||||
});
|
||||
@@ -1215,13 +1262,13 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
public function testDefaultHandlerLogsTheErrorWhenDebugIsFalse()
|
||||
{
|
||||
$s = new \Slim\Slim(array('debug' => false));
|
||||
$s->container->singleton('log', function ($c) {
|
||||
return new EchoErrorLogger();
|
||||
});
|
||||
$s->get('/bar', function () use ($s) {
|
||||
throw new \InvalidArgumentException('my specific error message');
|
||||
});
|
||||
|
||||
$env = $s->environment();
|
||||
$env['slim.log'] = new EchoErrorLogger(); // <-- inject the fake logger
|
||||
|
||||
ob_start();
|
||||
$s->run();
|
||||
$output = ob_get_clean();
|
||||
@@ -1276,7 +1323,8 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
public function testErrorWithMultipleApps()
|
||||
{
|
||||
$s1 = new \Slim\Slim(array(
|
||||
'debug' => false
|
||||
'debug' => false,
|
||||
'log.enabled' => false
|
||||
));
|
||||
$s2 = new \Slim\Slim();
|
||||
$s1->get('/bar', function () use ($s1) {
|
||||
@@ -1323,22 +1371,20 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$defaultErrorReporting = error_reporting();
|
||||
|
||||
// Assert Slim ignores E_NOTICE errors
|
||||
// Test 1
|
||||
error_reporting(E_ALL ^ E_NOTICE); // <-- Report all errors EXCEPT notices
|
||||
try {
|
||||
$this->assertTrue(\Slim\Slim::handleErrors(E_NOTICE, 'test error', 'Slim.php', 119));
|
||||
\Slim\Slim::handleErrors(E_NOTICE, 'test error', 'Slim.php', 119);
|
||||
} catch (\ErrorException $e) {
|
||||
$this->fail('Slim::handleErrors reported a disabled error level.');
|
||||
}
|
||||
|
||||
// Assert Slim reports E_STRICT errors
|
||||
// Test 2
|
||||
error_reporting(E_ALL | E_STRICT); // <-- Report all errors, including E_STRICT
|
||||
try {
|
||||
\Slim\Slim::handleErrors(E_STRICT, 'test error', 'Slim.php', 119);
|
||||
$this->fail('Slim::handleErrors didn\'t report a enabled error level');
|
||||
} catch (\ErrorException $e) {
|
||||
$this->assertEquals('test error', $e->getMessage());
|
||||
}
|
||||
} catch (\ErrorException $e) {}
|
||||
|
||||
error_reporting($defaultErrorReporting);
|
||||
}
|
||||
@@ -1357,8 +1403,8 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
* Slim should throw a Slim_Exception_Stop if error callback is not callable
|
||||
*/
|
||||
public function testErrorHandlerIfNotCallable() {
|
||||
$this->setExpectedException('\Slim\Exception\Stop');
|
||||
$s = new \Slim\Slim();
|
||||
$this->setExpectedException('\Slim\Exception\Stop');
|
||||
$s = new \Slim\Slim(array("log.enabled" => false));
|
||||
$errCallback = 'foo';
|
||||
$s->error($errCallback);
|
||||
}
|
||||
@@ -1377,7 +1423,7 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
* Slim should throw a Slim_Exception_Stop if NotFound callback is not callable
|
||||
*/
|
||||
public function testNotFoundHandlerIfNotCallable() {
|
||||
$this->setExpectedException('\Slim\Exception\Stop');
|
||||
$this->setExpectedException('\Slim\Exception\Stop');
|
||||
$s = new \Slim\Slim();
|
||||
$notFoundCallback = 'foo';
|
||||
$s->notFound($notFoundCallback);
|
||||
@@ -1473,13 +1519,13 @@ class SlimTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(array(array()), $app->getHooks('test.hook.one'));
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Test late static binding
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Slim app is extended by Derived class and instantiated;
|
||||
* Derived class overrides the 'getDefaultSettings' function and adds an extra default config value
|
||||
* Test that the new config value exists
|
||||
* Test that the new config value exists
|
||||
*
|
||||
* Post-conditions:
|
||||
* Config value exists and is equal to expected value
|
||||
|
||||
Vendored
+132
-129
@@ -6,7 +6,7 @@
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.2.0
|
||||
* @version 2.4.0
|
||||
*
|
||||
* MIT LICENSE
|
||||
*
|
||||
@@ -32,164 +32,167 @@
|
||||
|
||||
class ViewTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
public function testGetDataAll()
|
||||
{
|
||||
$this->view = new \Slim\View();
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$prop->setValue($view, new \Slim\Helper\Set(array('foo' => 'bar')));
|
||||
|
||||
$this->assertSame(array('foo' => 'bar'), $view->getData());
|
||||
}
|
||||
|
||||
public function generateTestData()
|
||||
public function testGetDataKeyExists()
|
||||
{
|
||||
return array('a' => 1, 'b' => 2, 'c' => 3);
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$prop->setValue($view, new \Slim\Helper\Set(array('foo' => 'bar')));
|
||||
|
||||
$this->assertEquals('bar', $view->getData('foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test initial View data is an empty array
|
||||
*
|
||||
* Pre-conditions:
|
||||
* None
|
||||
*
|
||||
* Post-conditions:
|
||||
* The View object's data attribute is an empty array
|
||||
*/
|
||||
public function testViewIsConstructedWithDataArray()
|
||||
public function testGetDataKeyNotExists()
|
||||
{
|
||||
$this->assertEquals(array(), $this->view->getData());
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$prop->setValue($view, new \Slim\Helper\Set(array('foo' => 'bar')));
|
||||
|
||||
$this->assertNull($view->getData('abc'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test View sets and gets data
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Case A: Set view data key/value
|
||||
* Case B: Set view data as array
|
||||
* Case C: Set view data with one argument that is not an array
|
||||
*
|
||||
* Post-conditions:
|
||||
* Case A: Data key/value are set
|
||||
* Case B: Data is set to array
|
||||
* Case C: An InvalidArgumentException is thrown
|
||||
*/
|
||||
public function testViewSetAndGetData()
|
||||
public function testSetDataKeyValue()
|
||||
{
|
||||
//Case A
|
||||
$this->view->setData('one', 1);
|
||||
$this->assertEquals(1, $this->view->getData('one'));
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$view->setData('foo', 'bar');
|
||||
|
||||
//Case B
|
||||
$data = array('foo' => 'bar', 'a' => 'A');
|
||||
$this->view->setData($data);
|
||||
$this->assertSame($data, $this->view->getData());
|
||||
|
||||
//Case C
|
||||
try {
|
||||
$this->view->setData('foo');
|
||||
$this->fail('Setting View data with non-array single argument did not throw exception');
|
||||
} catch ( \InvalidArgumentException $e ) {}
|
||||
$this->assertEquals(array('foo' => 'bar'), $prop->getValue($view)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test View appends data
|
||||
*
|
||||
* Pre-conditions:
|
||||
* Case A: Append data to View several times
|
||||
* Case B: Append view data which is not an array
|
||||
*
|
||||
* Post-conditions:
|
||||
* Case A: The View data contains all appended data
|
||||
* Case B: An InvalidArgumentException is thrown
|
||||
*/
|
||||
public function testViewAppendsData()
|
||||
public function testSetDataKeyValueAsClosure()
|
||||
{
|
||||
//Case A
|
||||
$this->view->appendData(array('a' => 'A'));
|
||||
$this->view->appendData(array('b' => 'B'));
|
||||
$this->assertEquals(array('a' => 'A', 'b' => 'B'), $this->view->getData());
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
|
||||
//Case B
|
||||
try {
|
||||
$this->view->appendData('not an array');
|
||||
$this->fail('Appending View data with non-array argument did not throw exception');
|
||||
} catch ( \InvalidArgumentException $e ) {}
|
||||
$view->setData('fooClosure', function () {
|
||||
return 'foo';
|
||||
});
|
||||
|
||||
$value = $prop->getValue($view)->get('fooClosure');
|
||||
$this->assertInstanceOf('Closure', $value);
|
||||
$this->assertEquals('foo', $value());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test View templates directory
|
||||
*
|
||||
* Pre-conditions:
|
||||
* View templates directory is set to an existing directory
|
||||
*
|
||||
* Post-conditions:
|
||||
* The templates directory is set correctly.
|
||||
*/
|
||||
public function testSetsTemplatesDirectory()
|
||||
public function testSetDataArray()
|
||||
{
|
||||
$templatesDirectory = dirname(__FILE__) . '/templates';
|
||||
$this->view->setTemplatesDirectory($templatesDirectory);
|
||||
$this->assertEquals($templatesDirectory, $this->view->getTemplatesDirectory());
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$view->setData(array('foo' => 'bar'));
|
||||
|
||||
$this->assertEquals(array('foo' => 'bar'), $prop->getValue($view)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test View templates directory may have a trailing slash when set
|
||||
*
|
||||
* Pre-conditions:
|
||||
* View templates directory is set to an existing directory with a trailing slash
|
||||
*
|
||||
* Post-conditions:
|
||||
* The View templates directory is set correctly without a trailing slash
|
||||
*/
|
||||
public function testTemplatesDirectoryWithTrailingSlash()
|
||||
public function testSetDataInvalidArgument()
|
||||
{
|
||||
$this->view->setTemplatesDirectory(dirname(__FILE__) . '/templates/');
|
||||
$this->assertEquals(dirname(__FILE__) . '/templates', $this->view->getTemplatesDirectory());
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$view = new \Slim\View();
|
||||
$view->setData('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test View renders template
|
||||
*
|
||||
* Pre-conditions:
|
||||
* View templates directory is set to an existing directory.
|
||||
* View data is set without errors
|
||||
* Case A: View renders an existing template
|
||||
* Case B: View renders a non-existing template
|
||||
*
|
||||
* Post-conditions:
|
||||
* Case A: The rendered template is returned as a string
|
||||
* Case B: A RuntimeException is thrown
|
||||
*/
|
||||
public function testRendersTemplateWithData()
|
||||
public function testAppendData()
|
||||
{
|
||||
$this->view->setTemplatesDirectory(dirname(__FILE__) . '/templates');
|
||||
$this->view->setData(array('foo' => 'bar'));
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$view->appendData(array('foo' => 'bar'));
|
||||
|
||||
//Case A
|
||||
$output = $this->view->render('test.php');
|
||||
$this->assertEquals('test output bar', $output);
|
||||
|
||||
//Case B
|
||||
try {
|
||||
$output = $this->view->render('foo.php');
|
||||
$this->fail('Rendering non-existent template did not throw exception');
|
||||
} catch ( \RuntimeException $e ) {}
|
||||
$this->assertEquals(array('foo' => 'bar'), $prop->getValue($view)->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test View displays template
|
||||
*
|
||||
* Pre-conditions:
|
||||
* View templates directory is set to an existing directory.
|
||||
* View data is set without errors
|
||||
* View is displayed
|
||||
*
|
||||
* Post-conditions:
|
||||
* The output buffer contains the rendered template
|
||||
*/
|
||||
public function testDisplaysTemplateWithData()
|
||||
public function testLocalData()
|
||||
{
|
||||
$view = new \Slim\View();
|
||||
$prop1 = new \ReflectionProperty($view, 'data');
|
||||
$prop1->setAccessible(true);
|
||||
$prop1->setValue($view, new \Slim\Helper\Set(array('foo' => 'bar')));
|
||||
|
||||
$prop2 = new \ReflectionProperty($view, 'templatesDirectory');
|
||||
$prop2->setAccessible(true);
|
||||
$prop2->setValue($view, dirname(__FILE__) . '/templates');
|
||||
|
||||
$output = $view->fetch('test.php', array('foo' => 'baz'));
|
||||
$this->assertEquals('test output baz', $output);
|
||||
}
|
||||
|
||||
public function testAppendDataOverwrite()
|
||||
{
|
||||
$view = new \Slim\View();
|
||||
$prop = new \ReflectionProperty($view, 'data');
|
||||
$prop->setAccessible(true);
|
||||
$prop->setValue($view, new \Slim\Helper\Set(array('foo' => 'bar')));
|
||||
$view->appendData(array('foo' => '123'));
|
||||
|
||||
$this->assertEquals(array('foo' => '123'), $prop->getValue($view)->all());
|
||||
}
|
||||
|
||||
public function testAppendDataInvalidArgument()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$view = new \Slim\View();
|
||||
$view->appendData('foo');
|
||||
}
|
||||
|
||||
public function testGetTemplatesDirectory()
|
||||
{
|
||||
$view = new \Slim\View();
|
||||
$property = new \ReflectionProperty($view, 'templatesDirectory');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($view, 'templates');
|
||||
|
||||
$this->assertEquals('templates', $view->getTemplatesDirectory());
|
||||
}
|
||||
|
||||
public function testSetTemplatesDirectory()
|
||||
{
|
||||
$view = new \Slim\View();
|
||||
$view->setTemplatesDirectory('templates/'); // <-- Should strip trailing slash
|
||||
|
||||
$this->assertAttributeEquals('templates', 'templatesDirectory', $view);
|
||||
}
|
||||
|
||||
public function testDisplay()
|
||||
{
|
||||
$this->expectOutputString('test output bar');
|
||||
$this->view->setTemplatesDirectory(dirname(__FILE__) . '/templates');
|
||||
$this->view->setData(array('foo' => 'bar'));
|
||||
$this->view->display('test.php');
|
||||
|
||||
$view = new \Slim\View();
|
||||
$prop1 = new \ReflectionProperty($view, 'data');
|
||||
$prop1->setAccessible(true);
|
||||
$prop1->setValue($view, new \Slim\Helper\Set(array('foo' => 'bar')));
|
||||
|
||||
$prop2 = new \ReflectionProperty($view, 'templatesDirectory');
|
||||
$prop2->setAccessible(true);
|
||||
$prop2->setValue($view, dirname(__FILE__) . '/templates');
|
||||
|
||||
$view->display('test.php');
|
||||
}
|
||||
|
||||
public function testDisplayTemplateThatDoesNotExist()
|
||||
{
|
||||
$this->setExpectedException('\RuntimeException');
|
||||
|
||||
$view = new \Slim\View();
|
||||
|
||||
$prop2 = new \ReflectionProperty($view, 'templatesDirectory');
|
||||
$prop2->setAccessible(true);
|
||||
$prop2->setValue($view, dirname(__FILE__) . '/templates');
|
||||
|
||||
$view->display('foo.php');
|
||||
}
|
||||
}
|
||||
|
||||
+107
-145
@@ -19,6 +19,8 @@ use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputAwareInterface;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
@@ -54,16 +56,17 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
*/
|
||||
class Application
|
||||
{
|
||||
private $commands;
|
||||
private $commands = array();
|
||||
private $wantHelps = false;
|
||||
private $runningCommand;
|
||||
private $name;
|
||||
private $version;
|
||||
private $catchExceptions;
|
||||
private $autoExit;
|
||||
private $catchExceptions = true;
|
||||
private $autoExit = true;
|
||||
private $definition;
|
||||
private $helperSet;
|
||||
private $dispatcher;
|
||||
private $terminalDimensions;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -77,9 +80,6 @@ class Application
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->version = $version;
|
||||
$this->catchExceptions = true;
|
||||
$this->autoExit = true;
|
||||
$this->commands = array();
|
||||
$this->helperSet = $this->getDefaultHelperSet();
|
||||
$this->definition = $this->getDefaultInputDefinition();
|
||||
|
||||
@@ -404,6 +404,10 @@ class Application
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $command->getDefinition()) {
|
||||
throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
|
||||
}
|
||||
|
||||
$this->commands[$command->getName()] = $command;
|
||||
|
||||
foreach ($command->getAliases() as $alias) {
|
||||
@@ -491,51 +495,31 @@ class Application
|
||||
public function findNamespace($namespace)
|
||||
{
|
||||
$allNamespaces = $this->getNamespaces();
|
||||
$found = '';
|
||||
foreach (explode(':', $namespace) as $i => $part) {
|
||||
// select sub-namespaces matching the current namespace we found
|
||||
$namespaces = array();
|
||||
foreach ($allNamespaces as $n) {
|
||||
if ('' === $found || 0 === strpos($n, $found)) {
|
||||
$namespaces[$n] = explode(':', $n);
|
||||
}
|
||||
}
|
||||
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
|
||||
$namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
|
||||
|
||||
$abbrevs = static::getAbbreviations(array_unique(array_values(array_filter(array_map(function ($p) use ($i) { return isset($p[$i]) ? $p[$i] : ''; }, $namespaces)))));
|
||||
if (empty($namespaces)) {
|
||||
$message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
|
||||
|
||||
if (!isset($abbrevs[$part])) {
|
||||
$message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
|
||||
|
||||
if (1 <= $i) {
|
||||
$part = $found.':'.$part;
|
||||
if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) {
|
||||
if (1 == count($alternatives)) {
|
||||
$message .= "\n\nDid you mean this?\n ";
|
||||
} else {
|
||||
$message .= "\n\nDid you mean one of these?\n ";
|
||||
}
|
||||
|
||||
if ($alternatives = $this->findAlternativeNamespace($part, $abbrevs)) {
|
||||
if (1 == count($alternatives)) {
|
||||
$message .= "\n\nDid you mean this?\n ";
|
||||
} else {
|
||||
$message .= "\n\nDid you mean one of these?\n ";
|
||||
}
|
||||
|
||||
$message .= implode("\n ", $alternatives);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException($message);
|
||||
$message .= implode("\n ", $alternatives);
|
||||
}
|
||||
|
||||
// there are multiple matches, but $part is an exact match of one of them so we select it
|
||||
if (in_array($part, $abbrevs[$part])) {
|
||||
$abbrevs[$part] = array($part);
|
||||
}
|
||||
|
||||
if (count($abbrevs[$part]) > 1) {
|
||||
throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$part])));
|
||||
}
|
||||
|
||||
$found .= $found ? ':' . $abbrevs[$part][0] : $abbrevs[$part][0];
|
||||
throw new \InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
return $found;
|
||||
$exact = in_array($namespace, $namespaces, true);
|
||||
if (count($namespaces) > 1 && !$exact) {
|
||||
throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
|
||||
}
|
||||
|
||||
return $exact ? $namespace : reset($namespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -554,58 +538,19 @@ class Application
|
||||
*/
|
||||
public function find($name)
|
||||
{
|
||||
// namespace
|
||||
$namespace = '';
|
||||
$searchName = $name;
|
||||
if (false !== $pos = strrpos($name, ':')) {
|
||||
$namespace = $this->findNamespace(substr($name, 0, $pos));
|
||||
$searchName = $namespace.substr($name, $pos);
|
||||
}
|
||||
$allCommands = array_keys($this->commands);
|
||||
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
|
||||
$commands = preg_grep('{^'.$expr.'}', $allCommands);
|
||||
|
||||
// name
|
||||
$commands = array();
|
||||
foreach ($this->commands as $command) {
|
||||
$extractedNamespace = $this->extractNamespace($command->getName());
|
||||
if ($extractedNamespace === $namespace
|
||||
|| !empty($namespace) && 0 === strpos($extractedNamespace, $namespace)
|
||||
) {
|
||||
$commands[] = $command->getName();
|
||||
if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
|
||||
if (false !== $pos = strrpos($name, ':')) {
|
||||
// check if a namespace exists and contains commands
|
||||
$this->findNamespace(substr($name, 0, $pos));
|
||||
}
|
||||
}
|
||||
|
||||
$abbrevs = static::getAbbreviations(array_unique($commands));
|
||||
if (isset($abbrevs[$searchName]) && 1 == count($abbrevs[$searchName])) {
|
||||
return $this->get($abbrevs[$searchName][0]);
|
||||
}
|
||||
|
||||
if (isset($abbrevs[$searchName]) && in_array($searchName, $abbrevs[$searchName])) {
|
||||
return $this->get($searchName);
|
||||
}
|
||||
|
||||
if (isset($abbrevs[$searchName]) && count($abbrevs[$searchName]) > 1) {
|
||||
$suggestions = $this->getAbbreviationSuggestions($abbrevs[$searchName]);
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
|
||||
}
|
||||
|
||||
// aliases
|
||||
$aliases = array();
|
||||
foreach ($this->commands as $command) {
|
||||
foreach ($command->getAliases() as $alias) {
|
||||
$extractedNamespace = $this->extractNamespace($alias);
|
||||
if ($extractedNamespace === $namespace
|
||||
|| !empty($namespace) && 0 === strpos($extractedNamespace, $namespace)
|
||||
) {
|
||||
$aliases[] = $alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aliases = static::getAbbreviations(array_unique($aliases));
|
||||
if (!isset($aliases[$searchName])) {
|
||||
$message = sprintf('Command "%s" is not defined.', $name);
|
||||
|
||||
if ($alternatives = $this->findAlternativeCommands($searchName, $abbrevs)) {
|
||||
if ($alternatives = $this->findAlternatives($name, $allCommands, array())) {
|
||||
if (1 == count($alternatives)) {
|
||||
$message .= "\n\nDid you mean this?\n ";
|
||||
} else {
|
||||
@@ -617,11 +562,14 @@ class Application
|
||||
throw new \InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
if (count($aliases[$searchName]) > 1) {
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $this->getAbbreviationSuggestions($aliases[$searchName])));
|
||||
$exact = in_array($name, $commands, true);
|
||||
if (count($commands) > 1 && !$exact) {
|
||||
$suggestions = $this->getAbbreviationSuggestions(array_values($commands));
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
|
||||
}
|
||||
|
||||
return $this->get($aliases[$searchName][0]);
|
||||
return $this->get($exact ? $name : reset($commands));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -684,8 +632,10 @@ class Application
|
||||
public function asText($namespace = null, $raw = false)
|
||||
{
|
||||
$descriptor = new TextDescriptor();
|
||||
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
|
||||
$descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
|
||||
|
||||
return $descriptor->describe($this, array('namespace' => $namespace, 'raw_text' => $raw));
|
||||
return $output->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -702,7 +652,14 @@ class Application
|
||||
{
|
||||
$descriptor = new XmlDescriptor();
|
||||
|
||||
return $descriptor->describe($this, array('namespace' => $namespace, 'as_dom' => $asDom));
|
||||
if ($asDom) {
|
||||
return $descriptor->getApplicationDocument($this, $namespace);
|
||||
}
|
||||
|
||||
$output = new BufferedOutput();
|
||||
$descriptor->describe($output, $this, array('namespace' => $namespace));
|
||||
|
||||
return $output->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -818,6 +775,10 @@ class Application
|
||||
*/
|
||||
public function getTerminalDimensions()
|
||||
{
|
||||
if ($this->terminalDimensions) {
|
||||
return $this->terminalDimensions;
|
||||
}
|
||||
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
// extract [w, H] from "wxh (WxH)"
|
||||
if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
|
||||
@@ -843,6 +804,23 @@ class Application
|
||||
return array(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets terminal dimensions.
|
||||
*
|
||||
* Can be useful to force terminal dimensions for functional tests.
|
||||
*
|
||||
* @param integer $width The width
|
||||
* @param integer $height The height
|
||||
*
|
||||
* @return Application The current application
|
||||
*/
|
||||
public function setTerminalDimensions($width, $height)
|
||||
{
|
||||
$this->terminalDimensions = array($width, $height);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the input and output instances based on the user arguments and options.
|
||||
*
|
||||
@@ -893,6 +871,12 @@ class Application
|
||||
*/
|
||||
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
foreach ($command->getHelperSet() as $helper) {
|
||||
if ($helper instanceof InputAwareInterface) {
|
||||
$helper->setInput($input);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $this->dispatcher) {
|
||||
return $command->run($input, $output);
|
||||
}
|
||||
@@ -1054,72 +1038,50 @@ class Application
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds alternative commands of $name
|
||||
*
|
||||
* @param string $name The full name of the command
|
||||
* @param array $abbrevs The abbreviations
|
||||
*
|
||||
* @return array A sorted array of similar commands
|
||||
*/
|
||||
private function findAlternativeCommands($name, $abbrevs)
|
||||
{
|
||||
$callback = function($item) {
|
||||
return $item->getName();
|
||||
};
|
||||
|
||||
return $this->findAlternatives($name, $this->commands, $abbrevs, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds alternative namespace of $name
|
||||
*
|
||||
* @param string $name The full name of the namespace
|
||||
* @param array $abbrevs The abbreviations
|
||||
*
|
||||
* @return array A sorted array of similar namespace
|
||||
*/
|
||||
private function findAlternativeNamespace($name, $abbrevs)
|
||||
{
|
||||
return $this->findAlternatives($name, $this->getNamespaces(), $abbrevs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds alternative of $name among $collection,
|
||||
* if nothing is found in $collection, try in $abbrevs
|
||||
* Finds alternative of $name among $collection
|
||||
*
|
||||
* @param string $name The string
|
||||
* @param array|Traversable $collection The collection
|
||||
* @param array $abbrevs The abbreviations
|
||||
* @param Closure|string|array $callback The callable to transform collection item before comparison
|
||||
*
|
||||
* @return array A sorted array of similar string
|
||||
*/
|
||||
private function findAlternatives($name, $collection, $abbrevs, $callback = null)
|
||||
private function findAlternatives($name, $collection)
|
||||
{
|
||||
$threshold = 1e3;
|
||||
$alternatives = array();
|
||||
|
||||
$collectionParts = array();
|
||||
foreach ($collection as $item) {
|
||||
if (null !== $callback) {
|
||||
$item = call_user_func($callback, $item);
|
||||
}
|
||||
|
||||
$lev = levenshtein($name, $item);
|
||||
if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
|
||||
$alternatives[$item] = $lev;
|
||||
}
|
||||
$collectionParts[$item] = explode(':', $item);
|
||||
}
|
||||
|
||||
if (!$alternatives) {
|
||||
foreach ($abbrevs as $key => $values) {
|
||||
$lev = levenshtein($name, $key);
|
||||
if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) {
|
||||
foreach ($values as $value) {
|
||||
$alternatives[$value] = $lev;
|
||||
}
|
||||
foreach (explode(':', $name) as $i => $subname) {
|
||||
foreach ($collectionParts as $collectionName => $parts) {
|
||||
$exists = isset($alternatives[$collectionName]);
|
||||
if (!isset($parts[$i]) && $exists) {
|
||||
$alternatives[$collectionName] += $threshold;
|
||||
continue;
|
||||
} elseif (!isset($parts[$i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lev = levenshtein($subname, $parts[$i]);
|
||||
if ($lev <= strlen($subname) / 3 || false !== strpos($parts[$i], $subname)) {
|
||||
$alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
|
||||
} elseif ($exists) {
|
||||
$alternatives[$collectionName] += $threshold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($collection as $item) {
|
||||
$lev = levenshtein($name, $item);
|
||||
if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
|
||||
$alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
|
||||
}
|
||||
}
|
||||
|
||||
$alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; });
|
||||
asort($alternatives);
|
||||
|
||||
return array_keys($alternatives);
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.4.0
|
||||
-----
|
||||
|
||||
* added a way to force terminal dimensions
|
||||
* added a convenient method to detect verbosity level
|
||||
* [BC BREAK] made descriptors use output instead of returning a string
|
||||
|
||||
2.3.0
|
||||
-----
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
@@ -32,13 +33,13 @@ class Command
|
||||
{
|
||||
private $application;
|
||||
private $name;
|
||||
private $aliases;
|
||||
private $aliases = array();
|
||||
private $definition;
|
||||
private $help;
|
||||
private $description;
|
||||
private $ignoreValidationErrors;
|
||||
private $applicationDefinitionMerged;
|
||||
private $applicationDefinitionMergedWithArgs;
|
||||
private $ignoreValidationErrors = false;
|
||||
private $applicationDefinitionMerged = false;
|
||||
private $applicationDefinitionMergedWithArgs = false;
|
||||
private $code;
|
||||
private $synopsis;
|
||||
private $helperSet;
|
||||
@@ -46,7 +47,7 @@ class Command
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the command
|
||||
* @param string|null $name The name of the command; passing null means it must be set in configure()
|
||||
*
|
||||
* @throws \LogicException When the command name is empty
|
||||
*
|
||||
@@ -55,10 +56,6 @@ class Command
|
||||
public function __construct($name = null)
|
||||
{
|
||||
$this->definition = new InputDefinition();
|
||||
$this->ignoreValidationErrors = false;
|
||||
$this->applicationDefinitionMerged = false;
|
||||
$this->applicationDefinitionMergedWithArgs = false;
|
||||
$this->aliases = array();
|
||||
|
||||
if (null !== $name) {
|
||||
$this->setName($name);
|
||||
@@ -401,7 +398,7 @@ class Command
|
||||
*
|
||||
* @return Command The current instance
|
||||
*
|
||||
* @throws \InvalidArgumentException When command name given is empty
|
||||
* @throws \InvalidArgumentException When the name is invalid
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
@@ -511,6 +508,8 @@ class Command
|
||||
*
|
||||
* @return Command The current instance
|
||||
*
|
||||
* @throws \InvalidArgumentException When an alias is invalid
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setAliases($aliases)
|
||||
@@ -576,8 +575,10 @@ class Command
|
||||
public function asText()
|
||||
{
|
||||
$descriptor = new TextDescriptor();
|
||||
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
|
||||
$descriptor->describe($output, $this, array('raw_output' => true));
|
||||
|
||||
return $descriptor->describe($this);
|
||||
return $output->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -593,12 +594,28 @@ class Command
|
||||
{
|
||||
$descriptor = new XmlDescriptor();
|
||||
|
||||
return $descriptor->describe($this, array('as_dom' => $asDom));
|
||||
if ($asDom) {
|
||||
return $descriptor->getCommandDocument($this);
|
||||
}
|
||||
|
||||
$output = new BufferedOutput();
|
||||
$descriptor->describe($output, $this);
|
||||
|
||||
return $output->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a command name.
|
||||
*
|
||||
* It must be non-empty and parts can optionally be separated by ":".
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @throws \InvalidArgumentException When the name is invalid
|
||||
*/
|
||||
private function validateName($name)
|
||||
{
|
||||
if (!preg_match('/^[^\:]+(\:[^\:]+)*$/', $name)) {
|
||||
if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
|
||||
throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class HelpCommand extends Command
|
||||
->setDefinition(array(
|
||||
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
|
||||
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
|
||||
))
|
||||
->setDescription('Displays help for a command')
|
||||
@@ -81,7 +81,11 @@ EOF
|
||||
}
|
||||
|
||||
$helper = new DescriptorHelper();
|
||||
$helper->describe($output, $this->command, $input->getOption('format'), $input->getOption('raw'));
|
||||
$helper->describe($output, $this->command, array(
|
||||
'format' => $input->getOption('format'),
|
||||
'raw' => $input->getOption('raw'),
|
||||
));
|
||||
|
||||
$this->command = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,11 @@ EOF
|
||||
}
|
||||
|
||||
$helper = new DescriptorHelper();
|
||||
$helper->describe($output, $this->getApplication(), $input->getOption('format'), $input->getOption('raw'), $input->getArgument('namespace'));
|
||||
$helper->describe($output, $this->getApplication(), array(
|
||||
'format' => $input->getOption('format'),
|
||||
'raw_text' => $input->getOption('raw'),
|
||||
'namespace' => $input->getArgument('namespace'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +89,7 @@ EOF
|
||||
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
|
||||
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
+34
-7
@@ -16,28 +16,55 @@ use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
abstract class Descriptor implements DescriptorInterface
|
||||
{
|
||||
public function describe($object, array $options = array())
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function describe(OutputInterface $output, $object, array $options = array())
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
switch (true) {
|
||||
case $object instanceof InputArgument:
|
||||
return $this->describeInputArgument($object, $options);
|
||||
$this->describeInputArgument($object, $options);
|
||||
break;
|
||||
case $object instanceof InputOption:
|
||||
return $this->describeInputOption($object, $options);
|
||||
$this->describeInputOption($object, $options);
|
||||
break;
|
||||
case $object instanceof InputDefinition:
|
||||
return $this->describeInputDefinition($object, $options);
|
||||
$this->describeInputDefinition($object, $options);
|
||||
break;
|
||||
case $object instanceof Command:
|
||||
return $this->describeCommand($object, $options);
|
||||
$this->describeCommand($object, $options);
|
||||
break;
|
||||
case $object instanceof Application:
|
||||
return $this->describeApplication($object, $options);
|
||||
$this->describeApplication($object, $options);
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
|
||||
}
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
|
||||
/**
|
||||
* Writes content to output.
|
||||
*
|
||||
* @param string $content
|
||||
* @param boolean $decorated
|
||||
*/
|
||||
protected function write($content, $decorated = false)
|
||||
{
|
||||
$this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-5
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Descriptor interface.
|
||||
*
|
||||
@@ -21,10 +23,9 @@ interface DescriptorInterface
|
||||
/**
|
||||
* Describes an InputArgument instance.
|
||||
*
|
||||
* @param object $object
|
||||
* @param array $options
|
||||
*
|
||||
* @return string|mixed
|
||||
* @param OutputInterface $output
|
||||
* @param object $object
|
||||
* @param array $options
|
||||
*/
|
||||
public function describe($object, array $options = array());
|
||||
public function describe(OutputInterface $output, $object, array $options = array());
|
||||
}
|
||||
|
||||
+81
-45
@@ -29,13 +29,7 @@ class JsonDescriptor extends Descriptor
|
||||
*/
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = array())
|
||||
{
|
||||
return $this->output(array(
|
||||
'name' => $argument->getName(),
|
||||
'is_required' => $argument->isRequired(),
|
||||
'is_array' => $argument->isArray(),
|
||||
'description' => $argument->getDescription(),
|
||||
'default' => $argument->getDefault(),
|
||||
), $options);
|
||||
$this->writeData($this->getInputArgumentData($argument), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,15 +37,7 @@ class JsonDescriptor extends Descriptor
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
{
|
||||
return $this->output(array(
|
||||
'name' => '--'.$option->getName(),
|
||||
'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
|
||||
'accept_value' => $option->acceptValue(),
|
||||
'is_value_required' => $option->isValueRequired(),
|
||||
'is_multiple' => $option->isArray(),
|
||||
'description' => $option->getDescription(),
|
||||
'default' => $option->getDefault(),
|
||||
), $options);
|
||||
$this->writeData($this->getInputOptionData($option), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,17 +45,7 @@ class JsonDescriptor extends Descriptor
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
{
|
||||
$inputArguments = array();
|
||||
foreach ($definition->getArguments() as $name => $argument) {
|
||||
$inputArguments[$name] = $this->describeInputArgument($argument, array('as_array' => true));
|
||||
}
|
||||
|
||||
$inputOptions = array();
|
||||
foreach ($definition->getOptions() as $name => $option) {
|
||||
$inputOptions[$name] = $this->describeInputOption($option, array('as_array' => true));
|
||||
}
|
||||
|
||||
return $this->output(array('arguments' => $inputArguments, 'options' => $inputOptions), $options);
|
||||
$this->writeData($this->getInputDefinitionData($definition), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,17 +53,7 @@ class JsonDescriptor extends Descriptor
|
||||
*/
|
||||
protected function describeCommand(Command $command, array $options = array())
|
||||
{
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
return $this->output(array(
|
||||
'name' => $command->getName(),
|
||||
'usage' => $command->getSynopsis(),
|
||||
'description' => $command->getDescription(),
|
||||
'help' => $command->getProcessedHelp(),
|
||||
'aliases' => $command->getAliases(),
|
||||
'definition' => $this->describeInputDefinition($command->getNativeDefinition(), array('as_array' => true)),
|
||||
), $options);
|
||||
$this->writeData($this->getCommandData($command), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,30 +66,100 @@ class JsonDescriptor extends Descriptor
|
||||
$commands = array();
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$commands[] = $this->describeCommand($command, array('as_array' => true));
|
||||
$commands[] = $this->getCommandData($command);
|
||||
}
|
||||
|
||||
$data = $describedNamespace
|
||||
? array('commands' => $commands, 'namespace' => $describedNamespace)
|
||||
: array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
|
||||
|
||||
return $this->output($data, $options);
|
||||
$this->writeData($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs data as array or string according to options.
|
||||
* Writes data as json.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $options
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function output(array $data, array $options)
|
||||
private function writeData(array $data, array $options)
|
||||
{
|
||||
if (isset($options['as_array']) && $options['as_array']) {
|
||||
return $data;
|
||||
$this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputArgument $argument
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getInputArgumentData(InputArgument $argument)
|
||||
{
|
||||
return array(
|
||||
'name' => $argument->getName(),
|
||||
'is_required' => $argument->isRequired(),
|
||||
'is_array' => $argument->isArray(),
|
||||
'description' => $argument->getDescription(),
|
||||
'default' => $argument->getDefault(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputOption $option
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getInputOptionData(InputOption $option)
|
||||
{
|
||||
return array(
|
||||
'name' => '--'.$option->getName(),
|
||||
'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
|
||||
'accept_value' => $option->acceptValue(),
|
||||
'is_value_required' => $option->isValueRequired(),
|
||||
'is_multiple' => $option->isArray(),
|
||||
'description' => $option->getDescription(),
|
||||
'default' => $option->getDefault(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputDefinition $definition
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getInputDefinitionData(InputDefinition $definition)
|
||||
{
|
||||
$inputArguments = array();
|
||||
foreach ($definition->getArguments() as $name => $argument) {
|
||||
$inputArguments[$name] = $this->getInputArgumentData($argument);
|
||||
}
|
||||
|
||||
return json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0);
|
||||
$inputOptions = array();
|
||||
foreach ($definition->getOptions() as $name => $option) {
|
||||
$inputOptions[$name] = $this->getInputOptionData($option);
|
||||
}
|
||||
|
||||
return array('arguments' => $inputArguments, 'options' => $inputOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $command
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getCommandData(Command $command)
|
||||
{
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
return array(
|
||||
'name' => $command->getName(),
|
||||
'usage' => $command->getSynopsis(),
|
||||
'description' => $command->getDescription(),
|
||||
'help' => $command->getProcessedHelp(),
|
||||
'aliases' => $command->getAliases(),
|
||||
'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+37
-27
@@ -29,12 +29,14 @@ class MarkdownDescriptor extends Descriptor
|
||||
*/
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = array())
|
||||
{
|
||||
return '**'.$argument->getName().':**'."\n\n"
|
||||
$this->write(
|
||||
'**'.$argument->getName().':**'."\n\n"
|
||||
.'* Name: '.($argument->getName() ?: '<none>')."\n"
|
||||
.'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
|
||||
.'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
|
||||
.'* Description: '.($argument->getDescription() ?: '<none>')."\n"
|
||||
.'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`';
|
||||
.'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,14 +44,16 @@ class MarkdownDescriptor extends Descriptor
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
{
|
||||
return '**'.$option->getName().':**'."\n\n"
|
||||
$this->write(
|
||||
'**'.$option->getName().':**'."\n\n"
|
||||
.'* Name: `--'.$option->getName().'`'."\n"
|
||||
.'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
|
||||
.'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
|
||||
.'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
|
||||
.'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
|
||||
.'* Description: '.($option->getDescription() ?: '<none>')."\n"
|
||||
.'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`';
|
||||
.'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,23 +61,25 @@ class MarkdownDescriptor extends Descriptor
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
{
|
||||
$blocks = array();
|
||||
|
||||
if (count($definition->getArguments()) > 0) {
|
||||
$blocks[] = '### Arguments:';
|
||||
if ($showArguments = count($definition->getArguments()) > 0) {
|
||||
$this->write('### Arguments:');
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$blocks[] = $this->describeInputArgument($argument);
|
||||
$this->write("\n\n");
|
||||
$this->write($this->describeInputArgument($argument));
|
||||
}
|
||||
}
|
||||
|
||||
if (count($definition->getOptions()) > 0) {
|
||||
$blocks[] = '### Options:';
|
||||
if ($showArguments) {
|
||||
$this->write("\n\n");
|
||||
}
|
||||
|
||||
$this->write('### Options:');
|
||||
foreach ($definition->getOptions() as $option) {
|
||||
$blocks[] = $this->describeInputOption($option);
|
||||
$this->write("\n\n");
|
||||
$this->write($this->describeInputOption($option));
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n\n", $blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,21 +90,23 @@ class MarkdownDescriptor extends Descriptor
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$markdown = $command->getName()."\n"
|
||||
$this->write(
|
||||
$command->getName()."\n"
|
||||
.str_repeat('-', strlen($command->getName()))."\n\n"
|
||||
.'* Description: '.($command->getDescription() ?: '<none>')."\n"
|
||||
.'* Usage: `'.$command->getSynopsis().'`'."\n"
|
||||
.'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '<none>');
|
||||
.'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '<none>')
|
||||
);
|
||||
|
||||
if ($help = $command->getProcessedHelp()) {
|
||||
$markdown .= "\n\n".$help;
|
||||
$this->write("\n\n");
|
||||
$this->write($help);
|
||||
}
|
||||
|
||||
if ($definitionMarkdown = $this->describeInputDefinition($command->getNativeDefinition())) {
|
||||
$markdown .= "\n\n".$definitionMarkdown;
|
||||
if ($definition = $command->getNativeDefinition()) {
|
||||
$this->write("\n\n");
|
||||
$this->describeInputDefinition($command->getNativeDefinition());
|
||||
}
|
||||
|
||||
return $markdown;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,22 +116,24 @@ class MarkdownDescriptor extends Descriptor
|
||||
{
|
||||
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
|
||||
$description = new ApplicationDescription($application, $describedNamespace);
|
||||
$blocks = array($application->getName()."\n".str_repeat('=', strlen($application->getName())));
|
||||
|
||||
$this->write($application->getName()."\n".str_repeat('=', strlen($application->getName())));
|
||||
|
||||
foreach ($description->getNamespaces() as $namespace) {
|
||||
if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
|
||||
$blocks[] = '**'.$namespace['id'].':**';
|
||||
$this->write("\n\n");
|
||||
$this->write('**'.$namespace['id'].':**');
|
||||
}
|
||||
|
||||
$blocks[] = implode("\n", array_map(function ($commandName) {
|
||||
$this->write("\n\n");
|
||||
$this->write(implode("\n", array_map(function ($commandName) {
|
||||
return '* '.$commandName;
|
||||
} , $namespace['commands']));
|
||||
} , $namespace['commands'])));
|
||||
}
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$blocks[] = $this->describeCommand($command);
|
||||
$this->write("\n\n");
|
||||
$this->write($this->describeCommand($command));
|
||||
}
|
||||
|
||||
return implode("\n\n", $blocks);
|
||||
}
|
||||
}
|
||||
|
||||
+59
-40
@@ -36,10 +36,12 @@ class TextDescriptor extends Descriptor
|
||||
}
|
||||
|
||||
$nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName());
|
||||
$output = str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription());
|
||||
$output = sprintf(" <info>%-${nameWidth}s</info> %s%s", $argument->getName(), $output, $default);
|
||||
|
||||
return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
|
||||
$this->writeText(sprintf(" <info>%-${nameWidth}s</info> %s%s",
|
||||
$argument->getName(),
|
||||
str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()),
|
||||
$default
|
||||
), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,15 +58,13 @@ class TextDescriptor extends Descriptor
|
||||
$nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName());
|
||||
$nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2;
|
||||
|
||||
$output = sprintf(" <info>%s</info> %-${nameWithShortcutWidth}s%s%s%s",
|
||||
$this->writeText(sprintf(" <info>%s</info> %-${nameWithShortcutWidth}s%s%s%s",
|
||||
'--'.$option->getName(),
|
||||
$option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
|
||||
str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()),
|
||||
$default,
|
||||
$option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
|
||||
);
|
||||
|
||||
return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
|
||||
), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,27 +85,27 @@ class TextDescriptor extends Descriptor
|
||||
}
|
||||
++$nameWidth;
|
||||
|
||||
$messages = array();
|
||||
|
||||
if ($definition->getArguments()) {
|
||||
$messages[] = '<comment>Arguments:</comment>';
|
||||
$this->writeText('<comment>Arguments:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$messages[] = $this->describeInputArgument($argument, array('name_width' => $nameWidth));
|
||||
$this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth)));
|
||||
$this->writeText("\n");
|
||||
}
|
||||
$messages[] = '';
|
||||
}
|
||||
|
||||
if ($definition->getArguments() && $definition->getOptions()) {
|
||||
$this->writeText("\n");
|
||||
}
|
||||
|
||||
if ($definition->getOptions()) {
|
||||
$messages[] = '<comment>Options:</comment>';
|
||||
$this->writeText('<comment>Options:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
foreach ($definition->getOptions() as $option) {
|
||||
$messages[] = $this->describeInputOption($option, array('name_width' => $nameWidth));
|
||||
$this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth)));
|
||||
$this->writeText("\n");
|
||||
}
|
||||
$messages[] = '';
|
||||
}
|
||||
|
||||
$output = implode("\n", $messages);
|
||||
|
||||
return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,22 +115,30 @@ class TextDescriptor extends Descriptor
|
||||
{
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
$messages = array('<comment>Usage:</comment>', ' '.$command->getSynopsis(), '');
|
||||
|
||||
if ($command->getAliases()) {
|
||||
$messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $command->getAliases()).'</info>';
|
||||
$this->writeText('<comment>Usage:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
$this->writeText(' '.$command->getSynopsis(), $options);
|
||||
$this->writeText("\n");
|
||||
|
||||
if (count($command->getAliases()) > 0) {
|
||||
$this->writeText("\n");
|
||||
$this->writeText('<comment>Aliases:</comment> <info>'.implode(', ', $command->getAliases()).'</info>', $options);
|
||||
}
|
||||
|
||||
$messages[] = $this->describeInputDefinition($command->getNativeDefinition());
|
||||
if ($definition = $command->getNativeDefinition()) {
|
||||
$this->writeText("\n");
|
||||
$this->describeInputDefinition($definition, $options);
|
||||
}
|
||||
|
||||
$this->writeText("\n");
|
||||
|
||||
if ($help = $command->getProcessedHelp()) {
|
||||
$messages[] = '<comment>Help:</comment>';
|
||||
$messages[] = ' '.str_replace("\n", "\n ", $help)."\n";
|
||||
$this->writeText('<comment>Help:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
$this->writeText(' '.str_replace("\n", "\n ", $help), $options);
|
||||
$this->writeText("\n");
|
||||
}
|
||||
|
||||
$output = implode("\n", $messages);
|
||||
|
||||
return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,41 +148,52 @@ class TextDescriptor extends Descriptor
|
||||
{
|
||||
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
|
||||
$description = new ApplicationDescription($application, $describedNamespace);
|
||||
$messages = array();
|
||||
|
||||
if (isset($options['raw_text']) && $options['raw_text']) {
|
||||
$width = $this->getColumnWidth($description->getCommands());
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$messages[] = sprintf("%-${width}s %s", $command->getName(), $command->getDescription());
|
||||
$this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
|
||||
$this->writeText("\n");
|
||||
}
|
||||
} else {
|
||||
$width = $this->getColumnWidth($description->getCommands());
|
||||
|
||||
$messages[] = $application->getHelp();
|
||||
$messages[] = '';
|
||||
$this->writeText($application->getHelp(), $options);
|
||||
$this->writeText("\n\n");
|
||||
|
||||
if ($describedNamespace) {
|
||||
$messages[] = sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $describedNamespace);
|
||||
$this->writeText(sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $describedNamespace), $options);
|
||||
} else {
|
||||
$messages[] = '<comment>Available commands:</comment>';
|
||||
$this->writeText('<comment>Available commands:</comment>', $options);
|
||||
}
|
||||
|
||||
// add commands by namespace
|
||||
foreach ($description->getNamespaces() as $namespace) {
|
||||
if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
|
||||
$messages[] = '<comment>'.$namespace['id'].'</comment>';
|
||||
$this->writeText("\n");
|
||||
$this->writeText('<comment>'.$namespace['id'].'</comment>', $options);
|
||||
}
|
||||
|
||||
foreach ($namespace['commands'] as $name) {
|
||||
$messages[] = sprintf(" <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription());
|
||||
$this->writeText("\n");
|
||||
$this->writeText(sprintf(" <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription()), $options);
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeText("\n");
|
||||
}
|
||||
}
|
||||
|
||||
$output = implode("\n", $messages);
|
||||
|
||||
return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private function writeText($content, array $options = array())
|
||||
{
|
||||
$this->write(
|
||||
isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
|
||||
isset($options['raw_output']) ? !$options['raw_output'] : true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+181
-129
@@ -24,10 +24,185 @@ use Symfony\Component\Console\Input\InputOption;
|
||||
*/
|
||||
class XmlDescriptor extends Descriptor
|
||||
{
|
||||
/**
|
||||
* @param InputDefinition $definition
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function getInputDefinitionDocument(InputDefinition $definition)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($definitionXML = $dom->createElement('definition'));
|
||||
|
||||
$definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
|
||||
}
|
||||
|
||||
$definitionXML->appendChild($optionsXML = $dom->createElement('options'));
|
||||
foreach ($definition->getOptions() as $option) {
|
||||
$this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $command
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function getCommandDocument(Command $command)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($commandXML = $dom->createElement('command'));
|
||||
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$commandXML->setAttribute('id', $command->getName());
|
||||
$commandXML->setAttribute('name', $command->getName());
|
||||
|
||||
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
|
||||
$usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), '')));
|
||||
|
||||
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
|
||||
$descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
|
||||
|
||||
$commandXML->appendChild($helpXML = $dom->createElement('help'));
|
||||
$helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
|
||||
|
||||
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
|
||||
foreach ($command->getAliases() as $alias) {
|
||||
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
|
||||
$aliasXML->appendChild($dom->createTextNode($alias));
|
||||
}
|
||||
|
||||
$definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
|
||||
$this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $application
|
||||
* @param string|null $namespace
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function getApplicationDocument(Application $application, $namespace = null)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($rootXml = $dom->createElement('symfony'));
|
||||
|
||||
if ($application->getName() !== 'UNKNOWN') {
|
||||
$rootXml->setAttribute('name', $application->getName());
|
||||
if ($application->getVersion() !== 'UNKNOWN') {
|
||||
$rootXml->setAttribute('version', $application->getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
$rootXml->appendChild($commandsXML = $dom->createElement('commands'));
|
||||
|
||||
$description = new ApplicationDescription($application, $namespace);
|
||||
|
||||
if ($namespace) {
|
||||
$commandsXML->setAttribute('namespace', $namespace);
|
||||
}
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$this->appendDocument($commandsXML, $this->getCommandDocument($command));
|
||||
}
|
||||
|
||||
if (!$namespace) {
|
||||
$rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
|
||||
|
||||
foreach ($description->getNamespaces() as $namespaceDescription) {
|
||||
$namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
|
||||
$namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
|
||||
|
||||
foreach ($namespaceDescription['commands'] as $name) {
|
||||
$namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
|
||||
$commandXML->appendChild($dom->createTextNode($name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputArgument(InputArgument $argument, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getInputArgumentDocument($argument));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getInputOptionDocument($option));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getInputDefinitionDocument($definition));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeCommand(Command $command, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getCommandDocument($command));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeApplication(Application $application, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends document children to parent node.
|
||||
*
|
||||
* @param \DOMNode $parentNode
|
||||
* @param \DOMNode $importedParent
|
||||
*/
|
||||
private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
|
||||
{
|
||||
foreach ($importedParent->childNodes as $childNode) {
|
||||
$parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes DOM document.
|
||||
*
|
||||
* @param \DOMDocument $dom
|
||||
*
|
||||
* @return \DOMDocument|string
|
||||
*/
|
||||
private function writeDocument(\DOMDocument $dom)
|
||||
{
|
||||
$dom->formatOutput = true;
|
||||
$this->write($dom->saveXML());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputArgument $argument
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getInputArgumentDocument(InputArgument $argument)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
@@ -45,13 +220,15 @@ class XmlDescriptor extends Descriptor
|
||||
$defaultXML->appendChild($dom->createTextNode($default));
|
||||
}
|
||||
|
||||
return $this->output($dom, $options);
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @param InputOption $option
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
protected function describeInputOption(InputOption $option, array $options = array())
|
||||
private function getInputOptionDocument(InputOption $option)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
@@ -82,131 +259,6 @@ class XmlDescriptor extends Descriptor
|
||||
}
|
||||
}
|
||||
|
||||
return $this->output($dom, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeInputDefinition(InputDefinition $definition, array $options = array())
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($definitionXML = $dom->createElement('definition'));
|
||||
|
||||
$definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$this->appendDocument($argumentsXML, $this->describeInputArgument($argument, array('as_dom' => true)));
|
||||
}
|
||||
|
||||
$definitionXML->appendChild($optionsXML = $dom->createElement('options'));
|
||||
foreach ($definition->getOptions() as $option) {
|
||||
$this->appendDocument($optionsXML, $this->describeInputOption($option, array('as_dom' => true)));
|
||||
}
|
||||
|
||||
return $this->output($dom, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeCommand(Command $command, array $options = array())
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($commandXML = $dom->createElement('command'));
|
||||
|
||||
$command->getSynopsis();
|
||||
$command->mergeApplicationDefinition(false);
|
||||
|
||||
$commandXML->setAttribute('id', $command->getName());
|
||||
$commandXML->setAttribute('name', $command->getName());
|
||||
|
||||
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
|
||||
$usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), '')));
|
||||
|
||||
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
|
||||
$descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
|
||||
|
||||
$commandXML->appendChild($helpXML = $dom->createElement('help'));
|
||||
$helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
|
||||
|
||||
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
|
||||
foreach ($command->getAliases() as $alias) {
|
||||
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
|
||||
$aliasXML->appendChild($dom->createTextNode($alias));
|
||||
}
|
||||
|
||||
$definitionXML = $this->describeInputDefinition($command->getNativeDefinition(), array('as_dom' => true));
|
||||
$this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
|
||||
|
||||
return $this->output($dom, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeApplication(Application $application, array $options = array())
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($rootXml = $dom->createElement('symfony'));
|
||||
$rootXml->appendChild($commandsXML = $dom->createElement('commands'));
|
||||
|
||||
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
|
||||
$description = new ApplicationDescription($application, $describedNamespace);
|
||||
|
||||
if ($describedNamespace) {
|
||||
$commandsXML->setAttribute('namespace', $describedNamespace);
|
||||
}
|
||||
|
||||
foreach ($description->getCommands() as $command) {
|
||||
$this->appendDocument($commandsXML, $this->describeCommand($command, array('as_dom' => true)));
|
||||
}
|
||||
|
||||
if (!$describedNamespace) {
|
||||
$rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
|
||||
|
||||
foreach ($description->getNamespaces() as $namespace) {
|
||||
$namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
|
||||
$namespaceArrayXML->setAttribute('id', $namespace['id']);
|
||||
|
||||
foreach ($namespace['commands'] as $name) {
|
||||
$namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
|
||||
$commandXML->appendChild($dom->createTextNode($name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->output($dom, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends document children to parent node.
|
||||
*
|
||||
* @param \DOMNode $parentNode
|
||||
* @param \DOMNode $importedParent
|
||||
*/
|
||||
private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
|
||||
{
|
||||
foreach ($importedParent->childNodes as $childNode) {
|
||||
$parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs document as DOMDocument or string according to options.
|
||||
*
|
||||
* @param \DOMDocument $dom
|
||||
* @param array $options
|
||||
*
|
||||
* @return \DOMDocument|string
|
||||
*/
|
||||
private function output(\DOMDocument $dom, array $options)
|
||||
{
|
||||
if (isset($options['as_dom']) && $options['as_dom']) {
|
||||
return $dom;
|
||||
}
|
||||
|
||||
$dom->formatOutput = true;
|
||||
|
||||
return $dom->saveXML();
|
||||
return $dom;
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -11,8 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\Console\Event;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/**
|
||||
* Allows to do things before the command is executed.
|
||||
*
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ class ConsoleExceptionEvent extends ConsoleEvent
|
||||
parent::__construct($command, $input, $output);
|
||||
|
||||
$this->setException($exception);
|
||||
$this->exitCode = $exitCode;
|
||||
$this->exitCode = (int) $exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ class ConsoleTerminateEvent extends ConsoleEvent
|
||||
*/
|
||||
public function setExitCode($exitCode)
|
||||
{
|
||||
$this->exitCode = $exitCode;
|
||||
$this->exitCode = (int) $exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-7
@@ -46,23 +46,29 @@ class DescriptorHelper extends Helper
|
||||
/**
|
||||
* Describes an object if supported.
|
||||
*
|
||||
* Available options are:
|
||||
* * format: string, the output format name
|
||||
* * raw_text: boolean, sets output type as raw
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param object $object
|
||||
* @param string $format
|
||||
* @param boolean $raw
|
||||
* @param array $options
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function describe(OutputInterface $output, $object, $format = null, $raw = false, $namespace = null)
|
||||
public function describe(OutputInterface $output, $object, array $options = array())
|
||||
{
|
||||
$options = array('raw_text' => $raw, 'format' => $format ?: 'txt', 'namespace' => $namespace);
|
||||
$type = !$raw && 'txt' === $options['format'] ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW;
|
||||
$options = array_merge(array(
|
||||
'raw_text' => false,
|
||||
'format' => 'txt',
|
||||
), $options);
|
||||
|
||||
if (!isset($this->descriptors[$options['format']])) {
|
||||
throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
|
||||
}
|
||||
|
||||
$descriptor = $this->descriptors[$options['format']];
|
||||
|
||||
$output->writeln($descriptor->describe($object, $options), $type);
|
||||
$descriptor->describe($output, $object, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class DialogHelper extends Helper
|
||||
class DialogHelper extends InputAwareHelper
|
||||
{
|
||||
private $inputStream;
|
||||
private static $shell;
|
||||
@@ -98,6 +98,10 @@ class DialogHelper extends Helper
|
||||
*/
|
||||
public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
|
||||
{
|
||||
if ($this->input && !$this->input->isInteractive()) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$output->write($question);
|
||||
|
||||
$inputStream = $this->inputStream ?: STDIN;
|
||||
|
||||
@@ -18,9 +18,9 @@ use Symfony\Component\Console\Command\Command;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class HelperSet
|
||||
class HelperSet implements \IteratorAggregate
|
||||
{
|
||||
private $helpers;
|
||||
private $helpers = array();
|
||||
private $command;
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,6 @@ class HelperSet
|
||||
*/
|
||||
public function __construct(array $helpers = array())
|
||||
{
|
||||
$this->helpers = array();
|
||||
foreach ($helpers as $alias => $helper) {
|
||||
$this->set($helper, is_int($alias) ? null : $alias);
|
||||
}
|
||||
@@ -101,4 +100,9 @@ class HelperSet
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->helpers);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-17
@@ -227,22 +227,7 @@ class ProgressHelper extends Helper
|
||||
*/
|
||||
public function advance($step = 1, $redraw = false)
|
||||
{
|
||||
if (null === $this->startTime) {
|
||||
throw new \LogicException('You must start the progress bar before calling advance().');
|
||||
}
|
||||
|
||||
if (0 === $this->current) {
|
||||
$redraw = true;
|
||||
}
|
||||
|
||||
$prevPeriod = intval($this->current / $this->redrawFreq);
|
||||
|
||||
$this->current += $step;
|
||||
|
||||
$currPeriod = intval($this->current / $this->redrawFreq);
|
||||
if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
|
||||
$this->display();
|
||||
}
|
||||
$this->setCurrent($this->current + $step, $redraw);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +257,7 @@ class ProgressHelper extends Helper
|
||||
$prevPeriod = intval($this->current / $this->redrawFreq);
|
||||
|
||||
$this->current = $current;
|
||||
|
||||
|
||||
$currPeriod = intval($this->current / $this->redrawFreq);
|
||||
if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
|
||||
$this->display();
|
||||
@@ -299,6 +284,18 @@ class ProgressHelper extends Helper
|
||||
$this->overwrite($this->output, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the progress bar from the current line.
|
||||
*
|
||||
* This is useful if you wish to write some output
|
||||
* while a progress bar is running.
|
||||
* Call display() to show the progress bar again.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->overwrite($this->output, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress output.
|
||||
*/
|
||||
|
||||
@@ -23,6 +23,7 @@ class TableHelper extends Helper
|
||||
{
|
||||
const LAYOUT_DEFAULT = 0;
|
||||
const LAYOUT_BORDERLESS = 1;
|
||||
const LAYOUT_COMPACT = 2;
|
||||
|
||||
/**
|
||||
* Table headers.
|
||||
@@ -45,6 +46,7 @@ class TableHelper extends Helper
|
||||
private $crossingChar;
|
||||
private $cellHeaderFormat;
|
||||
private $cellRowFormat;
|
||||
private $cellRowContentFormat;
|
||||
private $borderFormat;
|
||||
private $padType;
|
||||
|
||||
@@ -89,7 +91,22 @@ class TableHelper extends Helper
|
||||
->setVerticalBorderChar(' ')
|
||||
->setCrossingChar(' ')
|
||||
->setCellHeaderFormat('<info>%s</info>')
|
||||
->setCellRowFormat('<comment>%s</comment>')
|
||||
->setCellRowFormat('%s')
|
||||
->setCellRowContentFormat(' %s ')
|
||||
->setBorderFormat('%s')
|
||||
->setPadType(STR_PAD_RIGHT)
|
||||
;
|
||||
break;
|
||||
|
||||
case self::LAYOUT_COMPACT:
|
||||
$this
|
||||
->setPaddingChar(' ')
|
||||
->setHorizontalBorderChar('')
|
||||
->setVerticalBorderChar(' ')
|
||||
->setCrossingChar('')
|
||||
->setCellHeaderFormat('<info>%s</info>')
|
||||
->setCellRowFormat('%s')
|
||||
->setCellRowContentFormat('%s')
|
||||
->setBorderFormat('%s')
|
||||
->setPadType(STR_PAD_RIGHT)
|
||||
;
|
||||
@@ -102,7 +119,8 @@ class TableHelper extends Helper
|
||||
->setVerticalBorderChar('|')
|
||||
->setCrossingChar('+')
|
||||
->setCellHeaderFormat('<info>%s</info>')
|
||||
->setCellRowFormat('<comment>%s</comment>')
|
||||
->setCellRowFormat('%s')
|
||||
->setCellRowContentFormat(' %s ')
|
||||
->setBorderFormat('%s')
|
||||
->setPadType(STR_PAD_RIGHT)
|
||||
;
|
||||
@@ -162,6 +180,10 @@ class TableHelper extends Helper
|
||||
*/
|
||||
public function setPaddingChar($paddingChar)
|
||||
{
|
||||
if (!$paddingChar) {
|
||||
throw new \LogicException('The padding char must not be empty');
|
||||
}
|
||||
|
||||
$this->paddingChar = $paddingChar;
|
||||
|
||||
return $this;
|
||||
@@ -237,6 +259,20 @@ class TableHelper extends Helper
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets row cell content format.
|
||||
*
|
||||
* @param string $cellRowContentFormat
|
||||
*
|
||||
* @return TableHelper
|
||||
*/
|
||||
public function setCellRowContentFormat($cellRowContentFormat)
|
||||
{
|
||||
$this->cellRowContentFormat = $cellRowContentFormat;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets table border format.
|
||||
*
|
||||
@@ -309,11 +345,13 @@ class TableHelper extends Helper
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->horizontalBorderChar && !$this->crossingChar) {
|
||||
return;
|
||||
}
|
||||
|
||||
$markup = $this->crossingChar;
|
||||
for ($column = 0; $column < $count; $column++) {
|
||||
$markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column))
|
||||
.$this->crossingChar
|
||||
;
|
||||
$markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)).$this->crossingChar;
|
||||
}
|
||||
|
||||
$this->output->writeln(sprintf($this->borderFormat, $markup));
|
||||
@@ -366,15 +404,9 @@ class TableHelper extends Helper
|
||||
$width += strlen($cell) - mb_strlen($cell, $encoding);
|
||||
}
|
||||
|
||||
$this->output->write(sprintf(
|
||||
$cellFormat,
|
||||
str_pad(
|
||||
$this->paddingChar.$cell.$this->paddingChar,
|
||||
$width,
|
||||
$this->paddingChar,
|
||||
$this->padType
|
||||
)
|
||||
));
|
||||
$content = sprintf($this->cellRowContentFormat, $cell);
|
||||
|
||||
$this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->paddingChar, $this->padType)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -416,7 +448,7 @@ class TableHelper extends Helper
|
||||
$lengths[] = $this->getCellWidth($row, $column);
|
||||
}
|
||||
|
||||
return $this->columnWidths[$column] = max($lengths) + 2;
|
||||
return $this->columnWidths[$column] = max($lengths) + strlen($this->cellRowContentFormat) - 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,9 +24,12 @@ namespace Symfony\Component\Console\Input;
|
||||
*/
|
||||
abstract class Input implements InputInterface
|
||||
{
|
||||
/**
|
||||
* @var InputDefinition
|
||||
*/
|
||||
protected $definition;
|
||||
protected $options;
|
||||
protected $arguments;
|
||||
protected $options = array();
|
||||
protected $arguments = array();
|
||||
protected $interactive = true;
|
||||
|
||||
/**
|
||||
@@ -37,8 +40,6 @@ abstract class Input implements InputInterface
|
||||
public function __construct(InputDefinition $definition = null)
|
||||
{
|
||||
if (null === $definition) {
|
||||
$this->arguments = array();
|
||||
$this->options = array();
|
||||
$this->definition = new InputDefinition();
|
||||
} else {
|
||||
$this->bind($definition);
|
||||
|
||||
+12
-2
@@ -18,6 +18,7 @@ if (!defined('JSON_UNESCAPED_UNICODE')) {
|
||||
|
||||
use Symfony\Component\Console\Descriptor\TextDescriptor;
|
||||
use Symfony\Component\Console\Descriptor\XmlDescriptor;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
|
||||
/**
|
||||
* A InputDefinition represents a set of valid command line arguments and options.
|
||||
@@ -426,8 +427,10 @@ class InputDefinition
|
||||
public function asText()
|
||||
{
|
||||
$descriptor = new TextDescriptor();
|
||||
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
|
||||
$descriptor->describe($output, $this, array('raw_output' => true));
|
||||
|
||||
return $descriptor->describe($this);
|
||||
return $output->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,6 +446,13 @@ class InputDefinition
|
||||
{
|
||||
$descriptor = new XmlDescriptor();
|
||||
|
||||
return $descriptor->describe($this, array('as_dom' => $asDom));
|
||||
if ($asDom) {
|
||||
return $descriptor->getInputDefinitionDocument($this);
|
||||
}
|
||||
|
||||
$output = new BufferedOutput();
|
||||
$descriptor->describe($output, $this);
|
||||
|
||||
return $output->fetch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ abstract class Output implements OutputInterface
|
||||
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
|
||||
{
|
||||
$this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
|
||||
$this->formatter = null === $formatter ? new OutputFormatter() : $formatter;
|
||||
$this->formatter = $formatter ?: new OutputFormatter();
|
||||
$this->formatter->setDecorated($decorated);
|
||||
}
|
||||
|
||||
@@ -98,6 +98,26 @@ abstract class Output implements OutputInterface
|
||||
return $this->verbosity;
|
||||
}
|
||||
|
||||
public function isQuiet()
|
||||
{
|
||||
return self::VERBOSITY_QUIET === $this->verbosity;
|
||||
}
|
||||
|
||||
public function isVerbose()
|
||||
{
|
||||
return self::VERBOSITY_VERBOSE <= $this->verbosity;
|
||||
}
|
||||
|
||||
public function isVeryVerbose()
|
||||
{
|
||||
return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
|
||||
}
|
||||
|
||||
public function isDebug()
|
||||
{
|
||||
return self::VERBOSITY_DEBUG <= $this->verbosity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ class Shell
|
||||
private $history;
|
||||
private $output;
|
||||
private $hasReadline;
|
||||
private $processIsolation;
|
||||
private $processIsolation = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -48,7 +48,6 @@ class Shell
|
||||
$this->application = $application;
|
||||
$this->history = getenv('HOME').'/.history_'.$application->getName();
|
||||
$this->output = new ConsoleOutput();
|
||||
$this->processIsolation = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+12
-1
@@ -32,6 +32,7 @@ class ApplicationTester
|
||||
private $application;
|
||||
private $input;
|
||||
private $output;
|
||||
private $statusCode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -72,7 +73,7 @@ class ApplicationTester
|
||||
$this->output->setVerbosity($options['verbosity']);
|
||||
}
|
||||
|
||||
return $this->application->run($this->input, $this->output);
|
||||
return $this->statusCode = $this->application->run($this->input, $this->output);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,4 +115,14 @@ class ApplicationTester
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status code returned by the last execution of the application.
|
||||
*
|
||||
* @return integer The status code
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ class CommandTester
|
||||
private $command;
|
||||
private $input;
|
||||
private $output;
|
||||
private $statusCode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -54,6 +55,15 @@ class CommandTester
|
||||
*/
|
||||
public function execute(array $input, array $options = array())
|
||||
{
|
||||
// set the command name automatically if the application requires
|
||||
// this argument and no command name was passed
|
||||
if (!isset($input['command'])
|
||||
&& (null !== $application = $this->command->getApplication())
|
||||
&& $application->getDefinition()->hasArgument('command')
|
||||
) {
|
||||
$input['command'] = $this->command->getName();
|
||||
}
|
||||
|
||||
$this->input = new ArrayInput($input);
|
||||
if (isset($options['interactive'])) {
|
||||
$this->input->setInteractive($options['interactive']);
|
||||
@@ -67,7 +77,7 @@ class CommandTester
|
||||
$this->output->setVerbosity($options['verbosity']);
|
||||
}
|
||||
|
||||
return $this->command->run($this->input, $this->output);
|
||||
return $this->statusCode = $this->command->run($this->input, $this->output);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,4 +119,14 @@ class CommandTester
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status code returned by the last execution of the application.
|
||||
*
|
||||
* @return integer The status code
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
+98
-31
@@ -14,6 +14,7 @@ namespace Symfony\Component\Console\Tests;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
@@ -22,6 +23,7 @@ use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\NullOutput;
|
||||
use Symfony\Component\Console\Output\Output;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
use Symfony\Component\Console\Tester\ApplicationTester;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
|
||||
@@ -40,6 +42,9 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
require_once self::$fixturesPath.'/Foo2Command.php';
|
||||
require_once self::$fixturesPath.'/Foo3Command.php';
|
||||
require_once self::$fixturesPath.'/Foo4Command.php';
|
||||
require_once self::$fixturesPath.'/Foo5Command.php';
|
||||
require_once self::$fixturesPath.'/FoobarCommand.php';
|
||||
require_once self::$fixturesPath.'/BarBucCommand.php';
|
||||
}
|
||||
|
||||
protected function normalizeLineBreaks($text)
|
||||
@@ -124,6 +129,16 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(array($foo, $foo1), array($commands['foo:bar'], $commands['foo:bar1']), '->addCommands() registers an array of commands');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor.
|
||||
*/
|
||||
public function testAddCommandWithEmptyConstructor()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new \Foo5Command());
|
||||
}
|
||||
|
||||
public function testHasGet()
|
||||
{
|
||||
$application = new Application();
|
||||
@@ -193,6 +208,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
public function testFindAmbiguousNamespace()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new \BarBucCommand());
|
||||
$application->add(new \FooCommand());
|
||||
$application->add(new \Foo2Command());
|
||||
$application->findNamespace('f');
|
||||
@@ -208,6 +224,20 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
$application->findNamespace('bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Command "foo1" is not defined
|
||||
*/
|
||||
public function testFindUniqueNameButNamespaceName()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new \FooCommand());
|
||||
$application->add(new \Foo1Command());
|
||||
$application->add(new \Foo2Command());
|
||||
|
||||
$application->find($commandName = 'foo1');
|
||||
}
|
||||
|
||||
public function testFind()
|
||||
{
|
||||
$application = new Application();
|
||||
@@ -240,7 +270,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
return array(
|
||||
array('f', 'Command "f" is not defined.'),
|
||||
array('a', 'Command "a" is ambiguous (afoobar, afoobar1 and 1 more).'),
|
||||
array('foo:b', 'Command "foo:b" is ambiguous (foo:bar, foo:bar1).')
|
||||
array('foo:b', 'Command "foo:b" is ambiguous (foo:bar, foo:bar1 and 1 more).')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -254,6 +284,23 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertInstanceOf('Foo4Command', $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name');
|
||||
}
|
||||
|
||||
public function testFindCommandWithAmbiguousNamespacesButUniqueName()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new \FooCommand());
|
||||
$application->add(new \FoobarCommand());
|
||||
|
||||
$this->assertInstanceOf('FoobarCommand', $application->find('f:f'));
|
||||
}
|
||||
|
||||
public function testFindCommandWithMissingNamespace()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new \Foo4Command());
|
||||
|
||||
$this->assertInstanceOf('Foo4Command', $application->find('f::t'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideInvalidCommandNamesSingle
|
||||
* @expectedException \InvalidArgumentException
|
||||
@@ -262,15 +309,15 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
public function testFindAlternativeExceptionMessageSingle($name)
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new \FooCommand());
|
||||
$application->add(new \Foo3Command());
|
||||
$application->find($name);
|
||||
}
|
||||
|
||||
public function provideInvalidCommandNamesSingle()
|
||||
{
|
||||
return array(
|
||||
array('foo:baR'),
|
||||
array('foO:bar')
|
||||
array('foo3:baR'),
|
||||
array('foO3:bar')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -288,6 +335,8 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
} catch (\Exception $e) {
|
||||
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||
$this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||
$this->assertRegExp('/foo1:bar/', $e->getMessage());
|
||||
$this->assertRegExp('/foo:bar/', $e->getMessage());
|
||||
}
|
||||
|
||||
// Namespace + plural
|
||||
@@ -297,6 +346,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
} catch (\Exception $e) {
|
||||
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||
$this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||
$this->assertRegExp('/foo1/', $e->getMessage());
|
||||
}
|
||||
|
||||
$application->add(new \Foo3Command());
|
||||
@@ -329,26 +379,17 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, without alternatives');
|
||||
}
|
||||
|
||||
// Test if "bar1" command throw an "\InvalidArgumentException" and does not contain
|
||||
// "foo:bar" as alternative because "bar1" is too far from "foo:bar"
|
||||
try {
|
||||
$application->find($commandName = 'foo');
|
||||
$application->find($commandName = 'bar1');
|
||||
$this->fail('->find() throws an \InvalidArgumentException if command does not exist');
|
||||
} catch (\Exception $e) {
|
||||
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
|
||||
$this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||
$this->assertRegExp('/foo:bar/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo:bar"');
|
||||
$this->assertRegExp('/foo1:bar/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo1:bar"');
|
||||
$this->assertRegExp('/afoobar1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "afoobar1"');
|
||||
$this->assertRegExp('/foo:bar1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo:bar1"');
|
||||
}
|
||||
|
||||
// Test if "foo1" command throw an "\InvalidArgumentException" and does not contain
|
||||
// "foo:bar" as alternative because "foo1" is too far from "foo:bar"
|
||||
try {
|
||||
$application->find($commandName = 'foo1');
|
||||
$this->fail('->find() throws an \InvalidArgumentException if command does not exist');
|
||||
} catch (\Exception $e) {
|
||||
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
|
||||
$this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||
$this->assertFalse(strpos($e->getMessage(), 'foo:bar'), '->find() throws an \InvalidArgumentException if command does not exist, without "foo:bar" alternative');
|
||||
$this->assertNotRegExp('/foo:bar(?>!1)/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, without "foo:bar" alternative');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,6 +602,29 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue #9285
|
||||
*
|
||||
* If the "verbose" option is just before an argument in ArgvInput,
|
||||
* an argument value should not be treated as verbosity value.
|
||||
* This test will fail with "Not enough arguments." if broken
|
||||
*/
|
||||
public function testVerboseValueNotBreakArguments()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->setCatchExceptions(false);
|
||||
$application->add(new \FooCommand());
|
||||
|
||||
$output = new StreamOutput(fopen('php://memory', 'w', false));
|
||||
|
||||
$input = new ArgvInput(array('cli.php', '-v', 'foo:bar'));
|
||||
$application->run($input, $output);
|
||||
|
||||
$input = new ArgvInput(array('cli.php', '--verbose', 'foo:bar'));
|
||||
$application->run($input, $output);
|
||||
}
|
||||
|
||||
public function testRunReturnsIntegerExitCode()
|
||||
{
|
||||
$exception = new \Exception('', 4);
|
||||
@@ -734,10 +798,6 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testRunWithDispatcher()
|
||||
{
|
||||
if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
|
||||
$this->markTestSkipped('The "EventDispatcher" component is not available');
|
||||
}
|
||||
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->setDispatcher($this->getDispatcher());
|
||||
@@ -757,10 +817,6 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testRunWithExceptionAndDispatcher()
|
||||
{
|
||||
if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
|
||||
$this->markTestSkipped('The "EventDispatcher" component is not available');
|
||||
}
|
||||
|
||||
$application = new Application();
|
||||
$application->setDispatcher($this->getDispatcher());
|
||||
$application->setAutoExit(false);
|
||||
@@ -776,10 +832,6 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testRunDispatchesAllEventsWithException()
|
||||
{
|
||||
if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
|
||||
$this->markTestSkipped('The "EventDispatcher" component is not available');
|
||||
}
|
||||
|
||||
$application = new Application();
|
||||
$application->setDispatcher($this->getDispatcher());
|
||||
$application->setAutoExit(false);
|
||||
@@ -795,9 +847,24 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertContains('before.foo.after.caught.', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testTerminalDimensions()
|
||||
{
|
||||
$application = new Application();
|
||||
$originalDimensions = $application->getTerminalDimensions();
|
||||
$this->assertCount(2, $originalDimensions);
|
||||
|
||||
$width = 80;
|
||||
if ($originalDimensions[0] == $width) {
|
||||
$width = 100;
|
||||
}
|
||||
|
||||
$application->setTerminalDimensions($width, 80);
|
||||
$this->assertSame(array($width, 80), $application->getTerminalDimensions());
|
||||
}
|
||||
|
||||
protected function getDispatcher()
|
||||
{
|
||||
$dispatcher = new EventDispatcher;
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
|
||||
$event->getOutput()->write('before.');
|
||||
});
|
||||
|
||||
Vendored
+13
-5
@@ -16,31 +16,32 @@ use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
|
||||
abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @dataProvider getDescribeInputArgumentTestData */
|
||||
public function testDescribeInputArgument(InputArgument $argument, $expectedDescription)
|
||||
{
|
||||
$this->assertEquals(trim($expectedDescription), trim($this->getDescriptor()->describe($argument)));
|
||||
$this->assertDescription($expectedDescription, $argument);
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeInputOptionTestData */
|
||||
public function testDescribeInputOption(InputOption $option, $expectedDescription)
|
||||
{
|
||||
$this->assertEquals(trim($expectedDescription), trim($this->getDescriptor()->describe($option)));
|
||||
$this->assertDescription($expectedDescription, $option);
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeInputDefinitionTestData */
|
||||
public function testDescribeInputDefinition(InputDefinition $definition, $expectedDescription)
|
||||
{
|
||||
$this->assertEquals(trim($expectedDescription), trim($this->getDescriptor()->describe($definition)));
|
||||
$this->assertDescription($expectedDescription, $definition);
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeCommandTestData */
|
||||
public function testDescribeCommand(Command $command, $expectedDescription)
|
||||
{
|
||||
$this->assertEquals(trim($expectedDescription), trim($this->getDescriptor()->describe($command)));
|
||||
$this->assertDescription($expectedDescription, $command);
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeApplicationTestData */
|
||||
@@ -53,7 +54,7 @@ abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
|
||||
$command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp()));
|
||||
}
|
||||
|
||||
$this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $this->getDescriptor()->describe($application))));
|
||||
$this->assertDescription($expectedDescription, $application);
|
||||
}
|
||||
|
||||
public function getDescribeInputArgumentTestData()
|
||||
@@ -94,4 +95,11 @@ abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function assertDescription($expectedDescription, $describedObject)
|
||||
{
|
||||
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
|
||||
$this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true));
|
||||
$this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch())));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":null},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":null}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]}
|
||||
{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":"txt"}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]}
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ To display the list of available commands, please use the <info>list</info> comm
|
||||
* Is value required: yes
|
||||
* Is multiple: no
|
||||
* Description: To output help in other formats
|
||||
* Default: `NULL`
|
||||
* Default: `'txt'`
|
||||
|
||||
**raw:**
|
||||
|
||||
@@ -196,4 +196,4 @@ It's also possible to get raw list of commands (useful for embedding command run
|
||||
* Is value required: yes
|
||||
* Is multiple: no
|
||||
* Description: To output list in other formats
|
||||
* Default: `NULL`
|
||||
* Default: `'txt'`
|
||||
|
||||
+6
-2
@@ -28,7 +28,9 @@
|
||||
</option>
|
||||
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
|
||||
<description>To output help in other formats</description>
|
||||
<defaults/>
|
||||
<defaults>
|
||||
<default>txt</default>
|
||||
</defaults>
|
||||
</option>
|
||||
<option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>To output raw command help</description>
|
||||
@@ -90,7 +92,9 @@
|
||||
</option>
|
||||
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
|
||||
<description>To output list in other formats</description>
|
||||
<defaults/>
|
||||
<defaults>
|
||||
<default>txt</default>
|
||||
</defaults>
|
||||
</option>
|
||||
</options>
|
||||
</command>
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
-2
@@ -58,7 +58,7 @@ To display the list of available commands, please use the <info>list</info> comm
|
||||
* Is value required: yes
|
||||
* Is multiple: no
|
||||
* Description: To output help in other formats
|
||||
* Default: `NULL`
|
||||
* Default: `'txt'`
|
||||
|
||||
**raw:**
|
||||
|
||||
@@ -203,7 +203,7 @@ It's also possible to get raw list of commands (useful for embedding command run
|
||||
* Is value required: yes
|
||||
* Is multiple: no
|
||||
* Description: To output list in other formats
|
||||
* Default: `NULL`
|
||||
* Default: `'txt'`
|
||||
|
||||
descriptor:command1
|
||||
-------------------
|
||||
|
||||
+7
-3
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<symfony>
|
||||
<symfony name="My Symfony application" version="v1.0">
|
||||
<commands>
|
||||
<command id="help" name="help">
|
||||
<usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
|
||||
@@ -28,7 +28,9 @@
|
||||
</option>
|
||||
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
|
||||
<description>To output help in other formats</description>
|
||||
<defaults/>
|
||||
<defaults>
|
||||
<default>txt</default>
|
||||
</defaults>
|
||||
</option>
|
||||
<option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>To output raw command help</description>
|
||||
@@ -90,7 +92,9 @@
|
||||
</option>
|
||||
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
|
||||
<description>To output list in other formats</description>
|
||||
<defaults/>
|
||||
<defaults>
|
||||
<default>txt</default>
|
||||
</defaults>
|
||||
</option>
|
||||
</options>
|
||||
</command>
|
||||
|
||||
+1
-1
@@ -17,4 +17,4 @@
|
||||
<info>help </info> Displays help for a command
|
||||
<info>list </info> Lists commands
|
||||
<comment>foo</comment>
|
||||
<info>foo:bar </info> The foo:bar command
|
||||
<info>foo:bar </info> The foo:bar command
|
||||
|
||||
+1
-1
@@ -13,4 +13,4 @@
|
||||
<info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.
|
||||
|
||||
<comment>Available commands for the "foo" namespace:</comment>
|
||||
<info>foo:bar </info> The foo:bar command
|
||||
<info>foo:bar </info> The foo:bar command
|
||||
|
||||
+6
-2
@@ -28,7 +28,9 @@
|
||||
</option>
|
||||
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
|
||||
<description>To output help in other formats</description>
|
||||
<defaults/>
|
||||
<defaults>
|
||||
<default>txt</default>
|
||||
</defaults>
|
||||
</option>
|
||||
<option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
|
||||
<description>To output raw command help</description>
|
||||
@@ -90,7 +92,9 @@
|
||||
</option>
|
||||
<option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
|
||||
<description>To output list in other formats</description>
|
||||
<defaults/>
|
||||
<defaults>
|
||||
<default>txt</default>
|
||||
</defaults>
|
||||
</option>
|
||||
</options>
|
||||
</command>
|
||||
|
||||
+1
-2
@@ -7,7 +7,7 @@ Arguments:
|
||||
|
||||
Options:
|
||||
--xml To output help as XML
|
||||
--format To output help in other formats
|
||||
--format To output help in other formats (default: "txt")
|
||||
--raw To output raw command help
|
||||
--help (-h) Display this help message.
|
||||
--quiet (-q) Do not output any message.
|
||||
@@ -27,4 +27,3 @@ Help:
|
||||
php app/console help --format=xml list
|
||||
|
||||
To display the list of available commands, please use the list command.
|
||||
|
||||
|
||||
+1
-2
@@ -7,7 +7,7 @@ Arguments:
|
||||
Options:
|
||||
--xml To output list as XML
|
||||
--raw To output raw command list
|
||||
--format To output list in other formats
|
||||
--format To output list in other formats (default: "txt")
|
||||
|
||||
Help:
|
||||
The list command lists all commands:
|
||||
@@ -25,4 +25,3 @@ Help:
|
||||
It's also possible to get raw list of commands (useful for embedding command runner):
|
||||
|
||||
php app/console list --raw
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -59,7 +59,7 @@ class OutputFormatterStyleStackTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidPop()
|
||||
{
|
||||
|
||||
+13
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Console\Tests\Helper;
|
||||
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Helper\DialogHelper;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
@@ -156,6 +157,18 @@ class DialogHelperTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testNoInteration()
|
||||
{
|
||||
$dialog = new DialogHelper();
|
||||
|
||||
$input = new ArrayInput(array());
|
||||
$input->setInteractive(false);
|
||||
|
||||
$dialog->setInput($input);
|
||||
|
||||
$this->assertEquals('not yet', $dialog->ask($this->getOutputStream(), 'Do you have a job?', 'not yet'));
|
||||
}
|
||||
|
||||
protected function getInputStream($input)
|
||||
{
|
||||
$stream = fopen('php://memory', 'r+', false);
|
||||
|
||||
+17
@@ -111,6 +111,23 @@ class HelperSetTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($cmd, $helperset->getCommand(), '->getCommand() retrieves stored command');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Symfony\Component\Console\Helper\HelperSet::getIterator
|
||||
*/
|
||||
public function testIteration()
|
||||
{
|
||||
$helperset = new HelperSet();
|
||||
$helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset));
|
||||
$helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset));
|
||||
|
||||
$helpers = array('fake_helper_01', 'fake_helper_02');
|
||||
$i = 0;
|
||||
|
||||
foreach ($helperset as $helper) {
|
||||
$this->assertEquals($helpers[$i++], $helper->getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a generic mock for the helper interface. Optionally check for a call to setHelperSet with a specific
|
||||
* helperset instance.
|
||||
|
||||
+14
@@ -166,6 +166,20 @@ class ProgressHelperTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($this->generateOutput(' 3 [■■■>------------------------]'), stream_get_contents($output->getStream()));
|
||||
}
|
||||
|
||||
public function testClear()
|
||||
{
|
||||
$progress = new ProgressHelper();
|
||||
$progress->start($output = $this->getOutputStream(), 50);
|
||||
$progress->setCurrent(25);
|
||||
$progress->clear();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 25/50 [==============>-------------] 50%') . $this->generateOutput(''),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testPercentNotHundredBeforeComplete()
|
||||
{
|
||||
$progress = new ProgressHelper();
|
||||
|
||||
+33
-13
@@ -81,15 +81,17 @@ class TableHelperTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testRenderProvider()
|
||||
{
|
||||
$books = array(
|
||||
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
|
||||
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
|
||||
array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
|
||||
array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
|
||||
);
|
||||
|
||||
return array(
|
||||
array(
|
||||
array('ISBN', 'Title', 'Author'),
|
||||
array(
|
||||
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
|
||||
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
|
||||
array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
|
||||
array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
|
||||
),
|
||||
$books,
|
||||
TableHelper::LAYOUT_DEFAULT,
|
||||
<<<TABLE
|
||||
+---------------+--------------------------+------------------+
|
||||
@@ -105,14 +107,32 @@ TABLE
|
||||
),
|
||||
array(
|
||||
array('ISBN', 'Title', 'Author'),
|
||||
array(
|
||||
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
|
||||
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
|
||||
array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
|
||||
array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
|
||||
),
|
||||
$books,
|
||||
TableHelper::LAYOUT_COMPACT,
|
||||
<<<TABLE
|
||||
ISBN Title Author
|
||||
99921-58-10-7 Divine Comedy Dante Alighieri
|
||||
9971-5-0210-0 A Tale of Two Cities Charles Dickens
|
||||
960-425-059-0 The Lord of the Rings J. R. R. Tolkien
|
||||
80-902734-1-6 And Then There Were None Agatha Christie
|
||||
|
||||
TABLE
|
||||
),
|
||||
array(
|
||||
array('ISBN', 'Title', 'Author'),
|
||||
$books,
|
||||
TableHelper::LAYOUT_BORDERLESS,
|
||||
" =============== ========================== ================== \n ISBN Title Author \n =============== ========================== ================== \n 99921-58-10-7 Divine Comedy Dante Alighieri \n 9971-5-0210-0 A Tale of Two Cities Charles Dickens \n 960-425-059-0 The Lord of the Rings J. R. R. Tolkien \n 80-902734-1-6 And Then There Were None Agatha Christie \n =============== ========================== ================== \n"
|
||||
<<<TABLE
|
||||
=============== ========================== ==================
|
||||
ISBN Title Author
|
||||
=============== ========================== ==================
|
||||
99921-58-10-7 Divine Comedy Dante Alighieri
|
||||
9971-5-0210-0 A Tale of Two Cities Charles Dickens
|
||||
960-425-059-0 The Lord of the Rings J. R. R. Tolkien
|
||||
80-902734-1-6 And Then There Were None Agatha Christie
|
||||
=============== ========================== ==================
|
||||
|
||||
TABLE
|
||||
),
|
||||
array(
|
||||
array('ISBN', 'Title'),
|
||||
|
||||
@@ -35,6 +35,35 @@ class OutputTest extends \PHPUnit_Framework_TestCase
|
||||
$output = new TestOutput();
|
||||
$output->setVerbosity(Output::VERBOSITY_QUIET);
|
||||
$this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '->setVerbosity() sets the verbosity');
|
||||
|
||||
$this->assertTrue($output->isQuiet());
|
||||
$this->assertFalse($output->isVerbose());
|
||||
$this->assertFalse($output->isVeryVerbose());
|
||||
$this->assertFalse($output->isDebug());
|
||||
|
||||
$output->setVerbosity(Output::VERBOSITY_NORMAL);
|
||||
$this->assertFalse($output->isQuiet());
|
||||
$this->assertFalse($output->isVerbose());
|
||||
$this->assertFalse($output->isVeryVerbose());
|
||||
$this->assertFalse($output->isDebug());
|
||||
|
||||
$output->setVerbosity(Output::VERBOSITY_VERBOSE);
|
||||
$this->assertFalse($output->isQuiet());
|
||||
$this->assertTrue($output->isVerbose());
|
||||
$this->assertFalse($output->isVeryVerbose());
|
||||
$this->assertFalse($output->isDebug());
|
||||
|
||||
$output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE);
|
||||
$this->assertFalse($output->isQuiet());
|
||||
$this->assertTrue($output->isVerbose());
|
||||
$this->assertTrue($output->isVeryVerbose());
|
||||
$this->assertFalse($output->isDebug());
|
||||
|
||||
$output->setVerbosity(Output::VERBOSITY_DEBUG);
|
||||
$this->assertFalse($output->isQuiet());
|
||||
$this->assertTrue($output->isVerbose());
|
||||
$this->assertTrue($output->isVeryVerbose());
|
||||
$this->assertTrue($output->isDebug());
|
||||
}
|
||||
|
||||
public function testWriteWithVerbosityQuiet()
|
||||
|
||||
+5
@@ -61,4 +61,9 @@ class ApplicationTesterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution');
|
||||
}
|
||||
|
||||
public function testGetStatusCode()
|
||||
{
|
||||
$this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Console\Tests\Tester;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Output\Output;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
@@ -59,4 +60,25 @@ class CommandTesterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution');
|
||||
}
|
||||
|
||||
public function testGetStatusCode()
|
||||
{
|
||||
$this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
|
||||
}
|
||||
|
||||
public function testCommandFromApplication()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
|
||||
$command = new Command('foo');
|
||||
$command->setCode(function ($input, $output) { $output->writeln('foo'); });
|
||||
|
||||
$application->add($command);
|
||||
|
||||
$tester = new CommandTester($application->find('foo'));
|
||||
|
||||
// check that there is no need to pass the command name here
|
||||
$this->assertEquals(0, $tester->execute(array()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ test: Simple Mapping
|
||||
brief: |
|
||||
You can add a keyed list (also known as a dictionary or
|
||||
hash) to your document by placing each member of the
|
||||
list on a new line, with a colon seperating the key
|
||||
list on a new line, with a colon separating the key
|
||||
from its value. In YAML, this type of list is called
|
||||
a mapping.
|
||||
yaml: |
|
||||
|
||||
+1
-1
@@ -222,7 +222,7 @@ yaml: |
|
||||
# Following node labeled SS
|
||||
- &SS Sammy Sosa
|
||||
rbi:
|
||||
- *SS # Subsequent occurance
|
||||
- *SS # Subsequent occurrence
|
||||
- Ken Griffey
|
||||
php: |
|
||||
array(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user