Issue #2366043 by dawehner: Upgrade to Symfony 2.6
parent
150cbcf61f
commit
3b945fe250
|
|
@ -6,16 +6,17 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.4.5",
|
"php": ">=5.4.5",
|
||||||
"sdboyer/gliph": "0.1.*",
|
"sdboyer/gliph": "0.1.*",
|
||||||
"symfony/class-loader": "2.5.*",
|
"symfony/class-loader": "2.6.0-beta1",
|
||||||
"symfony/css-selector": "2.5.*",
|
"symfony/css-selector": "2.6.0-beta1",
|
||||||
"symfony/dependency-injection": "2.5.*",
|
"symfony/debug": "2.6.0-beta1",
|
||||||
"symfony/event-dispatcher": "2.5.*",
|
"symfony/dependency-injection": "2.6.0-beta1",
|
||||||
"symfony/http-foundation": "2.5.*",
|
"symfony/event-dispatcher": "2.6.0-beta1",
|
||||||
"symfony/http-kernel": "2.5.*",
|
"symfony/http-foundation": "2.6.0-beta1",
|
||||||
"symfony/routing": "2.5.*",
|
"symfony/http-kernel": "2.6.0-beta1",
|
||||||
"symfony/serializer": "2.5.*",
|
"symfony/routing": "2.6.0-beta1",
|
||||||
"symfony/validator": "2.5.*",
|
"symfony/serializer": "2.6.0-beta1",
|
||||||
"symfony/yaml": "dev-master#499f7d7aa96747ad97940089bd7a1fb24ad8182a",
|
"symfony/validator": "2.6.0-beta1",
|
||||||
|
"symfony/yaml": "2.6.0-beta1",
|
||||||
"twig/twig": "1.16.*",
|
"twig/twig": "1.16.*",
|
||||||
"doctrine/common": "dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5",
|
"doctrine/common": "dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5",
|
||||||
"doctrine/annotations": "1.2.*",
|
"doctrine/annotations": "1.2.*",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "2bd5814ec010b13a6997359736b58695",
|
"hash": "34a4f5a56891e51217c305b97e8cc675",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "doctrine/annotations",
|
"name": "doctrine/annotations",
|
||||||
|
|
@ -518,16 +518,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "egulias/email-validator",
|
"name": "egulias/email-validator",
|
||||||
"version": "1.2.2",
|
"version": "1.2.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/egulias/EmailValidator.git",
|
"url": "https://github.com/egulias/EmailValidator.git",
|
||||||
"reference": "39b451bb2bb0655d83d82a38a0bba7189298cfc5"
|
"reference": "518f80a0ff7c1a35780e7702f4262c8c6f2b807f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/39b451bb2bb0655d83d82a38a0bba7189298cfc5",
|
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/518f80a0ff7c1a35780e7702f4262c8c6f2b807f",
|
||||||
"reference": "39b451bb2bb0655d83d82a38a0bba7189298cfc5",
|
"reference": "518f80a0ff7c1a35780e7702f4262c8c6f2b807f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -540,7 +540,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.0.x-dev"
|
"dev-master": "1.3.x-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -564,7 +564,7 @@
|
||||||
"validation",
|
"validation",
|
||||||
"validator"
|
"validator"
|
||||||
],
|
],
|
||||||
"time": "2014-09-01 22:35:48"
|
"time": "2014-11-06 08:59:44"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/guzzle",
|
"name": "guzzlehttp/guzzle",
|
||||||
|
|
@ -626,16 +626,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/ringphp",
|
"name": "guzzlehttp/ringphp",
|
||||||
"version": "1.0.0",
|
"version": "1.0.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/guzzle/RingPHP.git",
|
"url": "https://github.com/guzzle/RingPHP.git",
|
||||||
"reference": "9e44b565d726d9614cd970319e6eea70ee15bff3"
|
"reference": "e7c28f96c5ac12ab0e63412cfc15989756fcb964"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/guzzle/RingPHP/zipball/9e44b565d726d9614cd970319e6eea70ee15bff3",
|
"url": "https://api.github.com/repos/guzzle/RingPHP/zipball/e7c28f96c5ac12ab0e63412cfc15989756fcb964",
|
||||||
"reference": "9e44b565d726d9614cd970319e6eea70ee15bff3",
|
"reference": "e7c28f96c5ac12ab0e63412cfc15989756fcb964",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -672,7 +672,7 @@
|
||||||
"homepage": "https://github.com/mtdowling"
|
"homepage": "https://github.com/mtdowling"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2014-10-13 00:59:38"
|
"time": "2014-11-04 07:01:14"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/streams",
|
"name": "guzzlehttp/streams",
|
||||||
|
|
@ -1386,16 +1386,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/environment",
|
"name": "sebastian/environment",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||||
"reference": "6288ebbf6fa3ed2b2ff2d69c356fbaaf4f0971a7"
|
"reference": "0d9bf79554d2a999da194a60416c15cf461eb67d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6288ebbf6fa3ed2b2ff2d69c356fbaaf4f0971a7",
|
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/0d9bf79554d2a999da194a60416c15cf461eb67d",
|
||||||
"reference": "6288ebbf6fa3ed2b2ff2d69c356fbaaf4f0971a7",
|
"reference": "0d9bf79554d2a999da194a60416c15cf461eb67d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1407,7 +1407,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.1.x-dev"
|
"dev-master": "1.2.x-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1432,7 +1432,7 @@
|
||||||
"environment",
|
"environment",
|
||||||
"hhvm"
|
"hhvm"
|
||||||
],
|
],
|
||||||
"time": "2014-10-07 09:23:16"
|
"time": "2014-10-22 06:38:05"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/exporter",
|
"name": "sebastian/exporter",
|
||||||
|
|
@ -1643,17 +1643,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/class-loader",
|
"name": "symfony/class-loader",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/ClassLoader",
|
"target-dir": "Symfony/Component/ClassLoader",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/ClassLoader.git",
|
"url": "https://github.com/symfony/ClassLoader.git",
|
||||||
"reference": "432561f655123b003b32f370ca812fed9a9340c6"
|
"reference": "d1a16139ea522ec3cc20801b7e19cd3cafd12d8c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/ClassLoader/zipball/432561f655123b003b32f370ca812fed9a9340c6",
|
"url": "https://api.github.com/repos/symfony/ClassLoader/zipball/d1a16139ea522ec3cc20801b7e19cd3cafd12d8c",
|
||||||
"reference": "432561f655123b003b32f370ca812fed9a9340c6",
|
"reference": "d1a16139ea522ec3cc20801b7e19cd3cafd12d8c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1665,7 +1665,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1689,21 +1689,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony ClassLoader Component",
|
"description": "Symfony ClassLoader Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-22 09:14:18"
|
"time": "2014-11-03 03:55:50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/css-selector",
|
"name": "symfony/css-selector",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/CssSelector",
|
"target-dir": "Symfony/Component/CssSelector",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/CssSelector.git",
|
"url": "https://github.com/symfony/CssSelector.git",
|
||||||
"reference": "caf5ecc3face1f22884fb74b8edab65ac5ba9976"
|
"reference": "41953ad30ffc5cd710d106cf01eff79f6effa117"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/CssSelector/zipball/caf5ecc3face1f22884fb74b8edab65ac5ba9976",
|
"url": "https://api.github.com/repos/symfony/CssSelector/zipball/41953ad30ffc5cd710d106cf01eff79f6effa117",
|
||||||
"reference": "caf5ecc3face1f22884fb74b8edab65ac5ba9976",
|
"reference": "41953ad30ffc5cd710d106cf01eff79f6effa117",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1712,7 +1712,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1740,25 +1740,26 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony CssSelector Component",
|
"description": "Symfony CssSelector Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-22 09:14:18"
|
"time": "2014-10-26 07:46:28"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/debug",
|
"name": "symfony/debug",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/Debug",
|
"target-dir": "Symfony/Component/Debug",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Debug.git",
|
"url": "https://github.com/symfony/Debug.git",
|
||||||
"reference": "4a3dd4ef3fc0cee2fd9faaae12bd7af43afcf648"
|
"reference": "3548595c26175fdaca19cbec204668c22cda41f0"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Debug/zipball/4a3dd4ef3fc0cee2fd9faaae12bd7af43afcf648",
|
"url": "https://api.github.com/repos/symfony/Debug/zipball/3548595c26175fdaca19cbec204668c22cda41f0",
|
||||||
"reference": "4a3dd4ef3fc0cee2fd9faaae12bd7af43afcf648",
|
"reference": "3548595c26175fdaca19cbec204668c22cda41f0",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3",
|
||||||
|
"psr/log": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/http-foundation": "~2.1",
|
"symfony/http-foundation": "~2.1",
|
||||||
|
|
@ -1771,7 +1772,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1795,21 +1796,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Debug Component",
|
"description": "Symfony Debug Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-28 15:22:14"
|
"time": "2014-10-28 10:06:58"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dependency-injection",
|
"name": "symfony/dependency-injection",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/DependencyInjection",
|
"target-dir": "Symfony/Component/DependencyInjection",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/DependencyInjection.git",
|
"url": "https://github.com/symfony/DependencyInjection.git",
|
||||||
"reference": "1f01a64c9047909e40700a14ee34e8c446300618"
|
"reference": "926500fe0b8a6562c4e8b8166a1cb664733804aa"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/1f01a64c9047909e40700a14ee34e8c446300618",
|
"url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/926500fe0b8a6562c4e8b8166a1cb664733804aa",
|
||||||
"reference": "1f01a64c9047909e40700a14ee34e8c446300618",
|
"reference": "926500fe0b8a6562c4e8b8166a1cb664733804aa",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1828,7 +1829,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1852,21 +1853,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony DependencyInjection Component",
|
"description": "Symfony DependencyInjection Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-27 08:35:39"
|
"time": "2014-11-03 03:55:50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/EventDispatcher",
|
"target-dir": "Symfony/Component/EventDispatcher",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/EventDispatcher.git",
|
"url": "https://github.com/symfony/EventDispatcher.git",
|
||||||
"reference": "f6281337bf5f985f585d1db6a83adb05ce531f46"
|
"reference": "dcf345d5ed96bc6c3b4521c1989670d2c9e5014e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/f6281337bf5f985f585d1db6a83adb05ce531f46",
|
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/dcf345d5ed96bc6c3b4521c1989670d2c9e5014e",
|
||||||
"reference": "f6281337bf5f985f585d1db6a83adb05ce531f46",
|
"reference": "dcf345d5ed96bc6c3b4521c1989670d2c9e5014e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1875,7 +1876,8 @@
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0",
|
||||||
"symfony/config": "~2.0",
|
"symfony/config": "~2.0",
|
||||||
"symfony/dependency-injection": "~2.0,<2.6.0",
|
"symfony/dependency-injection": "~2.6",
|
||||||
|
"symfony/expression-language": "~2.6",
|
||||||
"symfony/stopwatch": "~2.2"
|
"symfony/stopwatch": "~2.2"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
|
@ -1885,7 +1887,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1909,21 +1911,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony EventDispatcher Component",
|
"description": "Symfony EventDispatcher Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-28 15:56:11"
|
"time": "2014-11-03 03:55:50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-foundation",
|
"name": "symfony/http-foundation",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/HttpFoundation",
|
"target-dir": "Symfony/Component/HttpFoundation",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/HttpFoundation.git",
|
"url": "https://github.com/symfony/HttpFoundation.git",
|
||||||
"reference": "650e115af152d7a5e857d01c2cdb9a22809de9b4"
|
"reference": "4cd6c807598e560db7b3da50c4330fdb4808cfa1"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/650e115af152d7a5e857d01c2cdb9a22809de9b4",
|
"url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/4cd6c807598e560db7b3da50c4330fdb4808cfa1",
|
||||||
"reference": "650e115af152d7a5e857d01c2cdb9a22809de9b4",
|
"reference": "4cd6c807598e560db7b3da50c4330fdb4808cfa1",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1935,7 +1937,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1962,27 +1964,27 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony HttpFoundation Component",
|
"description": "Symfony HttpFoundation Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-25 09:52:29"
|
"time": "2014-11-03 03:55:50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-kernel",
|
"name": "symfony/http-kernel",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/HttpKernel",
|
"target-dir": "Symfony/Component/HttpKernel",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/HttpKernel.git",
|
"url": "https://github.com/symfony/HttpKernel.git",
|
||||||
"reference": "6a3595611229def14d5e644f060cf372235532ec"
|
"reference": "7fa0bd9220cd529ee78d8565bbf8d5a854bd72d2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/HttpKernel/zipball/6a3595611229def14d5e644f060cf372235532ec",
|
"url": "https://api.github.com/repos/symfony/HttpKernel/zipball/7fa0bd9220cd529ee78d8565bbf8d5a854bd72d2",
|
||||||
"reference": "6a3595611229def14d5e644f060cf372235532ec",
|
"reference": "7fa0bd9220cd529ee78d8565bbf8d5a854bd72d2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3",
|
"php": ">=5.3.3",
|
||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0",
|
||||||
"symfony/debug": "~2.5",
|
"symfony/debug": "~2.6",
|
||||||
"symfony/event-dispatcher": "~2.5",
|
"symfony/event-dispatcher": "~2.5",
|
||||||
"symfony/http-foundation": "~2.5"
|
"symfony/http-foundation": "~2.5"
|
||||||
},
|
},
|
||||||
|
|
@ -1997,7 +1999,9 @@
|
||||||
"symfony/process": "~2.0",
|
"symfony/process": "~2.0",
|
||||||
"symfony/routing": "~2.2",
|
"symfony/routing": "~2.2",
|
||||||
"symfony/stopwatch": "~2.2",
|
"symfony/stopwatch": "~2.2",
|
||||||
"symfony/templating": "~2.2"
|
"symfony/templating": "~2.2",
|
||||||
|
"symfony/translation": "~2.0",
|
||||||
|
"symfony/var-dumper": "~2.6"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/browser-kit": "",
|
"symfony/browser-kit": "",
|
||||||
|
|
@ -2005,12 +2009,13 @@
|
||||||
"symfony/config": "",
|
"symfony/config": "",
|
||||||
"symfony/console": "",
|
"symfony/console": "",
|
||||||
"symfony/dependency-injection": "",
|
"symfony/dependency-injection": "",
|
||||||
"symfony/finder": ""
|
"symfony/finder": "",
|
||||||
|
"symfony/var-dumper": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -2034,68 +2039,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony HttpKernel Component",
|
"description": "Symfony HttpKernel Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-28 17:33:53"
|
"time": "2014-11-03 20:15:26"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "symfony/process",
|
|
||||||
"version": "v2.5.5",
|
|
||||||
"target-dir": "Symfony/Component/Process",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/symfony/Process.git",
|
|
||||||
"reference": "8a1ec96c4e519cee0fb971ea48a1eb7369dda54b"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/symfony/Process/zipball/8a1ec96c4e519cee0fb971ea48a1eb7369dda54b",
|
|
||||||
"reference": "8a1ec96c4e519cee0fb971ea48a1eb7369dda54b",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.3"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "2.5-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-0": {
|
|
||||||
"Symfony\\Component\\Process\\": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Symfony Community",
|
|
||||||
"homepage": "http://symfony.com/contributors"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Symfony Process Component",
|
|
||||||
"homepage": "http://symfony.com",
|
|
||||||
"time": "2014-09-23 05:25:11"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/routing",
|
"name": "symfony/routing",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/Routing",
|
"target-dir": "Symfony/Component/Routing",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Routing.git",
|
"url": "https://github.com/symfony/Routing.git",
|
||||||
"reference": "9bc38fe72e0eff61611e7cd4df3accbce20b1d36"
|
"reference": "f0bb6f818f9a7ece41c7dfe14e08b13c2de55b0c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Routing/zipball/9bc38fe72e0eff61611e7cd4df3accbce20b1d36",
|
"url": "https://api.github.com/repos/symfony/Routing/zipball/f0bb6f818f9a7ece41c7dfe14e08b13c2de55b0c",
|
||||||
"reference": "9bc38fe72e0eff61611e7cd4df3accbce20b1d36",
|
"reference": "f0bb6f818f9a7ece41c7dfe14e08b13c2de55b0c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -2118,7 +2076,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -2148,21 +2106,21 @@
|
||||||
"uri",
|
"uri",
|
||||||
"url"
|
"url"
|
||||||
],
|
],
|
||||||
"time": "2014-09-22 15:28:36"
|
"time": "2014-11-03 19:16:49"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/serializer",
|
"name": "symfony/serializer",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/Serializer",
|
"target-dir": "Symfony/Component/Serializer",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Serializer.git",
|
"url": "https://github.com/symfony/Serializer.git",
|
||||||
"reference": "a95c0471682778da2e02169fb2644d3b08d4470f"
|
"reference": "e96b7ac54b3d75a458f76eab11b7cd2d757f09f1"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Serializer/zipball/a95c0471682778da2e02169fb2644d3b08d4470f",
|
"url": "https://api.github.com/repos/symfony/Serializer/zipball/e96b7ac54b3d75a458f76eab11b7cd2d757f09f1",
|
||||||
"reference": "a95c0471682778da2e02169fb2644d3b08d4470f",
|
"reference": "e96b7ac54b3d75a458f76eab11b7cd2d757f09f1",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -2171,7 +2129,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -2195,21 +2153,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Serializer Component",
|
"description": "Symfony Serializer Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-22 09:14:18"
|
"time": "2014-11-03 03:55:50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/translation",
|
"name": "symfony/translation",
|
||||||
"version": "v2.5.5",
|
"version": "v2.5.6",
|
||||||
"target-dir": "Symfony/Component/Translation",
|
"target-dir": "Symfony/Component/Translation",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Translation.git",
|
"url": "https://github.com/symfony/Translation.git",
|
||||||
"reference": "170c0d895616e1a6a35681ffb0b9e339f58ab928"
|
"reference": "362fe4da2cfe587f72d57aaa2f89e6b61c05dedf"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Translation/zipball/170c0d895616e1a6a35681ffb0b9e339f58ab928",
|
"url": "https://api.github.com/repos/symfony/Translation/zipball/362fe4da2cfe587f72d57aaa2f89e6b61c05dedf",
|
||||||
"reference": "170c0d895616e1a6a35681ffb0b9e339f58ab928",
|
"reference": "362fe4da2cfe587f72d57aaa2f89e6b61c05dedf",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -2251,21 +2209,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Translation Component",
|
"description": "Symfony Translation Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-23 05:25:11"
|
"time": "2014-10-01 05:50:18"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/validator",
|
"name": "symfony/validator",
|
||||||
"version": "v2.5.5",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/Validator",
|
"target-dir": "Symfony/Component/Validator",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Validator.git",
|
"url": "https://github.com/symfony/Validator.git",
|
||||||
"reference": "64f61505843ca5e6c647244f5a4b6812c1279427"
|
"reference": "6e521cdbc963cef7daf9931a7bde48b56d67d10a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Validator/zipball/64f61505843ca5e6c647244f5a4b6812c1279427",
|
"url": "https://api.github.com/repos/symfony/Validator/zipball/6e521cdbc963cef7daf9931a7bde48b56d67d10a",
|
||||||
"reference": "64f61505843ca5e6c647244f5a4b6812c1279427",
|
"reference": "6e521cdbc963cef7daf9931a7bde48b56d67d10a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -2297,7 +2255,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -2321,21 +2279,21 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Validator Component",
|
"description": "Symfony Validator Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-09-28 15:22:14"
|
"time": "2014-11-03 03:55:50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "dev-master",
|
"version": "v2.6.0-BETA1",
|
||||||
"target-dir": "Symfony/Component/Yaml",
|
"target-dir": "Symfony/Component/Yaml",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Yaml.git",
|
"url": "https://github.com/symfony/Yaml.git",
|
||||||
"reference": "499f7d7aa96747ad97940089bd7a1fb24ad8182a"
|
"reference": "9da3813f36985a4089f7e83c601a1034d125ff69"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/499f7d7aa96747ad97940089bd7a1fb24ad8182a",
|
"url": "https://api.github.com/repos/symfony/Yaml/zipball/9da3813f36985a4089f7e83c601a1034d125ff69",
|
||||||
"reference": "499f7d7aa96747ad97940089bd7a1fb24ad8182a",
|
"reference": "9da3813f36985a4089f7e83c601a1034d125ff69",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -2368,7 +2326,7 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Yaml Component",
|
"description": "Symfony Yaml Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-10-05 13:53:50"
|
"time": "2014-11-03 03:55:50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
|
|
@ -2564,7 +2522,17 @@
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": {
|
"stability-flags": {
|
||||||
"symfony/yaml": 20,
|
"symfony/class-loader": 10,
|
||||||
|
"symfony/css-selector": 10,
|
||||||
|
"symfony/debug": 10,
|
||||||
|
"symfony/dependency-injection": 10,
|
||||||
|
"symfony/event-dispatcher": 10,
|
||||||
|
"symfony/http-foundation": 10,
|
||||||
|
"symfony/http-kernel": 10,
|
||||||
|
"symfony/routing": 10,
|
||||||
|
"symfony/serializer": 10,
|
||||||
|
"symfony/validator": 10,
|
||||||
|
"symfony/yaml": 10,
|
||||||
"doctrine/common": 20,
|
"doctrine/common": 20,
|
||||||
"phpunit/phpunit-mock-objects": 20
|
"phpunit/phpunit-mock-objects": 20
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -173,4 +173,30 @@ class CompiledRoute extends SymfonyCompiledRoute {
|
||||||
return $this->route->getRequirements();
|
return $this->route->getRequirements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function serialize() {
|
||||||
|
$data = unserialize(parent::serialize());
|
||||||
|
$data['fit'] = $this->fit;
|
||||||
|
$data['patternOutline'] = $this->patternOutline;
|
||||||
|
$data['numParts'] = $this->numParts;
|
||||||
|
|
||||||
|
return serialize($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function unserialize($serialized)
|
||||||
|
{
|
||||||
|
parent::unserialize($serialized);
|
||||||
|
$data = unserialize($serialized);
|
||||||
|
|
||||||
|
$this->fit = $data['fit'];
|
||||||
|
$this->patternOutline = $data['patternOutline'];
|
||||||
|
$this->numParts = $data['numParts'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ return array(
|
||||||
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
||||||
'Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'),
|
'Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'),
|
||||||
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
|
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
|
||||||
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
|
|
||||||
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
|
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
|
||||||
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
|
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
|
||||||
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
|
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,13 @@
|
||||||
EmailValidator [](https://travis-ci.org/egulias/EmailValidator) [](https://coveralls.io/r/egulias/EmailValidator?branch=master) [](https://insight.sensiolabs.com/projects/b18d473e-bd5a-4d88-a7b2-7aeaee0ebd7b)[](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master)
|
EmailValidator [](https://travis-ci.org/egulias/EmailValidator) [](https://coveralls.io/r/egulias/EmailValidator?branch=master) [](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)[](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master)
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
##Installation##
|
##Installation##
|
||||||
Install via composer. Add to your current compooser.json ```require``` key: ```"egulias/email-validator":"1.0.x-dev" ```
|
|
||||||
|
Run the command below to install via Composer
|
||||||
|
|
||||||
|
```shell
|
||||||
|
composer require egulias/email-validator
|
||||||
|
```
|
||||||
|
|
||||||
##Usage##
|
##Usage##
|
||||||
|
|
||||||
|
|
@ -24,7 +29,7 @@ More advanced example (returns detailed diagnostic error codes):
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use egulias\EmailValidator\EmailValidator;
|
use Egulias\EmailValidator\EmailValidator;
|
||||||
|
|
||||||
$validator = new EmailValidator;
|
$validator = new EmailValidator;
|
||||||
$email = 'dominic@sayers.cc';
|
$email = 'dominic@sayers.cc';
|
||||||
|
|
@ -46,6 +51,6 @@ As this is a port from another library and work, here are other people related t
|
||||||
* Josepf Bielawski [@stloyd](http://github.com/stloyd): For its first re-work of Dominic's lib
|
* Josepf Bielawski [@stloyd](http://github.com/stloyd): For its first re-work of Dominic's lib
|
||||||
* Dominic Sayers [@dominicsayers](http://github.com/dominicsayers): The original isemail function
|
* Dominic Sayers [@dominicsayers](http://github.com/dominicsayers): The original isemail function
|
||||||
|
|
||||||
##Licence##
|
##License##
|
||||||
Released under the MIT Licence attached with this code.
|
Released under the MIT License attached with this code.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
],
|
],
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.0.x-dev"
|
"dev-master": "1.3.x-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
{
|
{
|
||||||
"_readme": [
|
"_readme": [
|
||||||
"This file locks the dependencies of your project to a known state",
|
"This file locks the dependencies of your project to a known state",
|
||||||
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
|
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "cca347a6b95164b1121e034b95f824ec",
|
"hash": "9e9dff0cc08c7292600453e681201e13",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "doctrine/lexer",
|
"name": "doctrine/lexer",
|
||||||
|
|
@ -61,16 +62,16 @@
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "guzzle/guzzle",
|
"name": "guzzle/guzzle",
|
||||||
"version": "v3.9.1",
|
"version": "v3.9.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/guzzle/guzzle3.git",
|
"url": "https://github.com/guzzle/guzzle3.git",
|
||||||
"reference": "92d9934f2fca1da15178c91239576ae26e505e60"
|
"reference": "54991459675c1a2924122afbb0e5609ade581155"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/guzzle/guzzle3/zipball/92d9934f2fca1da15178c91239576ae26e505e60",
|
"url": "https://api.github.com/repos/guzzle/guzzle3/zipball/54991459675c1a2924122afbb0e5609ade581155",
|
||||||
"reference": "92d9934f2fca1da15178c91239576ae26e505e60",
|
"reference": "54991459675c1a2924122afbb0e5609ade581155",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -114,7 +115,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "3.8-dev"
|
"dev-master": "3.9-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -149,7 +150,7 @@
|
||||||
"rest",
|
"rest",
|
||||||
"web service"
|
"web service"
|
||||||
],
|
],
|
||||||
"time": "2014-05-07 17:04:22"
|
"time": "2014-08-11 04:32:36"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
|
|
@ -195,18 +196,18 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/satooshi/php-coveralls.git",
|
"url": "https://github.com/satooshi/php-coveralls.git",
|
||||||
"reference": "b7271847c84d160f5b0aae83e45c225e8ffc96f4"
|
"reference": "94389a0ebdb64857d6899b5e0254dffa99e5aa96"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/b7271847c84d160f5b0aae83e45c225e8ffc96f4",
|
"url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/94389a0ebdb64857d6899b5e0254dffa99e5aa96",
|
||||||
"reference": "b7271847c84d160f5b0aae83e45c225e8ffc96f4",
|
"reference": "94389a0ebdb64857d6899b5e0254dffa99e5aa96",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*",
|
||||||
"guzzle/guzzle": ">=3.0",
|
"guzzle/guzzle": ">=2.7",
|
||||||
"php": ">=5.3",
|
"php": ">=5.3",
|
||||||
"psr/log": "1.0.0",
|
"psr/log": "1.0.0",
|
||||||
"symfony/config": ">=2.0",
|
"symfony/config": ">=2.0",
|
||||||
|
|
@ -216,7 +217,7 @@
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"apigen/apigen": "2.8.*@stable",
|
"apigen/apigen": "2.8.*@stable",
|
||||||
"pdepend/pdepend": "dev-master",
|
"pdepend/pdepend": "dev-master as 2.0.0",
|
||||||
"phpmd/phpmd": "dev-master",
|
"phpmd/phpmd": "dev-master",
|
||||||
"phpunit/php-invoker": ">=1.1.0,<1.2.0",
|
"phpunit/php-invoker": ">=1.1.0,<1.2.0",
|
||||||
"phpunit/phpunit": "3.7.*@stable",
|
"phpunit/phpunit": "3.7.*@stable",
|
||||||
|
|
@ -262,21 +263,21 @@
|
||||||
"github",
|
"github",
|
||||||
"test"
|
"test"
|
||||||
],
|
],
|
||||||
"time": "2014-05-14 13:09:37"
|
"time": "2014-07-09 10:45:38"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/config",
|
"name": "symfony/config",
|
||||||
"version": "v2.4.5",
|
"version": "v2.5.4",
|
||||||
"target-dir": "Symfony/Component/Config",
|
"target-dir": "Symfony/Component/Config",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Config.git",
|
"url": "https://github.com/symfony/Config.git",
|
||||||
"reference": "2effc67af6f21a0d267210b72d0b0b691d113528"
|
"reference": "080eabdc256c1d7a3a7cf6296271edb68eb1ab2b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Config/zipball/2effc67af6f21a0d267210b72d0b0b691d113528",
|
"url": "https://api.github.com/repos/symfony/Config/zipball/080eabdc256c1d7a3a7cf6296271edb68eb1ab2b",
|
||||||
"reference": "2effc67af6f21a0d267210b72d0b0b691d113528",
|
"reference": "080eabdc256c1d7a3a7cf6296271edb68eb1ab2b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -286,7 +287,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.4-dev"
|
"dev-master": "2.5-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -299,49 +300,49 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com",
|
|
||||||
"homepage": "http://fabien.potencier.org",
|
|
||||||
"role": "Lead Developer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Symfony Community",
|
"name": "Symfony Community",
|
||||||
"homepage": "http://symfony.com/contributors"
|
"homepage": "http://symfony.com/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Config Component",
|
"description": "Symfony Config Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-04-22 08:11:06"
|
"time": "2014-08-31 03:22:04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v2.4.5",
|
"version": "v2.5.4",
|
||||||
"target-dir": "Symfony/Component/Console",
|
"target-dir": "Symfony/Component/Console",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Console.git",
|
"url": "https://github.com/symfony/Console.git",
|
||||||
"reference": "24f723436e62598c9dddee2a8573d6992504dc5d"
|
"reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Console/zipball/24f723436e62598c9dddee2a8573d6992504dc5d",
|
"url": "https://api.github.com/repos/symfony/Console/zipball/748beed2a1e73179c3f5154d33fe6ae100c1aeb1",
|
||||||
"reference": "24f723436e62598c9dddee2a8573d6992504dc5d",
|
"reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"psr/log": "~1.0",
|
||||||
"symfony/event-dispatcher": "~2.1"
|
"symfony/event-dispatcher": "~2.1"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
"psr/log": "For using the console logger",
|
||||||
"symfony/event-dispatcher": ""
|
"symfony/event-dispatcher": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.4-dev"
|
"dev-master": "2.5-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -354,41 +355,42 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com",
|
|
||||||
"homepage": "http://fabien.potencier.org",
|
|
||||||
"role": "Lead Developer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Symfony Community",
|
"name": "Symfony Community",
|
||||||
"homepage": "http://symfony.com/contributors"
|
"homepage": "http://symfony.com/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-05-14 21:48:29"
|
"time": "2014-08-14 16:10:54"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v2.4.5",
|
"version": "v2.5.4",
|
||||||
"target-dir": "Symfony/Component/EventDispatcher",
|
"target-dir": "Symfony/Component/EventDispatcher",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/EventDispatcher.git",
|
"url": "https://github.com/symfony/EventDispatcher.git",
|
||||||
"reference": "e539602e5455aa086c0e81e604745af7789e4d8a"
|
"reference": "8faf5cc7e80fde74a650a36e60d32ce3c3e0457b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/e539602e5455aa086c0e81e604745af7789e4d8a",
|
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/8faf5cc7e80fde74a650a36e60d32ce3c3e0457b",
|
||||||
"reference": "e539602e5455aa086c0e81e604745af7789e4d8a",
|
"reference": "8faf5cc7e80fde74a650a36e60d32ce3c3e0457b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/dependency-injection": "~2.0"
|
"psr/log": "~1.0",
|
||||||
|
"symfony/config": "~2.0",
|
||||||
|
"symfony/dependency-injection": "~2.0",
|
||||||
|
"symfony/stopwatch": "~2.2"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/dependency-injection": "",
|
"symfony/dependency-injection": "",
|
||||||
|
|
@ -397,7 +399,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.4-dev"
|
"dev-master": "2.5-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -410,34 +412,32 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com",
|
|
||||||
"homepage": "http://fabien.potencier.org",
|
|
||||||
"role": "Lead Developer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Symfony Community",
|
"name": "Symfony Community",
|
||||||
"homepage": "http://symfony.com/contributors"
|
"homepage": "http://symfony.com/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony EventDispatcher Component",
|
"description": "Symfony EventDispatcher Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-04-16 10:34:31"
|
"time": "2014-07-28 13:20:46"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
"version": "v2.4.5",
|
"version": "v2.5.4",
|
||||||
"target-dir": "Symfony/Component/Filesystem",
|
"target-dir": "Symfony/Component/Filesystem",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Filesystem.git",
|
"url": "https://github.com/symfony/Filesystem.git",
|
||||||
"reference": "a3af8294bcce4a7c1b2892363b0c9d8109affad4"
|
"reference": "a765efd199e02ff4001c115c318e219030be9364"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/a3af8294bcce4a7c1b2892363b0c9d8109affad4",
|
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/a765efd199e02ff4001c115c318e219030be9364",
|
||||||
"reference": "a3af8294bcce4a7c1b2892363b0c9d8109affad4",
|
"reference": "a765efd199e02ff4001c115c318e219030be9364",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -446,7 +446,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.4-dev"
|
"dev-master": "2.5-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -459,34 +459,32 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com",
|
|
||||||
"homepage": "http://fabien.potencier.org",
|
|
||||||
"role": "Lead Developer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Symfony Community",
|
"name": "Symfony Community",
|
||||||
"homepage": "http://symfony.com/contributors"
|
"homepage": "http://symfony.com/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Filesystem Component",
|
"description": "Symfony Filesystem Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-04-16 10:34:31"
|
"time": "2014-09-03 09:00:14"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/stopwatch",
|
"name": "symfony/stopwatch",
|
||||||
"version": "v2.4.5",
|
"version": "v2.5.4",
|
||||||
"target-dir": "Symfony/Component/Stopwatch",
|
"target-dir": "Symfony/Component/Stopwatch",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Stopwatch.git",
|
"url": "https://github.com/symfony/Stopwatch.git",
|
||||||
"reference": "343bcc0360f2c22f371884b8f6a9fee8d1aa431a"
|
"reference": "22ab4f76cdeefd38b00022a6be5709190a2fd046"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Stopwatch/zipball/343bcc0360f2c22f371884b8f6a9fee8d1aa431a",
|
"url": "https://api.github.com/repos/symfony/Stopwatch/zipball/22ab4f76cdeefd38b00022a6be5709190a2fd046",
|
||||||
"reference": "343bcc0360f2c22f371884b8f6a9fee8d1aa431a",
|
"reference": "22ab4f76cdeefd38b00022a6be5709190a2fd046",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -495,7 +493,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.4-dev"
|
"dev-master": "2.5-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -508,34 +506,32 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com",
|
|
||||||
"homepage": "http://fabien.potencier.org",
|
|
||||||
"role": "Lead Developer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Symfony Community",
|
"name": "Symfony Community",
|
||||||
"homepage": "http://symfony.com/contributors"
|
"homepage": "http://symfony.com/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Stopwatch Component",
|
"description": "Symfony Stopwatch Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-04-18 20:37:09"
|
"time": "2014-08-14 16:10:54"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v2.4.5",
|
"version": "v2.5.4",
|
||||||
"target-dir": "Symfony/Component/Yaml",
|
"target-dir": "Symfony/Component/Yaml",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/Yaml.git",
|
"url": "https://github.com/symfony/Yaml.git",
|
||||||
"reference": "fd22bb88c3a6f73c898b39bec185a9e211b06265"
|
"reference": "01a7695bcfb013d0a15c6757e15aae120342986f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/Yaml/zipball/fd22bb88c3a6f73c898b39bec185a9e211b06265",
|
"url": "https://api.github.com/repos/symfony/Yaml/zipball/01a7695bcfb013d0a15c6757e15aae120342986f",
|
||||||
"reference": "fd22bb88c3a6f73c898b39bec185a9e211b06265",
|
"reference": "01a7695bcfb013d0a15c6757e15aae120342986f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -544,7 +540,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.4-dev"
|
"dev-master": "2.5-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -557,20 +553,18 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com",
|
|
||||||
"homepage": "http://fabien.potencier.org",
|
|
||||||
"role": "Lead Developer"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Symfony Community",
|
"name": "Symfony Community",
|
||||||
"homepage": "http://symfony.com/contributors"
|
"homepage": "http://symfony.com/contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Yaml Component",
|
"description": "Symfony Yaml Component",
|
||||||
"homepage": "http://symfony.com",
|
"homepage": "http://symfony.com",
|
||||||
"time": "2014-05-12 09:27:48"
|
"time": "2014-08-31 03:22:04"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aliases": [
|
"aliases": [
|
||||||
|
|
@ -580,6 +574,7 @@
|
||||||
"stability-flags": {
|
"stability-flags": {
|
||||||
"satooshi/php-coveralls": 20
|
"satooshi/php-coveralls": 20
|
||||||
},
|
},
|
||||||
|
"prefer-stable": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": ">= 5.3.3"
|
"php": ">= 5.3.3"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,13 @@ class EmailLexer extends AbstractLexer
|
||||||
const S_SEMICOLON = 275;
|
const S_SEMICOLON = 275;
|
||||||
const S_OPENQBRACKET = 276;
|
const S_OPENQBRACKET = 276;
|
||||||
const S_CLOSEQBRACKET = 277;
|
const S_CLOSEQBRACKET = 277;
|
||||||
|
const S_SLASH = 278;
|
||||||
const S_EMPTY = null;
|
const S_EMPTY = null;
|
||||||
const GENERIC = 300;
|
const GENERIC = 300;
|
||||||
const CRLF = 301;
|
const CRLF = 301;
|
||||||
const INVALID = 302;
|
const INVALID = 302;
|
||||||
|
const ASCII_INVALID_FROM = 127;
|
||||||
|
const ASCII_INVALID_TO = 199;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3)
|
* US-ASCII visible characters not valid for atext (@link http://tools.ietf.org/html/rfc5322#section-3.2.3)
|
||||||
|
|
@ -52,6 +55,7 @@ class EmailLexer extends AbstractLexer
|
||||||
';' => self::S_SEMICOLON,
|
';' => self::S_SEMICOLON,
|
||||||
'@' => self::S_AT,
|
'@' => self::S_AT,
|
||||||
'\\' => self::S_BACKSLASH,
|
'\\' => self::S_BACKSLASH,
|
||||||
|
'/' => self::S_SLASH,
|
||||||
',' => self::S_COMMA,
|
',' => self::S_COMMA,
|
||||||
'.' => self::S_DOT,
|
'.' => self::S_DOT,
|
||||||
'"' => self::S_DQUOTE,
|
'"' => self::S_DQUOTE,
|
||||||
|
|
@ -67,14 +71,31 @@ class EmailLexer extends AbstractLexer
|
||||||
'>' => self::S_GREATERTHAN,
|
'>' => self::S_GREATERTHAN,
|
||||||
'{' => self::S_OPENQBRACKET,
|
'{' => self::S_OPENQBRACKET,
|
||||||
'}' => self::S_CLOSEQBRACKET,
|
'}' => self::S_CLOSEQBRACKET,
|
||||||
'' => self::S_EMPTY
|
'' => self::S_EMPTY,
|
||||||
|
'\0' => self::C_NUL,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
protected $invalidASCII = array(226 => 1,);
|
||||||
|
|
||||||
|
protected $hasInvalidTokens = false;
|
||||||
|
|
||||||
protected $previous;
|
protected $previous;
|
||||||
|
|
||||||
|
public function reset()
|
||||||
|
{
|
||||||
|
$this->hasInvalidTokens = false;
|
||||||
|
parent::reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasInvalidTokens()
|
||||||
|
{
|
||||||
|
return $this->hasInvalidTokens;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @param $type
|
||||||
* @throws \UnexpectedValueException
|
* @throws \UnexpectedValueException
|
||||||
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function find($type)
|
public function find($type)
|
||||||
{
|
{
|
||||||
|
|
@ -100,7 +121,7 @@ class EmailLexer extends AbstractLexer
|
||||||
/**
|
/**
|
||||||
* moveNext
|
* moveNext
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function moveNext()
|
public function moveNext()
|
||||||
{
|
{
|
||||||
|
|
@ -112,7 +133,7 @@ class EmailLexer extends AbstractLexer
|
||||||
/**
|
/**
|
||||||
* Lexical catchable patterns.
|
* Lexical catchable patterns.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
protected function getCatchablePatterns()
|
protected function getCatchablePatterns()
|
||||||
{
|
{
|
||||||
|
|
@ -130,7 +151,7 @@ class EmailLexer extends AbstractLexer
|
||||||
/**
|
/**
|
||||||
* Lexical non-catchable patterns.
|
* Lexical non-catchable patterns.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
protected function getNonCatchablePatterns()
|
protected function getNonCatchablePatterns()
|
||||||
{
|
{
|
||||||
|
|
@ -146,14 +167,48 @@ class EmailLexer extends AbstractLexer
|
||||||
*/
|
*/
|
||||||
protected function getType(&$value)
|
protected function getType(&$value)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if ($this->isNullType($value)) {
|
||||||
|
return self::C_NUL;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($this->charValue[$value])) {
|
if (isset($this->charValue[$value])) {
|
||||||
return $this->charValue[$value];
|
return $this->charValue[$value];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match('/[\x10-\x1F]+/', $value)) {
|
if ($this->isInvalid($value)) {
|
||||||
|
$this->hasInvalidTokens = true;
|
||||||
return self::INVALID;
|
return self::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::GENERIC;
|
return self::GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
protected function isNullType($value)
|
||||||
|
{
|
||||||
|
if ($value === "\0") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
protected function isInvalid($value)
|
||||||
|
{
|
||||||
|
if (preg_match('/[\x10-\x1F]+/', $value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->invalidASCII[ord($value)])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ class EmailParser
|
||||||
$this->domainPartParser = new DomainPart($this->lexer);
|
$this->domainPartParser = new DomainPart($this->lexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*/
|
||||||
public function parse($str)
|
public function parse($str)
|
||||||
{
|
{
|
||||||
$this->lexer->setInput($str);
|
$this->lexer->setInput($str);
|
||||||
|
|
@ -36,6 +39,10 @@ class EmailParser
|
||||||
throw new \InvalidArgumentException('ERR_NOLOCALPART');
|
throw new \InvalidArgumentException('ERR_NOLOCALPART');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->lexer->hasInvalidTokens()) {
|
||||||
|
throw new \InvalidArgumentException('ERR_INVALID_ATEXT');
|
||||||
|
}
|
||||||
|
|
||||||
$this->localPartParser->parse($str);
|
$this->localPartParser->parse($str);
|
||||||
$this->domainPartParser->parse($str);
|
$this->domainPartParser->parse($str);
|
||||||
|
|
||||||
|
|
@ -78,6 +85,10 @@ class EmailParser
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $localPart
|
||||||
|
* @param string $parsedDomainPart
|
||||||
|
*/
|
||||||
protected function addLongEmailWarning($localPart, $parsedDomainPart)
|
protected function addLongEmailWarning($localPart, $parsedDomainPart)
|
||||||
{
|
{
|
||||||
if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) {
|
if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Egulias\EmailValidator;
|
namespace Egulias\EmailValidator;
|
||||||
|
|
||||||
use Egulias\EmailValidator\Parser\LocalPart;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EmailValidator
|
* EmailValidator
|
||||||
*
|
*
|
||||||
|
|
@ -97,7 +95,7 @@ class EmailValidator
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($strict) ? (!$this->hasWarnings() && $dns) : true;
|
return !$strict || (!$this->hasWarnings() && $dns);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -146,16 +144,9 @@ class EmailValidator
|
||||||
|
|
||||||
protected function checkDNS()
|
protected function checkDNS()
|
||||||
{
|
{
|
||||||
$checked = false;
|
$checked = true;
|
||||||
if (!function_exists('dns_get_record') && (
|
|
||||||
in_array(self::DNSWARN_NO_RECORD, $this->warnings) &&
|
|
||||||
in_array(self::DNSWARN_NO_MX_RECORD, $this->warnings)
|
|
||||||
)) {
|
|
||||||
return $checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = checkdnsrr(trim($this->parser->getParsedDomainPart()), 'MX');
|
$result = checkdnsrr(trim($this->parser->getParsedDomainPart()), 'MX');
|
||||||
$checked = true;
|
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
$this->warnings[] = self::DNSWARN_NO_RECORD;
|
$this->warnings[] = self::DNSWARN_NO_RECORD;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ class DomainPart extends Parser
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_EMPTY) {
|
if ($this->lexer->token['type'] === EmailLexer::S_EMPTY) {
|
||||||
throw new \InvalidArgumentException('ERR_NODOMAIN');
|
throw new \InvalidArgumentException('ERR_NODOMAIN');
|
||||||
}
|
}
|
||||||
|
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
|
||||||
|
throw new \InvalidArgumentException('ERR_DOMAINHYPHENEND');
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||||
$this->warnings[] = EmailValidator::DEPREC_COMMENT;
|
$this->warnings[] = EmailValidator::DEPREC_COMMENT;
|
||||||
|
|
@ -103,6 +106,10 @@ class DomainPart extends Parser
|
||||||
do {
|
do {
|
||||||
$prev = $this->lexer->getPrevious();
|
$prev = $this->lexer->getPrevious();
|
||||||
|
|
||||||
|
if ($this->lexer->token['type'] === EmailLexer::S_SLASH) {
|
||||||
|
throw new \InvalidArgumentException('ERR_DOMAIN_CHAR_NOT_ALLOWED');
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||||
$this->parseComments();
|
$this->parseComments();
|
||||||
$this->lexer->moveNext();
|
$this->lexer->moveNext();
|
||||||
|
|
@ -210,6 +217,9 @@ class DomainPart extends Parser
|
||||||
return $addressLiteral;
|
return $addressLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $addressLiteral
|
||||||
|
*/
|
||||||
protected function checkIPV4Tag($addressLiteral)
|
protected function checkIPV4Tag($addressLiteral)
|
||||||
{
|
{
|
||||||
$matchesIP = array();
|
$matchesIP = array();
|
||||||
|
|
@ -295,5 +305,4 @@ class DomainPart extends Parser
|
||||||
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace Egulias\EmailValidator\Parser;
|
||||||
|
|
||||||
use Egulias\EmailValidator\EmailLexer;
|
use Egulias\EmailValidator\EmailLexer;
|
||||||
use Egulias\EmailValidator\EmailValidator;
|
use Egulias\EmailValidator\EmailValidator;
|
||||||
|
use \InvalidArgumentException;
|
||||||
|
|
||||||
|
|
||||||
class LocalPart extends Parser
|
class LocalPart extends Parser
|
||||||
|
|
@ -21,8 +22,7 @@ class LocalPart extends Parser
|
||||||
|
|
||||||
$closingQuote = $this->checkDQUOTE($closingQuote);
|
$closingQuote = $this->checkDQUOTE($closingQuote);
|
||||||
if ($closingQuote && $parseDQuote) {
|
if ($closingQuote && $parseDQuote) {
|
||||||
$this->parseDoubleQuote();
|
$parseDQuote = $this->parseDoubleQuote();
|
||||||
$parseDQuote = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
|
||||||
|
|
@ -56,23 +56,51 @@ class LocalPart extends Parser
|
||||||
|
|
||||||
protected function parseDoubleQuote()
|
protected function parseDoubleQuote()
|
||||||
{
|
{
|
||||||
$special = array (
|
$parseAgain = true;
|
||||||
|
$special = array(
|
||||||
EmailLexer::S_CR => true,
|
EmailLexer::S_CR => true,
|
||||||
EmailLexer::S_HTAB => true,
|
EmailLexer::S_HTAB => true,
|
||||||
EmailLexer::S_LF => true
|
EmailLexer::S_LF => true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$invalid = array(
|
||||||
|
EmailLexer::C_NUL => true,
|
||||||
|
EmailLexer::S_HTAB => true,
|
||||||
|
EmailLexer::S_CR => true,
|
||||||
|
EmailLexer::S_LF => true
|
||||||
|
);
|
||||||
$setSpecialsWarning = true;
|
$setSpecialsWarning = true;
|
||||||
|
|
||||||
$this->lexer->moveNext();
|
$this->lexer->moveNext();
|
||||||
|
|
||||||
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && $this->lexer->token) {
|
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && $this->lexer->token) {
|
||||||
|
$parseAgain = false;
|
||||||
if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) {
|
if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) {
|
||||||
$this->warnings[] = EmailValidator::CFWS_FWS;
|
$this->warnings[] = EmailValidator::CFWS_FWS;
|
||||||
$setSpecialsWarning = false;
|
$setSpecialsWarning = false;
|
||||||
}
|
}
|
||||||
$this->lexer->moveNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$this->lexer->moveNext();
|
||||||
|
|
||||||
|
if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) {
|
||||||
|
throw new InvalidArgumentException("ERR_EXPECTED_ATEXT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$prev = $this->lexer->getPrevious();
|
||||||
|
|
||||||
|
if ($prev['type'] === EmailLexer::S_BACKSLASH) {
|
||||||
|
if (!$this->checkDQUOTE(false)) {
|
||||||
|
throw new \InvalidArgumentException("ERR_UNCLOSED_DQUOTE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) {
|
||||||
|
throw new \InvalidArgumentException("ERR_EXPECED_AT");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parseAgain;
|
||||||
|
}
|
||||||
|
|
||||||
protected function isInvalidToken($token, $closingQuote)
|
protected function isInvalidToken($token, $closingQuote)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -124,8 +124,7 @@ abstract class Parser
|
||||||
|
|
||||||
if ($previous['type'] === EmailLexer::S_BACKSLASH
|
if ($previous['type'] === EmailLexer::S_BACKSLASH
|
||||||
&&
|
&&
|
||||||
($this->lexer->token['type'] === EmailLexer::S_SP ||
|
$this->lexer->token['type'] !== EmailLexer::GENERIC
|
||||||
$this->lexer->token['type'] === EmailLexer::S_HTAB)
|
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -164,6 +163,7 @@ abstract class Parser
|
||||||
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) {
|
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) {
|
||||||
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->warnings[] = EmailValidator::RFC5321_QUOTEDSTRING;
|
$this->warnings[] = EmailValidator::RFC5321_QUOTEDSTRING;
|
||||||
try {
|
try {
|
||||||
$this->lexer->find(EmailLexer::S_DQUOTE);
|
$this->lexer->find(EmailLexer::S_DQUOTE);
|
||||||
|
|
@ -187,4 +187,4 @@ abstract class Parser
|
||||||
throw new \InvalidArgumentException("ERR_FWS_CRLF_END");
|
throw new \InvalidArgumentException("ERR_FWS_CRLF_END");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,15 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertTrue($lexer->find(EmailLexer::S_HTAB));
|
$this->assertTrue($lexer->find(EmailLexer::S_HTAB));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testLexerHasInvalidTokens()
|
||||||
|
{
|
||||||
|
$lexer = new EmailLexer();
|
||||||
|
$lexer->setInput(chr(226));
|
||||||
|
$lexer->moveNext();
|
||||||
|
$lexer->moveNext();
|
||||||
|
$this->assertTrue($lexer->hasInvalidTokens());
|
||||||
|
}
|
||||||
|
|
||||||
public function getTokens()
|
public function getTokens()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
|
|
@ -61,6 +70,7 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
||||||
array("\"", EmailLexer::S_DQUOTE),
|
array("\"", EmailLexer::S_DQUOTE),
|
||||||
array("-", EmailLexer::S_HYPHEN),
|
array("-", EmailLexer::S_HYPHEN),
|
||||||
array("\\", EmailLexer::S_BACKSLASH),
|
array("\\", EmailLexer::S_BACKSLASH),
|
||||||
|
array("/", EmailLexer::S_SLASH),
|
||||||
array("(", EmailLexer::S_OPENPARENTHESIS),
|
array("(", EmailLexer::S_OPENPARENTHESIS),
|
||||||
array(")", EmailLexer::S_CLOSEPARENTHESIS),
|
array(")", EmailLexer::S_CLOSEPARENTHESIS),
|
||||||
array('<', EmailLexer::S_LOWERTHAN),
|
array('<', EmailLexer::S_LOWERTHAN),
|
||||||
|
|
@ -74,7 +84,9 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
||||||
array('{', EmailLexer::S_OPENQBRACKET),
|
array('{', EmailLexer::S_OPENQBRACKET),
|
||||||
array('}', EmailLexer::S_CLOSEQBRACKET),
|
array('}', EmailLexer::S_CLOSEQBRACKET),
|
||||||
array('', EmailLexer::S_EMPTY),
|
array('', EmailLexer::S_EMPTY),
|
||||||
array(chr(31), EmailLexer::INVALID)
|
array(chr(31), EmailLexer::INVALID),
|
||||||
|
array(chr(226), EmailLexer::INVALID),
|
||||||
|
array(chr(0), EmailLexer::C_NUL)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,10 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
array('"user,name"@example.com'),
|
array('"user,name"@example.com'),
|
||||||
array('"user name"@example.com'),
|
array('"user name"@example.com'),
|
||||||
array('"user@name"@example.com'),
|
array('"user@name"@example.com'),
|
||||||
|
array('"\a"@iana.org'),
|
||||||
|
array('"test\ test"@iana.org'),
|
||||||
|
array('""@iana.org'),
|
||||||
|
array('"\""@iana.org'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,9 +61,10 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
public function getInvalidEmails()
|
public function getInvalidEmails()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
|
|
||||||
array('example.@example.co.uk'),
|
array('example.@example.co.uk'),
|
||||||
array('example@example@example.co.uk'),
|
array('example@example@example.co.uk'),
|
||||||
array('(fabien_potencier@example.fr)'),
|
array('(test_exampel@example.fr)'),
|
||||||
array('example(example)example@example.co.uk'),
|
array('example(example)example@example.co.uk'),
|
||||||
array('.example@localhost'),
|
array('.example@localhost'),
|
||||||
array('ex\ample@localhost'),
|
array('ex\ample@localhost'),
|
||||||
|
|
@ -72,6 +77,27 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
array('username@example,com'),
|
array('username@example,com'),
|
||||||
array('usern,ame@example.com'),
|
array('usern,ame@example.com'),
|
||||||
array('user[na]me@example.com'),
|
array('user[na]me@example.com'),
|
||||||
|
array('"""@iana.org'),
|
||||||
|
array('"\"@iana.org'),
|
||||||
|
array('"test"test@iana.org'),
|
||||||
|
array('"test""test"@iana.org'),
|
||||||
|
array('"test"."test"@iana.org'),
|
||||||
|
array('"test".test@iana.org'),
|
||||||
|
array('"test"' . chr(0) . '@iana.org'),
|
||||||
|
array('"test\"@iana.org'),
|
||||||
|
array(chr(226) . '@iana.org'),
|
||||||
|
array('test@' . chr(226) . '.org'),
|
||||||
|
array('\r\ntest@iana.org'),
|
||||||
|
array('\r\n test@iana.org'),
|
||||||
|
array('\r\n \r\ntest@iana.org'),
|
||||||
|
array('\r\n \r\ntest@iana.org'),
|
||||||
|
array('\r\n \r\n test@iana.org'),
|
||||||
|
array('test@iana.org \r\n'),
|
||||||
|
array('test@iana.org \r\n '),
|
||||||
|
array('test@iana.org \r\n \r\n'),
|
||||||
|
array('test@iana.org \r\n\r\n'),
|
||||||
|
array('test@iana.org \r\n\r\n '),
|
||||||
|
array('test@iana/icann.org'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,6 +150,16 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals($warnings, $this->validator->getWarnings());
|
$this->assertEquals($warnings, $this->validator->getWarnings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getInvalidEmailsWithWarnings
|
||||||
|
*/
|
||||||
|
public function testInvalidEmailsWithDnsCheckAndStrictMode($warnings, $email)
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->validator->isValid($email, true, true));
|
||||||
|
|
||||||
|
$this->assertEquals($warnings, $this->validator->getWarnings());
|
||||||
|
}
|
||||||
|
|
||||||
public function getInvalidEmailsWithWarnings()
|
public function getInvalidEmailsWithWarnings()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
|
|
@ -275,6 +311,17 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
'parttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpart'.
|
'parttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpart'.
|
||||||
'toolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpar'
|
'toolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpar'
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
EmailValidator::DNSWARN_NO_RECORD,
|
||||||
|
),
|
||||||
|
'test@test'
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testInvalidEmailsWithStrict()
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->validator->isValid('"test"@test', false, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 1.0.3 - 2014-11-03
|
||||||
|
|
||||||
|
* Setting the `header` stream option as a string to be compatible with GAE.
|
||||||
|
* Header parsing now ensures that header order is maintained in the parsed
|
||||||
|
message.
|
||||||
|
|
||||||
|
## 1.0.2 - 2014-10-28
|
||||||
|
|
||||||
|
* Now correctly honoring a `version` option is supplied in a request.
|
||||||
|
See https://github.com/guzzle/RingPHP/pull/8
|
||||||
|
|
||||||
|
## 1.0.1 - 2014-10-26
|
||||||
|
|
||||||
|
* Fixed a header parsing issue with the `CurlHandler` and `CurlMultiHandler`
|
||||||
|
that caused cURL requests with multiple responses to merge repsonses together
|
||||||
|
(e.g., requests with digest authentication).
|
||||||
|
|
||||||
|
## 1.0.0 - 2014-10-12
|
||||||
|
|
||||||
|
* Initial release.
|
||||||
|
|
@ -2,13 +2,45 @@
|
||||||
RingPHP
|
RingPHP
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Provides low level APIs used to power HTTP clients and servers through a
|
Provides a simple API and specification that abstracts away the details of HTTP
|
||||||
simple, PHP ``callable`` that accepts a request hash and returns a future
|
into a single PHP function. RingPHP be used to power HTTP clients and servers
|
||||||
response hash. RingPHP supports both synchronous and asynchronous
|
through a PHP function that accepts a request hash and returns a response hash
|
||||||
workflows by utilizing both futures and `promises <https://github.com/reactphp/promise>`_.
|
that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
|
||||||
|
allowing RingPHP to support both synchronous and asynchronous workflows.
|
||||||
|
|
||||||
|
By abstracting the implementation details of different HTTP clients and
|
||||||
|
servers, RingPHP allows you to utilize pluggable HTTP clients and servers
|
||||||
|
without tying your application to a specific implementation.
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
|
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||||
|
|
||||||
|
$handler = new CurlHandler();
|
||||||
|
$response = $handler([
|
||||||
|
'http_method' => 'GET',
|
||||||
|
'uri' => '/',
|
||||||
|
'headers' => [
|
||||||
|
'host' => ['www.google.com'],
|
||||||
|
'x-foo' => ['baz']
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->then(function (array $response) {
|
||||||
|
echo $response['status'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$response->wait();
|
||||||
|
|
||||||
RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
|
RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
|
||||||
but has been modified to accommodate clients and servers for both blocking
|
which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
|
||||||
and non-blocking requests.
|
utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
|
||||||
|
HTTP requests.
|
||||||
|
|
||||||
See http://guzzle-ring.readthedocs.org/ for the full online documentation.
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
See http://ringphp.readthedocs.org/ for the full online documentation.
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,49 @@
|
||||||
RingPHP
|
RingPHP
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Provides low level APIs used to power HTTP clients and servers through a
|
Provides a simple API and specification that abstracts away the details of HTTP
|
||||||
simple, PHP ``callable`` that accepts a request hash and returns a future
|
into a single PHP function. RingPHP be used to power HTTP clients and servers
|
||||||
response hash. RingPHP supports both synchronous and asynchronous
|
through a PHP function that accepts a request hash and returns a response hash
|
||||||
workflows by utilizing both futures and `promises <https://github.com/reactphp/promise>`_.
|
that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
|
||||||
|
allowing RingPHP to support both synchronous and asynchronous workflows.
|
||||||
|
|
||||||
RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
|
By abstracting the implementation details of different HTTP clients and
|
||||||
but has been modified to accommodate clients and servers for both blocking
|
servers, RingPHP allows you to utilize pluggable HTTP clients and servers
|
||||||
and non-blocking requests.
|
without tying your application to a specific implementation.
|
||||||
|
|
||||||
RingPHP is utilized as the handler layer in
|
|
||||||
`Guzzle <http://guzzlephp.org>`_ 5.0+ to send HTTP requests.
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 2
|
||||||
|
|
||||||
spec
|
spec
|
||||||
futures
|
futures
|
||||||
client_middleware
|
client_middleware
|
||||||
client_handlers
|
client_handlers
|
||||||
testing
|
testing
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
|
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||||
|
|
||||||
|
$handler = new CurlHandler();
|
||||||
|
$response = $handler([
|
||||||
|
'http_method' => 'GET',
|
||||||
|
'uri' => '/',
|
||||||
|
'headers' => [
|
||||||
|
'host' => ['www.google.com'],
|
||||||
|
'x-foo' => ['baz']
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->then(function (array $response) {
|
||||||
|
echo $response['status'];
|
||||||
|
});
|
||||||
|
|
||||||
|
$response->wait();
|
||||||
|
|
||||||
|
RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
|
||||||
|
which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
|
||||||
|
utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
|
||||||
|
HTTP requests.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ middleware.
|
||||||
Handlers
|
Handlers
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Handlers are implemented as a PHP ``callable`` that accept a request array and
|
Handlers are implemented as a PHP ``callable`` that accept a request array
|
||||||
and return a response array (``GuzzleHttp\Ring\Future\FutureArrayInterface``).
|
and return a response array (``GuzzleHttp\Ring\Future\FutureArrayInterface``).
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
|
||||||
|
|
@ -76,20 +76,17 @@ class CurlFactory
|
||||||
$response['effective_url'] = $response['transfer_stats']['url'];
|
$response['effective_url'] = $response['transfer_stats']['url'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($headers[0])) {
|
if (!empty($headers)) {
|
||||||
$startLine = explode(' ', array_shift($headers), 3);
|
$startLine = explode(' ', array_shift($headers), 3);
|
||||||
// Trim out 100-Continue start-lines
|
$headerList = Core::headersFromLines($headers);
|
||||||
if ($startLine[1] == '100') {
|
$response['headers'] = $headerList;
|
||||||
$startLine = explode(' ', array_shift($headers), 3);
|
|
||||||
}
|
|
||||||
$response['headers'] = Core::headersFromLines($headers);
|
|
||||||
$response['status'] = isset($startLine[1]) ? (int) $startLine[1] : null;
|
$response['status'] = isset($startLine[1]) ? (int) $startLine[1] : null;
|
||||||
$response['reason'] = isset($startLine[2]) ? $startLine[2] : null;
|
$response['reason'] = isset($startLine[2]) ? $startLine[2] : null;
|
||||||
$response['body'] = $body;
|
$response['body'] = $body;
|
||||||
Core::rewindBody($response);
|
Core::rewindBody($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !empty($response['curl']['errno']) || !isset($startLine[1])
|
return !empty($response['curl']['errno']) || !isset($response['status'])
|
||||||
? self::createErrorResponse($handler, $request, $response)
|
? self::createErrorResponse($handler, $request, $response)
|
||||||
: $response;
|
: $response;
|
||||||
}
|
}
|
||||||
|
|
@ -159,6 +156,7 @@ class CurlFactory
|
||||||
private function getDefaultOptions(array $request, array &$headers)
|
private function getDefaultOptions(array $request, array &$headers)
|
||||||
{
|
{
|
||||||
$url = Core::url($request);
|
$url = Core::url($request);
|
||||||
|
$startingResponse = false;
|
||||||
|
|
||||||
$options = [
|
$options = [
|
||||||
'_headers' => $request['headers'],
|
'_headers' => $request['headers'],
|
||||||
|
|
@ -167,15 +165,24 @@ class CurlFactory
|
||||||
CURLOPT_RETURNTRANSFER => false,
|
CURLOPT_RETURNTRANSFER => false,
|
||||||
CURLOPT_HEADER => false,
|
CURLOPT_HEADER => false,
|
||||||
CURLOPT_CONNECTTIMEOUT => 150,
|
CURLOPT_CONNECTTIMEOUT => 150,
|
||||||
CURLOPT_HEADERFUNCTION => function ($ch, $h) use (&$headers) {
|
CURLOPT_HEADERFUNCTION => function ($ch, $h) use (&$headers, &$startingResponse) {
|
||||||
$length = strlen($h);
|
$value = trim($h);
|
||||||
if ($value = trim($h)) {
|
if ($value === '') {
|
||||||
$headers[] = trim($h);
|
$startingResponse = true;
|
||||||
|
} elseif ($startingResponse) {
|
||||||
|
$startingResponse = false;
|
||||||
|
$headers = [$value];
|
||||||
|
} else {
|
||||||
|
$headers[] = $value;
|
||||||
}
|
}
|
||||||
return $length;
|
return strlen($h);
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (isset($request['version'])) {
|
||||||
|
$options[CURLOPT_HTTP_VERSION] = $request['version'] == 1.1 ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
|
||||||
|
}
|
||||||
|
|
||||||
if (defined('CURLOPT_PROTOCOLS')) {
|
if (defined('CURLOPT_PROTOCOLS')) {
|
||||||
$options[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
$options[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -214,10 +214,10 @@ class StreamHandler
|
||||||
|
|
||||||
private function getDefaultOptions(array $request)
|
private function getDefaultOptions(array $request)
|
||||||
{
|
{
|
||||||
$headers = [];
|
$headers = "";
|
||||||
foreach ($request['headers'] as $name => $value) {
|
foreach ($request['headers'] as $name => $value) {
|
||||||
foreach ((array) $value as $val) {
|
foreach ((array) $value as $val) {
|
||||||
$headers[] = "$name: $val";
|
$headers .= "$name: $val\r\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,7 +225,7 @@ class StreamHandler
|
||||||
'http' => [
|
'http' => [
|
||||||
'method' => $request['http_method'],
|
'method' => $request['http_method'],
|
||||||
'header' => $headers,
|
'header' => $headers,
|
||||||
'protocol_version' => '1.1',
|
'protocol_version' => isset($request['version']) ? $request['version'] : 1.1,
|
||||||
'ignore_errors' => true,
|
'ignore_errors' => true,
|
||||||
'follow_location' => 0,
|
'follow_location' => 0,
|
||||||
],
|
],
|
||||||
|
|
@ -236,10 +236,12 @@ class StreamHandler
|
||||||
$context['http']['content'] = $body;
|
$context['http']['content'] = $body;
|
||||||
// Prevent the HTTP handler from adding a Content-Type header.
|
// Prevent the HTTP handler from adding a Content-Type header.
|
||||||
if (!Core::hasHeader($request, 'Content-Type')) {
|
if (!Core::hasHeader($request, 'Content-Type')) {
|
||||||
$context['http']['header'][] .= "Content-Type:";
|
$context['http']['header'] .= "Content-Type:\r\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$context['http']['header'] = rtrim($context['http']['header']);
|
||||||
|
|
||||||
return $context;
|
return $context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,24 +41,17 @@ class Core
|
||||||
*/
|
*/
|
||||||
public static function headerLines($message, $header)
|
public static function headerLines($message, $header)
|
||||||
{
|
{
|
||||||
// Slight optimization for exact matches.
|
$result = [];
|
||||||
if (isset($message['headers'][$header])) {
|
|
||||||
return $message['headers'][$header];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for message with no headers after the "fast" isset check.
|
if (!empty($message['headers'])) {
|
||||||
if (!isset($message['headers'])) {
|
foreach ($message['headers'] as $name => $value) {
|
||||||
return [];
|
if (!strcasecmp($name, $header)) {
|
||||||
}
|
$result = array_merge($result, $value);
|
||||||
|
}
|
||||||
// Iterate and case-insensitively find the header by name.
|
|
||||||
foreach ($message['headers'] as $name => $value) {
|
|
||||||
if (!strcasecmp($name, $header)) {
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,18 +84,17 @@ class Core
|
||||||
*/
|
*/
|
||||||
public static function firstHeader($message, $header)
|
public static function firstHeader($message, $header)
|
||||||
{
|
{
|
||||||
$match = self::headerLines($message, $header);
|
if (!empty($message['headers'])) {
|
||||||
|
foreach ($message['headers'] as $name => $value) {
|
||||||
if (!isset($match[0])) {
|
if (!strcasecmp($name, $header)) {
|
||||||
return null;
|
// Return the match itself if it is a single value.
|
||||||
|
$pos = strpos($value[0], ',');
|
||||||
|
return $pos ? substr($value[0], 0, $pos) : $value[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the match itself if it is a single value.
|
return null;
|
||||||
if (!($pos = strpos($match[0], ','))) {
|
|
||||||
return $match[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return substr($match[0], 0, $pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -115,7 +107,15 @@ class Core
|
||||||
*/
|
*/
|
||||||
public static function hasHeader($message, $header)
|
public static function hasHeader($message, $header)
|
||||||
{
|
{
|
||||||
return (bool) self::headerLines($message, $header);
|
if (!empty($message['headers'])) {
|
||||||
|
foreach ($message['headers'] as $name => $value) {
|
||||||
|
if (!strcasecmp($name, $header)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,7 @@ trait BaseFutureTrait
|
||||||
private $isRealized = false;
|
private $isRealized = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param PromiseInterface $promise Promise to shadow with the future. Only
|
* @param PromiseInterface $promise Promise to shadow with the future.
|
||||||
* supply if the promise is not owned
|
|
||||||
* by the deferred value.
|
|
||||||
* @param callable $wait Function that blocks until the deferred
|
* @param callable $wait Function that blocks until the deferred
|
||||||
* computation has been resolved. This
|
* computation has been resolved. This
|
||||||
* function MUST resolve the deferred value
|
* function MUST resolve the deferred value
|
||||||
|
|
|
||||||
|
|
@ -404,6 +404,19 @@ class CurlFactoryTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals($content, Core::body($response));
|
$this->assertEquals($content, Core::body($response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testProtocolVersion()
|
||||||
|
{
|
||||||
|
Server::flush();
|
||||||
|
Server::enqueue([['status' => 200]]);
|
||||||
|
$a = new CurlMultiHandler();
|
||||||
|
$a([
|
||||||
|
'http_method' => 'GET',
|
||||||
|
'headers' => ['host' => [Server::$host]],
|
||||||
|
'version' => 1.0,
|
||||||
|
]);
|
||||||
|
$this->assertEquals(CURL_HTTP_VERSION_1_0, $_SERVER['_curl'][CURLOPT_HTTP_VERSION]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \InvalidArgumentException
|
* @expectedException \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
|
|
@ -570,7 +583,7 @@ class CurlFactoryTest extends \PHPUnit_Framework_TestCase
|
||||||
'http_method' => 'GET',
|
'http_method' => 'GET',
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'host' => [Server::$host],
|
'host' => [Server::$host],
|
||||||
'content-length' => 3,
|
'content-length' => [3],
|
||||||
],
|
],
|
||||||
'body' => 'foo',
|
'body' => 'foo',
|
||||||
]);
|
]);
|
||||||
|
|
@ -709,6 +722,71 @@ class CurlFactoryTest extends \PHPUnit_Framework_TestCase
|
||||||
);
|
);
|
||||||
$this->assertInstanceOf('GuzzleHttp\Ring\Exception\ConnectException', $response['error']);
|
$this->assertInstanceOf('GuzzleHttp\Ring\Exception\ConnectException', $response['error']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testParsesLastResponseOnly()
|
||||||
|
{
|
||||||
|
$response1 = [
|
||||||
|
'status' => 301,
|
||||||
|
'headers' => [
|
||||||
|
'Content-Length' => ['0'],
|
||||||
|
'Location' => ['/foo']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$response2 = [
|
||||||
|
'status' => 200,
|
||||||
|
'headers' => [
|
||||||
|
'Content-Length' => ['0'],
|
||||||
|
'Foo' => ['bar']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
Server::flush();
|
||||||
|
Server::enqueue([$response1, $response2]);
|
||||||
|
|
||||||
|
$a = new CurlMultiHandler();
|
||||||
|
$response = $a([
|
||||||
|
'http_method' => 'GET',
|
||||||
|
'headers' => ['Host' => [Server::$host]],
|
||||||
|
'client' => [
|
||||||
|
'curl' => [
|
||||||
|
CURLOPT_FOLLOWLOCATION => true
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])->wait();
|
||||||
|
|
||||||
|
$this->assertEquals(1, $response['transfer_stats']['redirect_count']);
|
||||||
|
$this->assertEquals('http://127.0.0.1:8125/foo', $response['effective_url']);
|
||||||
|
$this->assertEquals(['bar'], $response['headers']['Foo']);
|
||||||
|
$this->assertEquals(200, $response['status']);
|
||||||
|
$this->assertFalse(Core::hasHeader($response, 'Location'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMaintainsMultiHeaderOrder()
|
||||||
|
{
|
||||||
|
Server::flush();
|
||||||
|
Server::enqueue([
|
||||||
|
[
|
||||||
|
'status' => 200,
|
||||||
|
'headers' => [
|
||||||
|
'Content-Length' => ['0'],
|
||||||
|
'Foo' => ['a', 'b'],
|
||||||
|
'foo' => ['c', 'd'],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$a = new CurlMultiHandler();
|
||||||
|
$response = $a([
|
||||||
|
'http_method' => 'GET',
|
||||||
|
'headers' => ['Host' => [Server::$host]]
|
||||||
|
])->wait();
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
['a', 'b', 'c', 'd'],
|
||||||
|
Core::headerLines($response, 'Foo')
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,20 @@ class StreamHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertSame($content, Core::body($response));
|
$this->assertSame($content, Core::body($response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testProtocolVersion()
|
||||||
|
{
|
||||||
|
$this->queueRes();
|
||||||
|
$handler = new StreamHandler();
|
||||||
|
$handler([
|
||||||
|
'http_method' => 'GET',
|
||||||
|
'uri' => '/',
|
||||||
|
'headers' => ['host' => [Server::$host]],
|
||||||
|
'version' => 1.0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(1.0, Server::received()[0]['version']);
|
||||||
|
}
|
||||||
|
|
||||||
protected function getSendResult(array $opts)
|
protected function getSendResult(array $opts)
|
||||||
{
|
{
|
||||||
$this->queueRes();
|
$this->queueRes();
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,22 @@ class CoreTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertNull(Core::firstHeader([], 'Foo'));
|
$this->assertNull(Core::firstHeader([], 'Foo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testChecksIfHasHeader()
|
||||||
|
{
|
||||||
|
$message = [
|
||||||
|
'headers' => [
|
||||||
|
'Foo' => ['Bar', 'Baz'],
|
||||||
|
'foo' => ['hello'],
|
||||||
|
'bar' => ['1']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$this->assertTrue(Core::hasHeader($message, 'Foo'));
|
||||||
|
$this->assertTrue(Core::hasHeader($message, 'foo'));
|
||||||
|
$this->assertTrue(Core::hasHeader($message, 'FoO'));
|
||||||
|
$this->assertTrue(Core::hasHeader($message, 'bar'));
|
||||||
|
$this->assertFalse(Core::hasHeader($message, 'barr'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testReturnsFirstHeaderWhenSimple()
|
public function testReturnsFirstHeaderWhenSimple()
|
||||||
{
|
{
|
||||||
$this->assertEquals('Bar', Core::firstHeader([
|
$this->assertEquals('Bar', Core::firstHeader([
|
||||||
|
|
@ -37,6 +53,19 @@ class CoreTest extends \PHPUnit_Framework_TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testExtractsCaseInsensitiveHeaderLines()
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
['a', 'b', 'c', 'd'],
|
||||||
|
Core::headerLines([
|
||||||
|
'headers' => [
|
||||||
|
'foo' => ['a', 'b'],
|
||||||
|
'Foo' => ['c', 'd']
|
||||||
|
]
|
||||||
|
], 'foo')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testExtractsHeaderLines()
|
public function testExtractsHeaderLines()
|
||||||
{
|
{
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.1.x-dev"
|
"dev-master": "1.2.x-dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,4 +68,28 @@ class Console
|
||||||
|
|
||||||
return function_exists('posix_isatty') && @posix_isatty(STDOUT);
|
return function_exists('posix_isatty') && @posix_isatty(STDOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of columns of the terminal.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getNumberOfColumns()
|
||||||
|
{
|
||||||
|
// Windows terminals have a fixed size of 80
|
||||||
|
// but one column is used for the cursor.
|
||||||
|
if (DIRECTORY_SEPARATOR == '\\') {
|
||||||
|
return 79;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('#\d+ (\d+)#', shell_exec('stty size'), $match) === 1) {
|
||||||
|
return (int) $match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('#columns = (\d+);#', shell_exec('stty'), $match) === 1) {
|
||||||
|
return (int) $match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 80;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,14 @@ class ConsoleTest extends PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
public function testCanDetectColorSupport()
|
public function testCanDetectColorSupport()
|
||||||
{
|
{
|
||||||
$this->assertTrue($this->console->hasColorSupport());
|
$this->assertInternalType('boolean', $this->console->hasColorSupport());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \SebastianBergmann\Environment\Console::hasColorSupport
|
||||||
|
*/
|
||||||
|
public function testCanDetectNumberOfColumns()
|
||||||
|
{
|
||||||
|
$this->assertInternalType('integer', $this->console->getNumberOfColumns());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ namespace Symfony\Component\ClassLoader;
|
||||||
* // register classes with namespaces
|
* // register classes with namespaces
|
||||||
* $loader->registerNamespaces(array(
|
* $loader->registerNamespaces(array(
|
||||||
* 'Symfony\Component' => __DIR__.'/component',
|
* 'Symfony\Component' => __DIR__.'/component',
|
||||||
* 'Symfony' => __DIR__.'/framework',
|
* 'Symfony' => __DIR__.'/framework',
|
||||||
* 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
|
* 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
|
||||||
* ));
|
* ));
|
||||||
*
|
*
|
||||||
* // register a library using the PEAR naming convention
|
* // register a library using the PEAR naming convention
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class ClassLoader
|
||||||
*/
|
*/
|
||||||
public function setUseIncludePath($useIncludePath)
|
public function setUseIncludePath($useIncludePath)
|
||||||
{
|
{
|
||||||
$this->useIncludePath = $useIncludePath;
|
$this->useIncludePath = (bool) $useIncludePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ class ClassMapGenerator
|
||||||
private static function findClasses($path)
|
private static function findClasses($path)
|
||||||
{
|
{
|
||||||
$contents = file_get_contents($path);
|
$contents = file_get_contents($path);
|
||||||
$tokens = token_get_all($contents);
|
$tokens = token_get_all($contents);
|
||||||
|
|
||||||
$classes = array();
|
$classes = array();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,51 +9,63 @@ standard or the PEAR naming convention.
|
||||||
|
|
||||||
First, register the autoloader:
|
First, register the autoloader:
|
||||||
|
|
||||||
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
|
```php
|
||||||
|
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
|
||||||
|
|
||||||
use Symfony\Component\ClassLoader\UniversalClassLoader;
|
use Symfony\Component\ClassLoader\UniversalClassLoader;
|
||||||
|
|
||||||
$loader = new UniversalClassLoader();
|
$loader = new UniversalClassLoader();
|
||||||
$loader->register();
|
$loader->register();
|
||||||
|
```
|
||||||
|
|
||||||
Then, register some namespaces with the `registerNamespace()` method:
|
Then, register some namespaces with the `registerNamespace()` method:
|
||||||
|
|
||||||
$loader->registerNamespace('Symfony', __DIR__.'/src');
|
```php
|
||||||
$loader->registerNamespace('Monolog', __DIR__.'/vendor/monolog/src');
|
$loader->registerNamespace('Symfony', __DIR__.'/src');
|
||||||
|
$loader->registerNamespace('Monolog', __DIR__.'/vendor/monolog/src');
|
||||||
|
```
|
||||||
|
|
||||||
The `registerNamespace()` method takes a namespace prefix and a path where to
|
The `registerNamespace()` method takes a namespace prefix and a path where to
|
||||||
look for the classes as arguments.
|
look for the classes as arguments.
|
||||||
|
|
||||||
You can also register a sub-namespaces:
|
You can also register a sub-namespaces:
|
||||||
|
|
||||||
$loader->registerNamespace('Doctrine\\Common', __DIR__.'/vendor/doctrine-common/lib');
|
```php
|
||||||
|
$loader->registerNamespace('Doctrine\\Common', __DIR__.'/vendor/doctrine-common/lib');
|
||||||
|
```
|
||||||
|
|
||||||
The order of registration is significant and the first registered namespace
|
The order of registration is significant and the first registered namespace
|
||||||
takes precedence over later registered one.
|
takes precedence over later registered one.
|
||||||
|
|
||||||
You can also register more than one path for a given namespace:
|
You can also register more than one path for a given namespace:
|
||||||
|
|
||||||
$loader->registerNamespace('Symfony', array(__DIR__.'/src', __DIR__.'/symfony/src'));
|
```php
|
||||||
|
$loader->registerNamespace('Symfony', array(__DIR__.'/src', __DIR__.'/symfony/src'));
|
||||||
|
```
|
||||||
|
|
||||||
Alternatively, you can use the `registerNamespaces()` method to register more
|
Alternatively, you can use the `registerNamespaces()` method to register more
|
||||||
than one namespace at once:
|
than one namespace at once:
|
||||||
|
|
||||||
$loader->registerNamespaces(array(
|
```php
|
||||||
'Symfony' => array(__DIR__.'/src', __DIR__.'/symfony/src'),
|
$loader->registerNamespaces(array(
|
||||||
'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib',
|
'Symfony' => array(__DIR__.'/src', __DIR__.'/symfony/src'),
|
||||||
'Doctrine' => __DIR__.'/vendor/doctrine/lib',
|
'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib',
|
||||||
'Monolog' => __DIR__.'/vendor/monolog/src',
|
'Doctrine' => __DIR__.'/vendor/doctrine/lib',
|
||||||
));
|
'Monolog' => __DIR__.'/vendor/monolog/src',
|
||||||
|
));
|
||||||
|
```
|
||||||
|
|
||||||
For better performance, you can use the APC based version of the universal
|
For better performance, you can use the APC based version of the universal
|
||||||
class loader:
|
class loader:
|
||||||
|
|
||||||
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
|
```php
|
||||||
require_once __DIR__.'/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
|
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
|
||||||
|
require_once __DIR__.'/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
|
||||||
|
|
||||||
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
|
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
|
||||||
|
|
||||||
$loader = new ApcUniversalClassLoader('apc.prefix.');
|
$loader = new ApcUniversalClassLoader('apc.prefix.');
|
||||||
|
```
|
||||||
|
|
||||||
Furthermore, the component provides tools to aggregate classes into a single
|
Furthermore, the component provides tools to aggregate classes into a single
|
||||||
file, which is especially useful to improve performance on servers that do not
|
file, which is especially useful to improve performance on servers that do not
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,9 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
$data = array(
|
$data = array(
|
||||||
array(__DIR__.'/Fixtures/Namespaced', array(
|
array(__DIR__.'/Fixtures/Namespaced', array(
|
||||||
'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php',
|
'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php',
|
||||||
'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
|
'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
|
||||||
'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php',
|
'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php',
|
||||||
'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php',
|
'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -85,22 +85,22 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||||
'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php',
|
'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php',
|
||||||
)),
|
)),
|
||||||
array(__DIR__.'/Fixtures/Pearlike', array(
|
array(__DIR__.'/Fixtures/Pearlike', array(
|
||||||
'Pearlike_Foo' => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php',
|
'Pearlike_Foo' => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php',
|
||||||
'Pearlike_Bar' => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php',
|
'Pearlike_Bar' => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php',
|
||||||
'Pearlike_Baz' => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php',
|
'Pearlike_Baz' => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php',
|
||||||
'Pearlike_WithComments' => realpath(__DIR__).'/Fixtures/Pearlike/WithComments.php',
|
'Pearlike_WithComments' => realpath(__DIR__).'/Fixtures/Pearlike/WithComments.php',
|
||||||
)),
|
)),
|
||||||
array(__DIR__.'/Fixtures/classmap', array(
|
array(__DIR__.'/Fixtures/classmap', array(
|
||||||
'Foo\\Bar\\A' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
|
'Foo\\Bar\\A' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
|
||||||
'Foo\\Bar\\B' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
|
'Foo\\Bar\\B' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
|
||||||
'A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
'A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
||||||
'Alpha\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
'Alpha\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
||||||
'Alpha\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
'Alpha\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
||||||
'Beta\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
'Beta\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
||||||
'Beta\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
'Beta\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php',
|
||||||
'ClassMap\\SomeInterface' => realpath(__DIR__).'/Fixtures/classmap/SomeInterface.php',
|
'ClassMap\\SomeInterface' => realpath(__DIR__).'/Fixtures/classmap/SomeInterface.php',
|
||||||
'ClassMap\\SomeParent' => realpath(__DIR__).'/Fixtures/classmap/SomeParent.php',
|
'ClassMap\\SomeParent' => realpath(__DIR__).'/Fixtures/classmap/SomeParent.php',
|
||||||
'ClassMap\\SomeClass' => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php',
|
'ClassMap\\SomeClass' => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php',
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ namespace Symfony\Component\ClassLoader;
|
||||||
* // register classes with namespaces
|
* // register classes with namespaces
|
||||||
* $loader->registerNamespaces(array(
|
* $loader->registerNamespaces(array(
|
||||||
* 'Symfony\Component' => __DIR__.'/component',
|
* 'Symfony\Component' => __DIR__.'/component',
|
||||||
* 'Symfony' => __DIR__.'/framework',
|
* 'Symfony' => __DIR__.'/framework',
|
||||||
* 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
|
* 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
|
||||||
* ));
|
* ));
|
||||||
*
|
*
|
||||||
* // register a library using the PEAR naming convention
|
* // register a library using the PEAR naming convention
|
||||||
|
|
@ -74,7 +74,7 @@ class UniversalClassLoader
|
||||||
*/
|
*/
|
||||||
public function useIncludePath($useIncludePath)
|
public function useIncludePath($useIncludePath)
|
||||||
{
|
{
|
||||||
$this->useIncludePath = $useIncludePath;
|
$this->useIncludePath = (bool) $useIncludePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"target-dir": "Symfony/Component/ClassLoader",
|
"target-dir": "Symfony/Component/ClassLoader",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,4 +75,28 @@ class Specificity
|
||||||
{
|
{
|
||||||
return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR;
|
return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns -1 if the object specificity is lower than the argument,
|
||||||
|
* 0 if they are equal, and 1 if the argument is lower
|
||||||
|
*
|
||||||
|
* @param Specificity $specificity
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function compareTo(Specificity $specificity)
|
||||||
|
{
|
||||||
|
if ($this->a !== $specificity->a) {
|
||||||
|
return $this->a > $specificity->a ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->b !== $specificity->b) {
|
||||||
|
return $this->b > $specificity->b ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->c !== $specificity->c) {
|
||||||
|
return $this->c > $specificity->c ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,13 @@ namespace Symfony\Component\CssSelector\Parser;
|
||||||
*/
|
*/
|
||||||
class Token
|
class Token
|
||||||
{
|
{
|
||||||
const TYPE_FILE_END = 'eof';
|
const TYPE_FILE_END = 'eof';
|
||||||
const TYPE_DELIMITER = 'delimiter';
|
const TYPE_DELIMITER = 'delimiter';
|
||||||
const TYPE_WHITESPACE = 'whitespace';
|
const TYPE_WHITESPACE = 'whitespace';
|
||||||
const TYPE_IDENTIFIER = 'identifier';
|
const TYPE_IDENTIFIER = 'identifier';
|
||||||
const TYPE_HASH = 'hash';
|
const TYPE_HASH = 'hash';
|
||||||
const TYPE_NUMBER = 'number';
|
const TYPE_NUMBER = 'number';
|
||||||
const TYPE_STRING = 'string';
|
const TYPE_STRING = 'string';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,11 @@ CssSelector converts CSS selectors to XPath expressions.
|
||||||
The component only goal is to convert CSS selectors to their XPath
|
The component only goal is to convert CSS selectors to their XPath
|
||||||
equivalents:
|
equivalents:
|
||||||
|
|
||||||
use Symfony\Component\CssSelector\CssSelector;
|
```php
|
||||||
|
use Symfony\Component\CssSelector\CssSelector;
|
||||||
|
|
||||||
print CssSelector::toXPath('div.item > h4 > a');
|
print CssSelector::toXPath('div.item > h4 > a');
|
||||||
|
```
|
||||||
|
|
||||||
HTML and XML are different
|
HTML and XML are different
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
@ -18,11 +20,13 @@ default. If you need to use this component with `XML` documents, you have to
|
||||||
disable this `HTML` extension. That's because, `HTML` tag & attribute names
|
disable this `HTML` extension. That's because, `HTML` tag & attribute names
|
||||||
are always lower-cased, but case-sensitive in `XML`:
|
are always lower-cased, but case-sensitive in `XML`:
|
||||||
|
|
||||||
// disable `HTML` extension:
|
```php
|
||||||
CssSelector::disableHtmlExtension();
|
// disable `HTML` extension:
|
||||||
|
CssSelector::disableHtmlExtension();
|
||||||
|
|
||||||
// re-enable `HTML` extension:
|
// re-enable `HTML` extension:
|
||||||
CssSelector::enableHtmlExtension();
|
CssSelector::enableHtmlExtension();
|
||||||
|
```
|
||||||
|
|
||||||
When the `HTML` extension is enabled, tag names are lower-cased, attribute
|
When the `HTML` extension is enabled, tag names are lower-cased, attribute
|
||||||
names are lower-cased, the following extra pseudo-classes are supported:
|
names are lower-cased, the following extra pseudo-classes are supported:
|
||||||
|
|
|
||||||
|
|
@ -37,4 +37,26 @@ class SpecificityTest extends \PHPUnit_Framework_TestCase
|
||||||
array(new Specificity(4, 3, 2), 432),
|
array(new Specificity(4, 3, 2), 432),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @dataProvider getCompareTestData */
|
||||||
|
public function testCompareTo(Specificity $a, Specificity $b, $result)
|
||||||
|
{
|
||||||
|
$this->assertEquals($result, $a->compareTo($b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompareTestData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(new Specificity(0, 0, 0), new Specificity(0, 0, 0), 0),
|
||||||
|
array(new Specificity(0, 0, 1), new Specificity(0, 0, 1), 0),
|
||||||
|
array(new Specificity(0, 0, 2), new Specificity(0, 0, 1), 1),
|
||||||
|
array(new Specificity(0, 0, 2), new Specificity(0, 0, 3), -1),
|
||||||
|
array(new Specificity(0, 4, 0), new Specificity(0, 4, 0), 0),
|
||||||
|
array(new Specificity(0, 6, 0), new Specificity(0, 5, 11), 1),
|
||||||
|
array(new Specificity(0, 7, 0), new Specificity(0, 8, 0), -1),
|
||||||
|
array(new Specificity(9, 0, 0), new Specificity(9, 0, 0), 0),
|
||||||
|
array(new Specificity(11, 0, 0), new Specificity(10, 11, 0), 1),
|
||||||
|
array(new Specificity(12, 11, 0), new Specificity(13, 0, 0), -1),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ class AttributeMatchingExtension extends AbstractExtension
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'exists' => array($this, 'translateExists'),
|
'exists' => array($this, 'translateExists'),
|
||||||
'=' => array($this, 'translateEquals'),
|
'=' => array($this, 'translateEquals'),
|
||||||
'~=' => array($this, 'translateIncludes'),
|
'~=' => array($this, 'translateIncludes'),
|
||||||
'|=' => array($this, 'translateDashMatch'),
|
'|=' => array($this, 'translateDashMatch'),
|
||||||
'^=' => array($this, 'translatePrefixMatch'),
|
'^=' => array($this, 'translatePrefixMatch'),
|
||||||
'$=' => array($this, 'translateSuffixMatch'),
|
'$=' => array($this, 'translateSuffixMatch'),
|
||||||
'*=' => array($this, 'translateSubstringMatch'),
|
'*=' => array($this, 'translateSubstringMatch'),
|
||||||
'!=' => array($this, 'translateDifferent'),
|
'!=' => array($this, 'translateDifferent'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,12 @@ class FunctionExtension extends AbstractExtension
|
||||||
public function getFunctionTranslators()
|
public function getFunctionTranslators()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'nth-child' => array($this, 'translateNthChild'),
|
'nth-child' => array($this, 'translateNthChild'),
|
||||||
'nth-last-child' => array($this, 'translateNthLastChild'),
|
'nth-last-child' => array($this, 'translateNthLastChild'),
|
||||||
'nth-of-type' => array($this, 'translateNthOfType'),
|
'nth-of-type' => array($this, 'translateNthOfType'),
|
||||||
'nth-last-of-type' => array($this, 'translateNthLastOfType'),
|
'nth-last-of-type' => array($this, 'translateNthLastOfType'),
|
||||||
'contains' => array($this, 'translateContains'),
|
'contains' => array($this, 'translateContains'),
|
||||||
'lang' => array($this, 'translateLang'),
|
'lang' => array($this, 'translateLang'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,14 @@ class HtmlExtension extends AbstractExtension
|
||||||
public function getPseudoClassTranslators()
|
public function getPseudoClassTranslators()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'checked' => array($this, 'translateChecked'),
|
'checked' => array($this, 'translateChecked'),
|
||||||
'link' => array($this, 'translateLink'),
|
'link' => array($this, 'translateLink'),
|
||||||
'disabled' => array($this, 'translateDisabled'),
|
'disabled' => array($this, 'translateDisabled'),
|
||||||
'enabled' => array($this, 'translateEnabled'),
|
'enabled' => array($this, 'translateEnabled'),
|
||||||
'selected' => array($this, 'translateSelected'),
|
'selected' => array($this, 'translateSelected'),
|
||||||
'invalid' => array($this, 'translateInvalid'),
|
'invalid' => array($this, 'translateInvalid'),
|
||||||
'hover' => array($this, 'translateHover'),
|
'hover' => array($this, 'translateHover'),
|
||||||
'visited' => array($this, 'translateVisited'),
|
'visited' => array($this, 'translateVisited'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ use Symfony\Component\CssSelector\XPath\XPathExpr;
|
||||||
*/
|
*/
|
||||||
class NodeExtension extends AbstractExtension
|
class NodeExtension extends AbstractExtension
|
||||||
{
|
{
|
||||||
const ELEMENT_NAME_IN_LOWER_CASE = 1;
|
const ELEMENT_NAME_IN_LOWER_CASE = 1;
|
||||||
const ATTRIBUTE_NAME_IN_LOWER_CASE = 2;
|
const ATTRIBUTE_NAME_IN_LOWER_CASE = 2;
|
||||||
const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4;
|
const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -79,15 +79,15 @@ class NodeExtension extends AbstractExtension
|
||||||
public function getNodeTranslators()
|
public function getNodeTranslators()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'Selector' => array($this, 'translateSelector'),
|
'Selector' => array($this, 'translateSelector'),
|
||||||
'CombinedSelector' => array($this, 'translateCombinedSelector'),
|
'CombinedSelector' => array($this, 'translateCombinedSelector'),
|
||||||
'Negation' => array($this, 'translateNegation'),
|
'Negation' => array($this, 'translateNegation'),
|
||||||
'Function' => array($this, 'translateFunction'),
|
'Function' => array($this, 'translateFunction'),
|
||||||
'Pseudo' => array($this, 'translatePseudo'),
|
'Pseudo' => array($this, 'translatePseudo'),
|
||||||
'Attribute' => array($this, 'translateAttribute'),
|
'Attribute' => array($this, 'translateAttribute'),
|
||||||
'Class' => array($this, 'translateClass'),
|
'Class' => array($this, 'translateClass'),
|
||||||
'Hash' => array($this, 'translateHash'),
|
'Hash' => array($this, 'translateHash'),
|
||||||
'Element' => array($this, 'translateElement'),
|
'Element' => array($this, 'translateElement'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,14 @@ class PseudoClassExtension extends AbstractExtension
|
||||||
public function getPseudoClassTranslators()
|
public function getPseudoClassTranslators()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'root' => array($this, 'translateRoot'),
|
'root' => array($this, 'translateRoot'),
|
||||||
'first-child' => array($this, 'translateFirstChild'),
|
'first-child' => array($this, 'translateFirstChild'),
|
||||||
'last-child' => array($this, 'translateLastChild'),
|
'last-child' => array($this, 'translateLastChild'),
|
||||||
'first-of-type' => array($this, 'translateFirstOfType'),
|
'first-of-type' => array($this, 'translateFirstOfType'),
|
||||||
'last-of-type' => array($this, 'translateLastOfType'),
|
'last-of-type' => array($this, 'translateLastOfType'),
|
||||||
'only-child' => array($this, 'translateOnlyChild'),
|
'only-child' => array($this, 'translateOnlyChild'),
|
||||||
'only-of-type' => array($this, 'translateOnlyOfType'),
|
'only-of-type' => array($this, 'translateOnlyOfType'),
|
||||||
'empty' => array($this, 'translateEmpty'),
|
'empty' => array($this, 'translateEmpty'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,17 +123,15 @@ class Translator implements TranslatorInterface
|
||||||
$selectors = $this->parseSelectors($cssExpr);
|
$selectors = $this->parseSelectors($cssExpr);
|
||||||
|
|
||||||
/** @var SelectorNode $selector */
|
/** @var SelectorNode $selector */
|
||||||
foreach ($selectors as $selector) {
|
foreach ($selectors as $index => $selector) {
|
||||||
if (null !== $selector->getPseudoElement()) {
|
if (null !== $selector->getPseudoElement()) {
|
||||||
throw new ExpressionErrorException('Pseudo-elements are not supported.');
|
throw new ExpressionErrorException('Pseudo-elements are not supported.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$selectors[$index] = $this->selectorToXPath($selector, $prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
$translator = $this;
|
return implode(' | ', $selectors);
|
||||||
|
|
||||||
return implode(' | ', array_map(function (SelectorNode $selector) use ($translator, $prefix) {
|
|
||||||
return $translator->selectorToXPath($selector, $prefix);
|
|
||||||
}, $selectors));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
2.6.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* generalized ErrorHandler and ExceptionHandler,
|
||||||
|
with some new methods and others deprecated
|
||||||
|
* enhanced error messages for uncaught exceptions
|
||||||
|
|
||||||
2.5.0
|
2.5.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,15 +39,23 @@ class Debug
|
||||||
|
|
||||||
static::$enabled = true;
|
static::$enabled = true;
|
||||||
|
|
||||||
error_reporting(-1);
|
if (null !== $errorReportingLevel) {
|
||||||
|
error_reporting($errorReportingLevel);
|
||||||
|
} else {
|
||||||
|
error_reporting(-1);
|
||||||
|
}
|
||||||
|
|
||||||
ErrorHandler::register($errorReportingLevel, $displayErrors);
|
|
||||||
if ('cli' !== php_sapi_name()) {
|
if ('cli' !== php_sapi_name()) {
|
||||||
|
ini_set('display_errors', 0);
|
||||||
ExceptionHandler::register();
|
ExceptionHandler::register();
|
||||||
// CLI - display errors only if they're not already logged to STDERR
|
|
||||||
} elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
|
} elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
|
||||||
|
// CLI - display errors only if they're not already logged to STDERR
|
||||||
ini_set('display_errors', 1);
|
ini_set('display_errors', 1);
|
||||||
}
|
}
|
||||||
|
$handler = ErrorHandler::register();
|
||||||
|
if (!$displayErrors) {
|
||||||
|
$handler->throwAt(0, true);
|
||||||
|
}
|
||||||
|
|
||||||
DebugClassLoader::enable();
|
DebugClassLoader::enable();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,8 @@ class DebugClassLoader
|
||||||
public static function enable()
|
public static function enable()
|
||||||
{
|
{
|
||||||
// Ensures we don't hit https://bugs.php.net/42098
|
// Ensures we don't hit https://bugs.php.net/42098
|
||||||
class_exists(__NAMESPACE__.'\ErrorHandler', true);
|
class_exists('Symfony\Component\Debug\ErrorHandler');
|
||||||
|
class_exists('Psr\Log\LogLevel');
|
||||||
|
|
||||||
if (!is_array($functions = spl_autoload_functions())) {
|
if (!is_array($functions = spl_autoload_functions())) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -22,188 +22,511 @@ use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
|
||||||
use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
|
use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ErrorHandler.
|
* A generic ErrorHandler for the PHP engine.
|
||||||
|
*
|
||||||
|
* Provides five bit fields that control how errors are handled:
|
||||||
|
* - thrownErrors: errors thrown as \ErrorException
|
||||||
|
* - loggedErrors: logged errors, when not @-silenced
|
||||||
|
* - scopedErrors: errors thrown or logged with their local context
|
||||||
|
* - tracedErrors: errors logged with their stack trace, only once for repeated errors
|
||||||
|
* - screamedErrors: never @-silenced errors
|
||||||
|
*
|
||||||
|
* Each error level can be logged by a dedicated PSR-3 logger object.
|
||||||
|
* Screaming only applies to logging.
|
||||||
|
* Throwing takes precedence over logging.
|
||||||
|
* Uncaught exceptions are logged as E_ERROR.
|
||||||
|
* E_DEPRECATED and E_USER_DEPRECATED levels never throw.
|
||||||
|
* E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw.
|
||||||
|
* Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so.
|
||||||
|
* As errors have a performance cost, repeated errors are all logged, so that the developer
|
||||||
|
* can see them and weight them as more important to fix than others of the same level.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
|
||||||
* @author Konstantin Myakshin <koc-dp@yandex.ru>
|
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class ErrorHandler
|
class ErrorHandler
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0.
|
||||||
|
*/
|
||||||
const TYPE_DEPRECATION = -100;
|
const TYPE_DEPRECATION = -100;
|
||||||
|
|
||||||
private $levels = array(
|
private $levels = array(
|
||||||
E_WARNING => 'Warning',
|
E_DEPRECATED => 'Deprecated',
|
||||||
E_NOTICE => 'Notice',
|
E_USER_DEPRECATED => 'User Deprecated',
|
||||||
E_USER_ERROR => 'User Error',
|
E_NOTICE => 'Notice',
|
||||||
E_USER_WARNING => 'User Warning',
|
E_USER_NOTICE => 'User Notice',
|
||||||
E_USER_NOTICE => 'User Notice',
|
E_STRICT => 'Runtime Notice',
|
||||||
E_STRICT => 'Runtime Notice',
|
E_WARNING => 'Warning',
|
||||||
|
E_USER_WARNING => 'User Warning',
|
||||||
|
E_COMPILE_WARNING => 'Compile Warning',
|
||||||
|
E_CORE_WARNING => 'Core Warning',
|
||||||
|
E_USER_ERROR => 'User Error',
|
||||||
E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
|
E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
|
||||||
E_DEPRECATED => 'Deprecated',
|
E_COMPILE_ERROR => 'Compile Error',
|
||||||
E_USER_DEPRECATED => 'User Deprecated',
|
E_PARSE => 'Parse Error',
|
||||||
E_ERROR => 'Error',
|
E_ERROR => 'Error',
|
||||||
E_CORE_ERROR => 'Core Error',
|
E_CORE_ERROR => 'Core Error',
|
||||||
E_COMPILE_ERROR => 'Compile Error',
|
|
||||||
E_PARSE => 'Parse Error',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
private $level;
|
private $loggers = array(
|
||||||
|
E_DEPRECATED => array(null, LogLevel::INFO),
|
||||||
|
E_USER_DEPRECATED => array(null, LogLevel::INFO),
|
||||||
|
E_NOTICE => array(null, LogLevel::NOTICE),
|
||||||
|
E_USER_NOTICE => array(null, LogLevel::NOTICE),
|
||||||
|
E_STRICT => array(null, LogLevel::NOTICE),
|
||||||
|
E_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_USER_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_COMPILE_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_CORE_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_USER_ERROR => array(null, LogLevel::ERROR),
|
||||||
|
E_RECOVERABLE_ERROR => array(null, LogLevel::ERROR),
|
||||||
|
E_COMPILE_ERROR => array(null, LogLevel::EMERGENCY),
|
||||||
|
E_PARSE => array(null, LogLevel::EMERGENCY),
|
||||||
|
E_ERROR => array(null, LogLevel::EMERGENCY),
|
||||||
|
E_CORE_ERROR => array(null, LogLevel::EMERGENCY),
|
||||||
|
);
|
||||||
|
|
||||||
private $reservedMemory;
|
private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
|
||||||
|
private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
|
||||||
|
private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE
|
||||||
|
private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE
|
||||||
|
private $loggedErrors = 0;
|
||||||
|
|
||||||
private $displayErrors;
|
private $loggedTraces = array();
|
||||||
|
private $isRecursive = 0;
|
||||||
|
private $exceptionHandler;
|
||||||
|
|
||||||
|
private static $reservedMemory;
|
||||||
|
private static $stackedErrors = array();
|
||||||
|
private static $stackedErrorLevels = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var LoggerInterface[] Loggers for channels
|
* Same init value as thrownErrors
|
||||||
|
*
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
private static $loggers = array();
|
private $displayErrors = 0x1FFF;
|
||||||
|
|
||||||
private static $stackedErrors = array();
|
|
||||||
|
|
||||||
private static $stackedErrorLevels = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the error handler.
|
* Registers the error handler.
|
||||||
*
|
*
|
||||||
* @param int $level The level at which the conversion to Exception is done (null to use the error_reporting() value and 0 to disable)
|
* @param self|null|int $handler The handler to register, or @deprecated (since 2.6, to be removed in 3.0) bit field of thrown levels
|
||||||
* @param bool $displayErrors Display errors (for dev environment) or just log them (production usage)
|
* @param bool $replace Whether to replace or not any existing handler
|
||||||
*
|
*
|
||||||
* @return ErrorHandler The registered error handler
|
* @return self The registered error handler
|
||||||
*/
|
*/
|
||||||
public static function register($level = null, $displayErrors = true)
|
public static function register($handler = null, $replace = true)
|
||||||
{
|
{
|
||||||
$handler = new static();
|
if (null === self::$reservedMemory) {
|
||||||
$handler->setLevel($level);
|
self::$reservedMemory = str_repeat('x', 10240);
|
||||||
$handler->setDisplayErrors($displayErrors);
|
register_shutdown_function(__CLASS__.'::handleFatalError');
|
||||||
|
}
|
||||||
|
|
||||||
ini_set('display_errors', 0);
|
$levels = -1;
|
||||||
set_error_handler(array($handler, 'handle'));
|
|
||||||
register_shutdown_function(array($handler, 'handleFatal'));
|
if ($handlerIsNew = !$handler instanceof self) {
|
||||||
$handler->reservedMemory = str_repeat('x', 10240);
|
// @deprecated polymorphism, to be removed in 3.0
|
||||||
|
if (null !== $handler) {
|
||||||
|
$levels = $replace ? $handler : 0;
|
||||||
|
$replace = true;
|
||||||
|
}
|
||||||
|
$handler = new static();
|
||||||
|
}
|
||||||
|
|
||||||
|
$prev = set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
|
||||||
|
|
||||||
|
if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
|
||||||
|
$handler = $prev[0];
|
||||||
|
$replace = false;
|
||||||
|
}
|
||||||
|
if ($replace || !$prev) {
|
||||||
|
$handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
|
||||||
|
} else {
|
||||||
|
restore_error_handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
$handler->throwAt($levels & $handler->thrownErrors, true);
|
||||||
|
|
||||||
return $handler;
|
return $handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the level at which the conversion to Exception is done.
|
* Sets a logger to non assigned errors levels.
|
||||||
*
|
*
|
||||||
* @param int|null $level The level (null to use the error_reporting() value and 0 to disable)
|
* @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels
|
||||||
|
* @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
|
||||||
|
* @param bool $replace Whether to replace or not any existing logger
|
||||||
*/
|
*/
|
||||||
public function setLevel($level)
|
public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
|
||||||
{
|
{
|
||||||
$this->level = null === $level ? error_reporting() : $level;
|
$loggers = array();
|
||||||
|
|
||||||
|
if (is_array($levels)) {
|
||||||
|
foreach ($levels as $type => $logLevel) {
|
||||||
|
if (empty($this->loggers[$type][0]) || $replace) {
|
||||||
|
$loggers[$type] = array($logger, $logLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (null === $levels) {
|
||||||
|
$levels = E_ALL | E_STRICT;
|
||||||
|
}
|
||||||
|
foreach ($this->loggers as $type => $log) {
|
||||||
|
if (($type & $levels) && (empty($log[0]) || $replace)) {
|
||||||
|
$log[0] = $logger;
|
||||||
|
$loggers[$type] = $log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setLoggers($loggers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the display_errors flag value.
|
* Sets a logger for each error level.
|
||||||
*
|
*
|
||||||
* @param int $displayErrors The display_errors flag value
|
* @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map
|
||||||
|
*
|
||||||
|
* @return array The previous map
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function setDisplayErrors($displayErrors)
|
public function setLoggers(array $loggers)
|
||||||
{
|
{
|
||||||
$this->displayErrors = $displayErrors;
|
$prevLogged = $this->loggedErrors;
|
||||||
|
$prev = $this->loggers;
|
||||||
|
|
||||||
|
foreach ($loggers as $type => $log) {
|
||||||
|
if (!isset($prev[$type])) {
|
||||||
|
throw new \InvalidArgumentException('Unknown error type: '.$type);
|
||||||
|
}
|
||||||
|
if (!is_array($log)) {
|
||||||
|
$log = array($log);
|
||||||
|
} elseif (!array_key_exists(0, $log)) {
|
||||||
|
throw new \InvalidArgumentException('No logger provided');
|
||||||
|
}
|
||||||
|
if (null === $log[0]) {
|
||||||
|
$this->loggedErrors &= ~$type;
|
||||||
|
} elseif ($log[0] instanceof LoggerInterface) {
|
||||||
|
$this->loggedErrors |= $type;
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException('Invalid logger provided');
|
||||||
|
}
|
||||||
|
$this->loggers[$type] = $log + $prev[$type];
|
||||||
|
}
|
||||||
|
$this->reRegister($prevLogged | $this->thrownErrors);
|
||||||
|
|
||||||
|
return $prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a logger for the given channel.
|
* Sets a user exception handler.
|
||||||
*
|
*
|
||||||
* @param LoggerInterface $logger A logger interface
|
* @param callable $handler A handler that will be called on Exception
|
||||||
* @param string $channel The channel associated with the logger (deprecation, emergency or scream)
|
*
|
||||||
|
* @return callable|null The previous exception handler
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
|
public function setExceptionHandler($handler)
|
||||||
{
|
{
|
||||||
self::$loggers[$channel] = $logger;
|
if (null !== $handler && !is_callable($handler)) {
|
||||||
|
throw new \LogicException('The exception handler must be a valid PHP callable.');
|
||||||
|
}
|
||||||
|
$prev = $this->exceptionHandler;
|
||||||
|
$this->exceptionHandler = $handler;
|
||||||
|
|
||||||
|
return $prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \ErrorException When error_reporting returns error
|
* Sets the error levels that are to be thrown.
|
||||||
|
*
|
||||||
|
* @param int $levels A bit field of E_* constants for thrown errors
|
||||||
|
* @param bool $replace Replace or amend the previous value
|
||||||
|
*
|
||||||
|
* @return int The previous value
|
||||||
*/
|
*/
|
||||||
public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
|
public function throwAt($levels, $replace = false)
|
||||||
{
|
{
|
||||||
if ($level & (E_USER_DEPRECATED | E_DEPRECATED)) {
|
$prev = $this->thrownErrors;
|
||||||
if (isset(self::$loggers['deprecation'])) {
|
$this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
|
||||||
if (self::$stackedErrorLevels) {
|
if (!$replace) {
|
||||||
self::$stackedErrors[] = func_get_args();
|
$this->thrownErrors |= $prev;
|
||||||
|
}
|
||||||
|
$this->reRegister($prev | $this->loggedErrors);
|
||||||
|
|
||||||
|
// $this->displayErrors is @deprecated since 2.6
|
||||||
|
$this->displayErrors = $this->thrownErrors;
|
||||||
|
|
||||||
|
return $prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the error levels that are logged or thrown with their local scope.
|
||||||
|
*
|
||||||
|
* @param int $levels A bit field of E_* constants for scoped errors
|
||||||
|
* @param bool $replace Replace or amend the previous value
|
||||||
|
*
|
||||||
|
* @return int The previous value
|
||||||
|
*/
|
||||||
|
public function scopeAt($levels, $replace = false)
|
||||||
|
{
|
||||||
|
$prev = $this->scopedErrors;
|
||||||
|
$this->scopedErrors = (int) $levels;
|
||||||
|
if (!$replace) {
|
||||||
|
$this->scopedErrors |= $prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the error levels that are logged with their stack trace.
|
||||||
|
*
|
||||||
|
* @param int $levels A bit field of E_* constants for traced errors
|
||||||
|
* @param bool $replace Replace or amend the previous value
|
||||||
|
*
|
||||||
|
* @return int The previous value
|
||||||
|
*/
|
||||||
|
public function traceAt($levels, $replace = false)
|
||||||
|
{
|
||||||
|
$prev = $this->tracedErrors;
|
||||||
|
$this->tracedErrors = (int) $levels;
|
||||||
|
if (!$replace) {
|
||||||
|
$this->tracedErrors |= $prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the error levels where the @-operator is ignored.
|
||||||
|
*
|
||||||
|
* @param int $levels A bit field of E_* constants for screamed errors
|
||||||
|
* @param bool $replace Replace or amend the previous value
|
||||||
|
*
|
||||||
|
* @return int The previous value
|
||||||
|
*/
|
||||||
|
public function screamAt($levels, $replace = false)
|
||||||
|
{
|
||||||
|
$prev = $this->screamedErrors;
|
||||||
|
$this->screamedErrors = (int) $levels;
|
||||||
|
if (!$replace) {
|
||||||
|
$this->screamedErrors |= $prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-registers as a PHP error handler if levels changed.
|
||||||
|
*/
|
||||||
|
private function reRegister($prev)
|
||||||
|
{
|
||||||
|
if ($prev !== $this->thrownErrors | $this->loggedErrors) {
|
||||||
|
$handler = set_error_handler('var_dump', 0);
|
||||||
|
$handler = is_array($handler) ? $handler[0] : null;
|
||||||
|
restore_error_handler();
|
||||||
|
if ($handler === $this) {
|
||||||
|
restore_error_handler();
|
||||||
|
set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles errors by filtering then logging them according to the configured bit fields.
|
||||||
|
*
|
||||||
|
* @param int $type One of the E_* constants
|
||||||
|
* @param string $file
|
||||||
|
* @param int $line
|
||||||
|
* @param array $context
|
||||||
|
*
|
||||||
|
* @return bool Returns false when no handling happens so that the PHP engine can handle the error itself.
|
||||||
|
*
|
||||||
|
* @throws \ErrorException When $this->thrownErrors requests so
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function handleError($type, $message, $file, $line, array $context)
|
||||||
|
{
|
||||||
|
$level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR;
|
||||||
|
$log = $this->loggedErrors & $type;
|
||||||
|
$throw = $this->thrownErrors & $type & $level;
|
||||||
|
$type &= $level | $this->screamedErrors;
|
||||||
|
|
||||||
|
if ($type && ($log || $throw)) {
|
||||||
|
if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) {
|
||||||
|
$e = $context; // Whatever the signature of the method,
|
||||||
|
unset($e['GLOBALS'], $context); // $context is always a reference in 5.3
|
||||||
|
$context = $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($throw) {
|
||||||
|
if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
|
||||||
|
// Checking for class existence is a work around for https://bugs.php.net/42098
|
||||||
|
$throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
|
||||||
} else {
|
} else {
|
||||||
if (version_compare(PHP_VERSION, '5.4', '<')) {
|
$throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
|
||||||
$stack = array_map(
|
}
|
||||||
function ($row) {
|
|
||||||
unset($row['args']);
|
|
||||||
|
|
||||||
return $row;
|
if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) {
|
||||||
},
|
// Exceptions thrown from error handlers are sometimes not caught by the exception
|
||||||
array_slice(debug_backtrace(false), 0, 10)
|
// handler and shutdown handlers are bypassed before 5.4.8/5.3.18.
|
||||||
);
|
// We temporarily re-enable display_errors to prevent any blank page related to this bug.
|
||||||
} else {
|
|
||||||
$stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
|
$throw->errorHandlerCanary = new ErrorHandlerCanary();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For duplicated errors, log the trace only once
|
||||||
|
$e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
|
||||||
|
$trace = true;
|
||||||
|
|
||||||
|
if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
|
||||||
|
$trace = false;
|
||||||
|
} else {
|
||||||
|
$this->loggedTraces[$e] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$e = compact('type', 'file', 'line', 'level');
|
||||||
|
|
||||||
|
if ($type & $level) {
|
||||||
|
if ($this->scopedErrors & $type) {
|
||||||
|
$e['context'] = $context;
|
||||||
|
if ($trace) {
|
||||||
|
$e['stack'] = debug_backtrace(true); // Provide object
|
||||||
}
|
}
|
||||||
|
} elseif ($trace) {
|
||||||
self::$loggers['deprecation']->warning($message, array('type' => self::TYPE_DEPRECATION, 'stack' => $stack));
|
$e['stack'] = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} elseif ($this->displayErrors && error_reporting() & $level && $this->level & $level) {
|
|
||||||
if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && is_array($context)) {
|
|
||||||
$c = $context; // Whatever the signature of the method,
|
|
||||||
unset($c['GLOBALS'], $context); // $context is always a reference in 5.3
|
|
||||||
$context = $c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$exception = sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line);
|
if ($this->isRecursive) {
|
||||||
if ($context && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
|
$log = 0;
|
||||||
// Checking for class existence is a work around for https://bugs.php.net/42098
|
} elseif (self::$stackedErrorLevels) {
|
||||||
$exception = new ContextErrorException($exception, 0, $level, $file, $line, $context);
|
self::$stackedErrors[] = array($this->loggers[$type], $message, $e);
|
||||||
} else {
|
} else {
|
||||||
$exception = new \ErrorException($exception, 0, $level, $file, $line);
|
try {
|
||||||
}
|
$this->isRecursive = true;
|
||||||
|
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
|
||||||
|
$this->isRecursive = false;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->isRecursive = false;
|
||||||
|
|
||||||
if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) {
|
throw $e;
|
||||||
// Exceptions thrown from error handlers are sometimes not caught by the exception
|
|
||||||
// handler and shutdown handlers are bypassed before 5.4.8/5.3.18.
|
|
||||||
// We temporarily re-enable display_errors to prevent any blank page related to this bug.
|
|
||||||
|
|
||||||
$exception->errorHandlerCanary = new ErrorHandlerCanary();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw $exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset(self::$loggers['scream']) && !(error_reporting() & $level)) {
|
|
||||||
if (self::$stackedErrorLevels) {
|
|
||||||
self::$stackedErrors[] = func_get_args();
|
|
||||||
} else {
|
|
||||||
switch ($level) {
|
|
||||||
case E_USER_ERROR:
|
|
||||||
case E_RECOVERABLE_ERROR:
|
|
||||||
$logLevel = LogLevel::ERROR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case E_WARNING:
|
|
||||||
case E_USER_WARNING:
|
|
||||||
$logLevel = LogLevel::WARNING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
$logLevel = LogLevel::NOTICE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$loggers['scream']->log($logLevel, $message, array(
|
|
||||||
'type' => $level,
|
|
||||||
'file' => $file,
|
|
||||||
'line' => $line,
|
|
||||||
'scream' => error_reporting(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return $type && $log;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the error handler for delayed handling.
|
* Handles an exception by logging then forwarding it to an other handler.
|
||||||
|
*
|
||||||
|
* @param \Exception $exception An exception to handle
|
||||||
|
* @param array $error An array as returned by error_get_last()
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function handleException(\Exception $exception, array $error = null)
|
||||||
|
{
|
||||||
|
$level = error_reporting();
|
||||||
|
if ($this->loggedErrors & E_ERROR & ($level | $this->screamedErrors)) {
|
||||||
|
$e = array(
|
||||||
|
'type' => E_ERROR,
|
||||||
|
'file' => $exception->getFile(),
|
||||||
|
'line' => $exception->getLine(),
|
||||||
|
'level' => $level,
|
||||||
|
'stack' => $exception->getTrace(),
|
||||||
|
);
|
||||||
|
if ($exception instanceof FatalErrorException) {
|
||||||
|
$message = 'Fatal '.$exception->getMessage();
|
||||||
|
} elseif ($exception instanceof \ErrorException) {
|
||||||
|
$message = 'Uncaught '.$exception->getMessage();
|
||||||
|
if ($exception instanceof ContextErrorException) {
|
||||||
|
$e['context'] = $exception->getContext();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message = 'Uncaught Exception: '.$exception->getMessage();
|
||||||
|
}
|
||||||
|
if ($this->loggedErrors & $e['type']) {
|
||||||
|
$this->loggers[$e['type']][0]->log($this->loggers[$e['type']][1], $message, $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
|
||||||
|
foreach ($this->getFatalErrorHandlers() as $handler) {
|
||||||
|
if ($e = $handler->handleError($error, $exception)) {
|
||||||
|
$exception = $e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (empty($this->exceptionHandler)) {
|
||||||
|
throw $exception; // Give back $exception to the native handler
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
call_user_func($this->exceptionHandler, $exception);
|
||||||
|
} catch (\Exception $handlerException) {
|
||||||
|
$this->exceptionHandler = null;
|
||||||
|
$this->handleException($handlerException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown registered function for handling PHP fatal errors.
|
||||||
|
*
|
||||||
|
* @param array $error An array as returned by error_get_last()
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public static function handleFatalError(array $error = null)
|
||||||
|
{
|
||||||
|
self::$reservedMemory = '';
|
||||||
|
gc_collect_cycles();
|
||||||
|
$handler = set_error_handler('var_dump', 0);
|
||||||
|
$handler = is_array($handler) ? $handler[0] : null;
|
||||||
|
restore_error_handler();
|
||||||
|
if ($handler instanceof self) {
|
||||||
|
if (null === $error) {
|
||||||
|
$error = error_get_last();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (self::$stackedErrorLevels) {
|
||||||
|
static::unstackErrors();
|
||||||
|
}
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
// Handled below
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) {
|
||||||
|
// Let's not throw anymore but keep logging
|
||||||
|
$handler->throwAt(0, true);
|
||||||
|
|
||||||
|
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
|
||||||
|
$exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false);
|
||||||
|
} else {
|
||||||
|
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true);
|
||||||
|
}
|
||||||
|
} elseif (!isset($exception)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$handler->handleException($exception, $error);
|
||||||
|
} catch (FatalErrorException $e) {
|
||||||
|
// Ignore this re-throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the error handler for delayed handling.
|
||||||
* Ensures also that non-catchable fatal errors are never silenced.
|
* Ensures also that non-catchable fatal errors are never silenced.
|
||||||
*
|
*
|
||||||
* As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724
|
* As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724
|
||||||
|
|
@ -219,7 +542,7 @@ class ErrorHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unstacks stacked errors and forwards to the regular handler
|
* Unstacks stacked errors and forwards to the logger
|
||||||
*/
|
*/
|
||||||
public static function unstackErrors()
|
public static function unstackErrors()
|
||||||
{
|
{
|
||||||
|
|
@ -237,64 +560,12 @@ class ErrorHandler
|
||||||
$errors = self::$stackedErrors;
|
$errors = self::$stackedErrors;
|
||||||
self::$stackedErrors = array();
|
self::$stackedErrors = array();
|
||||||
|
|
||||||
$errorHandler = set_error_handler('var_dump');
|
foreach ($errors as $e) {
|
||||||
restore_error_handler();
|
$e[0][0]->log($e[0][1], $e[1], $e[2]);
|
||||||
|
|
||||||
if ($errorHandler) {
|
|
||||||
foreach ($errors as $e) {
|
|
||||||
call_user_func_array($errorHandler, $e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleFatal()
|
|
||||||
{
|
|
||||||
$this->reservedMemory = '';
|
|
||||||
gc_collect_cycles();
|
|
||||||
$error = error_get_last();
|
|
||||||
|
|
||||||
// get current exception handler
|
|
||||||
$exceptionHandler = set_exception_handler('var_dump');
|
|
||||||
restore_exception_handler();
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (self::$stackedErrorLevels) {
|
|
||||||
static::unstackErrors();
|
|
||||||
}
|
|
||||||
} catch (\Exception $exception) {
|
|
||||||
if ($exceptionHandler) {
|
|
||||||
call_user_func($exceptionHandler, $exception);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->displayErrors) {
|
|
||||||
ini_set('display_errors', 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw $exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$error || !$this->level || !($error['type'] & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_PARSE))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset(self::$loggers['emergency'])) {
|
|
||||||
$fatal = array(
|
|
||||||
'type' => $error['type'],
|
|
||||||
'file' => $error['file'],
|
|
||||||
'line' => $error['line'],
|
|
||||||
);
|
|
||||||
|
|
||||||
self::$loggers['emergency']->emergency($error['message'], $fatal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->displayErrors && $exceptionHandler) {
|
|
||||||
$this->handleFatalError($exceptionHandler, $error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the fatal error handlers.
|
* Gets the fatal error handlers.
|
||||||
*
|
*
|
||||||
|
|
@ -311,33 +582,81 @@ class ErrorHandler
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleFatalError($exceptionHandler, array $error)
|
/**
|
||||||
|
* Sets the level at which the conversion to Exception is done.
|
||||||
|
*
|
||||||
|
* @param int|null $level The level (null to use the error_reporting() value and 0 to disable)
|
||||||
|
*
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0. Use throwAt() instead.
|
||||||
|
*/
|
||||||
|
public function setLevel($level)
|
||||||
{
|
{
|
||||||
// Let PHP handle any further error
|
$level = null === $level ? error_reporting() : $level;
|
||||||
set_error_handler('var_dump', 0);
|
$this->throwAt($level, true);
|
||||||
ini_set('display_errors', 1);
|
}
|
||||||
|
|
||||||
$level = isset($this->levels[$error['type']]) ? $this->levels[$error['type']] : $error['type'];
|
/**
|
||||||
$message = sprintf('%s: %s in %s line %d', $level, $error['message'], $error['file'], $error['line']);
|
* Sets the display_errors flag value.
|
||||||
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
|
*
|
||||||
$exception = new OutOfMemoryException($message, 0, $error['type'], $error['file'], $error['line'], 3, false);
|
* @param int $displayErrors The display_errors flag value
|
||||||
|
*
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0. Use throwAt() instead.
|
||||||
|
*/
|
||||||
|
public function setDisplayErrors($displayErrors)
|
||||||
|
{
|
||||||
|
if ($displayErrors) {
|
||||||
|
$this->throwAt($this->displayErrors, true);
|
||||||
} else {
|
} else {
|
||||||
$exception = new FatalErrorException($message, 0, $error['type'], $error['file'], $error['line'], 3, true);
|
$displayErrors = $this->displayErrors;
|
||||||
|
$this->throwAt(0, true);
|
||||||
foreach ($this->getFatalErrorHandlers() as $handler) {
|
$this->displayErrors = $displayErrors;
|
||||||
if ($e = $handler->handleError($error, $exception)) {
|
|
||||||
$exception = $e;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
/**
|
||||||
call_user_func($exceptionHandler, $exception);
|
* Sets a logger for the given channel.
|
||||||
} catch (\Exception $e) {
|
*
|
||||||
// The handler failed. Let PHP handle that now.
|
* @param LoggerInterface $logger A logger interface
|
||||||
throw $exception;
|
* @param string $channel The channel associated with the logger (deprecation, emergency or scream)
|
||||||
|
*
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0. Use setLoggers() or setDefaultLogger() instead.
|
||||||
|
*/
|
||||||
|
public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
|
||||||
|
{
|
||||||
|
$handler = set_error_handler('var_dump', 0);
|
||||||
|
$handler = is_array($handler) ? $handler[0] : null;
|
||||||
|
restore_error_handler();
|
||||||
|
if (!$handler instanceof self) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if ('deprecation' === $channel) {
|
||||||
|
$handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
|
||||||
|
$handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
|
||||||
|
} elseif ('scream' === $channel) {
|
||||||
|
$handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
|
||||||
|
$handler->screamAt(E_ALL | E_STRICT);
|
||||||
|
} elseif ('emergency' === $channel) {
|
||||||
|
$handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
|
||||||
|
$handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0. Use handleError() instead.
|
||||||
|
*/
|
||||||
|
public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
|
||||||
|
{
|
||||||
|
return $this->handleError($level, $message, $file, $line, (array) $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles PHP fatal errors.
|
||||||
|
*
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0. Use handleFatalError() instead.
|
||||||
|
*/
|
||||||
|
public function handleFatal()
|
||||||
|
{
|
||||||
|
static::handleFatalError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@ class FlattenException
|
||||||
foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
|
foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
|
||||||
$exceptions[] = array(
|
$exceptions[] = array(
|
||||||
'message' => $exception->getMessage(),
|
'message' => $exception->getMessage(),
|
||||||
'class' => $exception->getClass(),
|
'class' => $exception->getClass(),
|
||||||
'trace' => $exception->getTrace(),
|
'trace' => $exception->getTrace(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,14 +179,14 @@ class FlattenException
|
||||||
{
|
{
|
||||||
$this->trace = array();
|
$this->trace = array();
|
||||||
$this->trace[] = array(
|
$this->trace[] = array(
|
||||||
'namespace' => '',
|
'namespace' => '',
|
||||||
'short_class' => '',
|
'short_class' => '',
|
||||||
'class' => '',
|
'class' => '',
|
||||||
'type' => '',
|
'type' => '',
|
||||||
'function' => '',
|
'function' => '',
|
||||||
'file' => $file,
|
'file' => $file,
|
||||||
'line' => $line,
|
'line' => $line,
|
||||||
'args' => array(),
|
'args' => array(),
|
||||||
);
|
);
|
||||||
foreach ($trace as $entry) {
|
foreach ($trace as $entry) {
|
||||||
$class = '';
|
$class = '';
|
||||||
|
|
@ -198,14 +198,14 @@ class FlattenException
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->trace[] = array(
|
$this->trace[] = array(
|
||||||
'namespace' => $namespace,
|
'namespace' => $namespace,
|
||||||
'short_class' => $class,
|
'short_class' => $class,
|
||||||
'class' => isset($entry['class']) ? $entry['class'] : '',
|
'class' => isset($entry['class']) ? $entry['class'] : '',
|
||||||
'type' => isset($entry['type']) ? $entry['type'] : '',
|
'type' => isset($entry['type']) ? $entry['type'] : '',
|
||||||
'function' => isset($entry['function']) ? $entry['function'] : null,
|
'function' => isset($entry['function']) ? $entry['function'] : null,
|
||||||
'file' => isset($entry['file']) ? $entry['file'] : null,
|
'file' => isset($entry['file']) ? $entry['file'] : null,
|
||||||
'line' => isset($entry['line']) ? $entry['line'] : null,
|
'line' => isset($entry['line']) ? $entry['line'] : null,
|
||||||
'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
|
'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,29 +34,33 @@ if (!defined('ENT_SUBSTITUTE')) {
|
||||||
class ExceptionHandler
|
class ExceptionHandler
|
||||||
{
|
{
|
||||||
private $debug;
|
private $debug;
|
||||||
private $charset;
|
|
||||||
private $handler;
|
private $handler;
|
||||||
private $caughtBuffer;
|
private $caughtBuffer;
|
||||||
private $caughtLength;
|
private $caughtLength;
|
||||||
|
private $fileLinkFormat;
|
||||||
|
|
||||||
public function __construct($debug = true, $charset = 'UTF-8')
|
public function __construct($debug = true, $fileLinkFormat = null)
|
||||||
{
|
{
|
||||||
$this->debug = $debug;
|
$this->debug = $debug;
|
||||||
$this->charset = $charset;
|
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the exception handler.
|
* Registers the exception handler.
|
||||||
*
|
*
|
||||||
* @param bool $debug
|
* @param bool $debug
|
||||||
*
|
*
|
||||||
* @return ExceptionHandler The registered exception handler
|
* @return ExceptionHandler The registered exception handler
|
||||||
*/
|
*/
|
||||||
public static function register($debug = true)
|
public static function register($debug = true, $fileLinkFormat = null)
|
||||||
{
|
{
|
||||||
$handler = new static($debug);
|
$handler = new static($debug, $fileLinkFormat = null);
|
||||||
|
|
||||||
set_exception_handler(array($handler, 'handle'));
|
$prev = set_exception_handler(array($handler, 'handle'));
|
||||||
|
if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
|
||||||
|
restore_exception_handler();
|
||||||
|
$prev[0]->setExceptionHandler(array($handler, 'handle'));
|
||||||
|
}
|
||||||
|
|
||||||
return $handler;
|
return $handler;
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +83,21 @@ class ExceptionHandler
|
||||||
return $old;
|
return $old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the format for links to source files.
|
||||||
|
*
|
||||||
|
* @param string $format The format for links to source files
|
||||||
|
*
|
||||||
|
* @return string The previous file link format.
|
||||||
|
*/
|
||||||
|
public function setFileLinkFormat($format)
|
||||||
|
{
|
||||||
|
$old = $this->fileLinkFormat;
|
||||||
|
$this->fileLinkFormat = $format;
|
||||||
|
|
||||||
|
return $old;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a response for the given Exception.
|
* Sends a response for the given Exception.
|
||||||
*
|
*
|
||||||
|
|
@ -205,29 +224,26 @@ class ExceptionHandler
|
||||||
$total = $count + 1;
|
$total = $count + 1;
|
||||||
foreach ($exception->toArray() as $position => $e) {
|
foreach ($exception->toArray() as $position => $e) {
|
||||||
$ind = $count - $position + 1;
|
$ind = $count - $position + 1;
|
||||||
$class = $this->abbrClass($e['class']);
|
$class = $this->formatClass($e['class']);
|
||||||
$message = nl2br($e['message']);
|
$message = nl2br(self::utf8Htmlize($e['message']));
|
||||||
$content .= sprintf(<<<EOF
|
$content .= sprintf(<<<EOF
|
||||||
<div class="block_exception clear_fix">
|
<h2 class="block_exception clear_fix">
|
||||||
<h2><span>%d/%d</span> %s: %s</h2>
|
<span class="exception_counter">%d/%d</span>
|
||||||
</div>
|
<span class="exception_title">%s%s:</span>
|
||||||
|
<span class="exception_message">%s</span>
|
||||||
|
</h2>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<ol class="traces list_exception">
|
<ol class="traces list_exception">
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
, $ind, $total, $class, $message);
|
, $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
|
||||||
foreach ($e['trace'] as $trace) {
|
foreach ($e['trace'] as $trace) {
|
||||||
$content .= ' <li>';
|
$content .= ' <li>';
|
||||||
if ($trace['function']) {
|
if ($trace['function']) {
|
||||||
$content .= sprintf('at %s%s%s(%s)', $this->abbrClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
|
$content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
|
||||||
}
|
}
|
||||||
if (isset($trace['file']) && isset($trace['line'])) {
|
if (isset($trace['file']) && isset($trace['line'])) {
|
||||||
if ($linkFormat = ini_get('xdebug.file_link_format')) {
|
$content .= $this->formatPath($trace['file'], $trace['line']);
|
||||||
$link = str_replace(array('%f', '%l'), array($trace['file'], $trace['line']), $linkFormat);
|
|
||||||
$content .= sprintf(' in <a href="%s" title="Go to source">%s line %s</a>', $link, $trace['file'], $trace['line']);
|
|
||||||
} else {
|
|
||||||
$content .= sprintf(' in %s line %s', $trace['file'], $trace['line']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$content .= "</li>\n";
|
$content .= "</li>\n";
|
||||||
}
|
}
|
||||||
|
|
@ -272,12 +288,14 @@ EOF;
|
||||||
.sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
|
.sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
|
||||||
.sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
|
.sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
|
||||||
.sf-reset strong { font-weight:bold; }
|
.sf-reset strong { font-weight:bold; }
|
||||||
.sf-reset a { color:#6c6159; }
|
.sf-reset a { color:#6c6159; cursor: default; }
|
||||||
.sf-reset a img { border:none; }
|
.sf-reset a img { border:none; }
|
||||||
.sf-reset a:hover { text-decoration:underline; }
|
.sf-reset a:hover { text-decoration:underline; }
|
||||||
.sf-reset em { font-style:italic; }
|
.sf-reset em { font-style:italic; }
|
||||||
.sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
|
.sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
|
||||||
.sf-reset h2 span { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; }
|
.sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
|
||||||
|
.sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
|
||||||
|
.sf-reset .exception_message { margin-left: 3em; display: block; }
|
||||||
.sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
|
.sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
|
||||||
.sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
|
.sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
|
||||||
-webkit-border-bottom-right-radius: 16px;
|
-webkit-border-bottom-right-radius: 16px;
|
||||||
|
|
@ -303,8 +321,8 @@ EOF;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
.sf-reset li a { background:none; color:#868686; text-decoration:none; }
|
.sf-reset a { background:none; color:#868686; text-decoration:none; }
|
||||||
.sf-reset li a:hover { background:none; color:#313131; text-decoration:underline; }
|
.sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
|
||||||
.sf-reset ol { padding: 10px 0; }
|
.sf-reset ol { padding: 10px 0; }
|
||||||
.sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
|
.sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
|
||||||
-webkit-border-radius: 10px;
|
-webkit-border-radius: 10px;
|
||||||
|
|
@ -321,7 +339,7 @@ EOF;
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
<meta charset="UTF-8" />
|
||||||
<meta name="robots" content="noindex,nofollow" />
|
<meta name="robots" content="noindex,nofollow" />
|
||||||
<style>
|
<style>
|
||||||
/* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
|
/* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
|
||||||
|
|
@ -340,13 +358,27 @@ EOF;
|
||||||
EOF;
|
EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function abbrClass($class)
|
private function formatClass($class)
|
||||||
{
|
{
|
||||||
$parts = explode('\\', $class);
|
$parts = explode('\\', $class);
|
||||||
|
|
||||||
return sprintf("<abbr title=\"%s\">%s</abbr>", $class, array_pop($parts));
|
return sprintf("<abbr title=\"%s\">%s</abbr>", $class, array_pop($parts));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function formatPath($path, $line)
|
||||||
|
{
|
||||||
|
$path = self::utf8Htmlize($path);
|
||||||
|
$file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
|
||||||
|
|
||||||
|
if ($linkFormat = $this->fileLinkFormat) {
|
||||||
|
$link = str_replace(array('%f', '%l'), array($path, $line), $linkFormat);
|
||||||
|
|
||||||
|
return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(' in <a title="%s line %3$d" ondblclick="var f=this.innerHTML;this.innerHTML=this.title;this.title=f;">%s line %d</a>', $path, $file, $line);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats an array as a string.
|
* Formats an array as a string.
|
||||||
*
|
*
|
||||||
|
|
@ -359,11 +391,11 @@ EOF;
|
||||||
$result = array();
|
$result = array();
|
||||||
foreach ($args as $key => $item) {
|
foreach ($args as $key => $item) {
|
||||||
if ('object' === $item[0]) {
|
if ('object' === $item[0]) {
|
||||||
$formattedValue = sprintf("<em>object</em>(%s)", $this->abbrClass($item[1]));
|
$formattedValue = sprintf("<em>object</em>(%s)", $this->formatClass($item[1]));
|
||||||
} elseif ('array' === $item[0]) {
|
} elseif ('array' === $item[0]) {
|
||||||
$formattedValue = sprintf("<em>array</em>(%s)", is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
|
$formattedValue = sprintf("<em>array</em>(%s)", is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
|
||||||
} elseif ('string' === $item[0]) {
|
} elseif ('string' === $item[0]) {
|
||||||
$formattedValue = sprintf("'%s'", htmlspecialchars($item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset));
|
$formattedValue = sprintf("'%s'", self::utf8Htmlize($item[1]));
|
||||||
} elseif ('null' === $item[0]) {
|
} elseif ('null' === $item[0]) {
|
||||||
$formattedValue = '<em>null</em>';
|
$formattedValue = '<em>null</em>';
|
||||||
} elseif ('boolean' === $item[0]) {
|
} elseif ('boolean' === $item[0]) {
|
||||||
|
|
@ -371,7 +403,7 @@ EOF;
|
||||||
} elseif ('resource' === $item[0]) {
|
} elseif ('resource' === $item[0]) {
|
||||||
$formattedValue = '<em>resource</em>';
|
$formattedValue = '<em>resource</em>';
|
||||||
} else {
|
} else {
|
||||||
$formattedValue = str_replace("\n", '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), true));
|
$formattedValue = str_replace("\n", '', var_export(self::utf8Htmlize((string) $item[1]), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
|
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
|
||||||
|
|
@ -380,6 +412,25 @@ EOF;
|
||||||
return implode(', ', $result);
|
return implode(', ', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an UTF-8 and HTML encoded string
|
||||||
|
*/
|
||||||
|
protected static function utf8Htmlize($str)
|
||||||
|
{
|
||||||
|
if (!preg_match('//u', $str) && function_exists('iconv')) {
|
||||||
|
set_error_handler('var_dump', 0);
|
||||||
|
$charset = ini_get('default_charset');
|
||||||
|
if ('UTF-8' === $charset || $str !== @iconv($charset, $charset, $str)) {
|
||||||
|
$charset = 'CP1252';
|
||||||
|
}
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
|
$str = iconv($charset, 'UTF-8', $str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return htmlspecialchars($str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -51,29 +51,23 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||||
if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
|
if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
|
||||||
$className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
|
$className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
|
||||||
$namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
|
$namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
|
||||||
$message = sprintf(
|
$message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
|
||||||
'Attempted to load %s "%s" from namespace "%s" in %s line %d. Do you need to "use" it from another namespace?',
|
$tail = ' for another namespace?';
|
||||||
$typeName,
|
|
||||||
$className,
|
|
||||||
$namespacePrefix,
|
|
||||||
$error['file'],
|
|
||||||
$error['line']
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
$className = $fullyQualifiedClassName;
|
$className = $fullyQualifiedClassName;
|
||||||
$message = sprintf(
|
$message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
|
||||||
'Attempted to load %s "%s" from the global namespace in %s line %d. Did you forget a use statement for this %s?',
|
$tail = '?';
|
||||||
$typeName,
|
|
||||||
$className,
|
|
||||||
$error['file'],
|
|
||||||
$error['line'],
|
|
||||||
$typeName
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($classes = $this->getClassCandidates($className)) {
|
if ($candidates = $this->getClassCandidates($className)) {
|
||||||
$message .= sprintf(' Perhaps you need to add a use statement for one of the following: %s.', implode(', ', $classes));
|
$tail = array_pop($candidates).'"?';
|
||||||
|
if ($candidates) {
|
||||||
|
$tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
|
||||||
|
} else {
|
||||||
|
$tail = ' for "'.$tail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
$message .= "\nDid you forget a \"use\" statement".$tail;
|
||||||
|
|
||||||
return new ClassNotFoundException($message, $exception);
|
return new ClassNotFoundException($message, $exception);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,21 +47,10 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
|
||||||
if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
|
if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
|
||||||
$functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
|
$functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
|
||||||
$namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
|
$namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
|
||||||
$message = sprintf(
|
$message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
|
||||||
'Attempted to call function "%s" from namespace "%s" in %s line %d.',
|
|
||||||
$functionName,
|
|
||||||
$namespacePrefix,
|
|
||||||
$error['file'],
|
|
||||||
$error['line']
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
$functionName = $fullyQualifiedFunctionName;
|
$functionName = $fullyQualifiedFunctionName;
|
||||||
$message = sprintf(
|
$message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
|
||||||
'Attempted to call function "%s" from the global namespace in %s line %d.',
|
|
||||||
$functionName,
|
|
||||||
$error['file'],
|
|
||||||
$error['line']
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$candidates = array();
|
$candidates = array();
|
||||||
|
|
@ -81,9 +70,13 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
|
||||||
|
|
||||||
if ($candidates) {
|
if ($candidates) {
|
||||||
sort($candidates);
|
sort($candidates);
|
||||||
$message .= ' Did you mean to call: '.implode(', ', array_map(function ($val) {
|
$last = array_pop($candidates).'"?';
|
||||||
return '"'.$val.'"';
|
if ($candidates) {
|
||||||
}, $candidates)).'?';
|
$candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
|
||||||
|
} else {
|
||||||
|
$candidates = '"'.$last;
|
||||||
|
}
|
||||||
|
$message .= "\nDid you mean to call ".$candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UndefinedFunctionException($message, $exception);
|
return new UndefinedFunctionException($message, $exception);
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
|
||||||
$className = $matches[1];
|
$className = $matches[1];
|
||||||
$methodName = $matches[2];
|
$methodName = $matches[2];
|
||||||
|
|
||||||
$message = sprintf('Attempted to call method "%s" on class "%s" in %s line %d.', $methodName, $className, $error['file'], $error['line']);
|
$message = sprintf('Attempted to call method "%s" on class "%s".', $methodName, $className);
|
||||||
|
|
||||||
$candidates = array();
|
$candidates = array();
|
||||||
foreach (get_class_methods($className) as $definedMethodName) {
|
foreach (get_class_methods($className) as $definedMethodName) {
|
||||||
|
|
@ -46,7 +46,13 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
|
||||||
|
|
||||||
if ($candidates) {
|
if ($candidates) {
|
||||||
sort($candidates);
|
sort($candidates);
|
||||||
$message .= sprintf(' Did you mean to call: "%s"?', implode('", "', $candidates));
|
$last = array_pop($candidates).'"?';
|
||||||
|
if ($candidates) {
|
||||||
|
$candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
|
||||||
|
} else {
|
||||||
|
$candidates = '"'.$last;
|
||||||
|
}
|
||||||
|
$message .= "\nDid you mean to call ".$candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UndefinedMethodException($message, $exception);
|
return new UndefinedMethodException($message, $exception);
|
||||||
|
|
|
||||||
|
|
@ -6,23 +6,26 @@ Debug provides tools to make debugging easier.
|
||||||
Enabling all debug tools is as easy as calling the `enable()` method on the
|
Enabling all debug tools is as easy as calling the `enable()` method on the
|
||||||
main `Debug` class:
|
main `Debug` class:
|
||||||
|
|
||||||
use Symfony\Component\Debug\Debug;
|
```php
|
||||||
|
use Symfony\Component\Debug\Debug;
|
||||||
|
|
||||||
Debug::enable();
|
Debug::enable();
|
||||||
|
```
|
||||||
|
|
||||||
You can also use the tools individually:
|
You can also use the tools individually:
|
||||||
|
|
||||||
use Symfony\Component\Debug\ErrorHandler;
|
```php
|
||||||
use Symfony\Component\Debug\ExceptionHandler;
|
use Symfony\Component\Debug\ErrorHandler;
|
||||||
|
use Symfony\Component\Debug\ExceptionHandler;
|
||||||
|
|
||||||
error_reporting(-1);
|
if ('cli' !== php_sapi_name()) {
|
||||||
|
ini_set('display_errors', 0);
|
||||||
ErrorHandler::register($errorReportingLevel);
|
ExceptionHandler::register();
|
||||||
if ('cli' !== php_sapi_name()) {
|
} elseif (!ini_get('log_errors') || ini_get('error_log')) {
|
||||||
ExceptionHandler::register();
|
ini_set('display_errors', 1);
|
||||||
} elseif (!ini_get('log_errors') || ini_get('error_log')) {
|
}
|
||||||
ini_set('display_errors', 1);
|
ErrorHandler::register($errorReportingLevel);
|
||||||
}
|
```
|
||||||
|
|
||||||
Note that the `Debug::enable()` call also registers the debug class loader
|
Note that the `Debug::enable()` call also registers the debug class loader
|
||||||
from the Symfony ClassLoader component when available.
|
from the Symfony ClassLoader component when available.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
Symfony Debug Extension
|
||||||
|
=======================
|
||||||
|
|
||||||
|
This extension adds a ``symfony_zval_info($key, $array, $options = 0)`` function that:
|
||||||
|
|
||||||
|
- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP,
|
||||||
|
- does work with references, preventing memory copying.
|
||||||
|
|
||||||
|
Its behavior is about the same as:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function symfony_zval_info($key, $array, $options = 0)
|
||||||
|
{
|
||||||
|
// $options is currently not used, but could be in future version.
|
||||||
|
|
||||||
|
if (!array_key_exists($key, $array)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = array(
|
||||||
|
'type' => gettype($array[$key]),
|
||||||
|
'zval_hash' => /* hashed memory address of $array[$key] */,
|
||||||
|
'zval_refcount' => /* internal zval refcount of $array[$key] */,
|
||||||
|
'zval_isref' => /* is_ref status of $array[$key] */,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch ($info['type']) {
|
||||||
|
case 'object':
|
||||||
|
$info += array(
|
||||||
|
'object_class' => get_class($array[$key]),
|
||||||
|
'object_refcount' => /* internal object refcount of $array[$key] */,
|
||||||
|
'object_hash' => spl_object_hash($array[$key]),
|
||||||
|
'object_handle' => /* internal object handle $array[$key] */,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'resource':
|
||||||
|
$info += array(
|
||||||
|
'resource_handle' => (int) $array[$key],
|
||||||
|
'resource_type' => get_resource_type($array[$key]),
|
||||||
|
'resource_refcount' => /* internal resource refcount of $array[$key] */,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'array':
|
||||||
|
$info += array(
|
||||||
|
'array_count' => count($array[$key]),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'string':
|
||||||
|
$info += array(
|
||||||
|
'strlen' => strlen($array[$key]),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
To enable the extension from source, run:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
phpize
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
dnl $Id$
|
||||||
|
dnl config.m4 for extension symfony_debug
|
||||||
|
|
||||||
|
dnl Comments in this file start with the string 'dnl'.
|
||||||
|
dnl Remove where necessary. This file will not work
|
||||||
|
dnl without editing.
|
||||||
|
|
||||||
|
dnl If your extension references something external, use with:
|
||||||
|
|
||||||
|
dnl PHP_ARG_WITH(symfony_debug, for symfony_debug support,
|
||||||
|
dnl Make sure that the comment is aligned:
|
||||||
|
dnl [ --with-symfony_debug Include symfony_debug support])
|
||||||
|
|
||||||
|
dnl Otherwise use enable:
|
||||||
|
|
||||||
|
PHP_ARG_ENABLE(symfony_debug, whether to enable symfony_debug support,
|
||||||
|
dnl Make sure that the comment is aligned:
|
||||||
|
[ --enable-symfony_debug Enable symfony_debug support])
|
||||||
|
|
||||||
|
if test "$PHP_SYMFONY_DEBUG" != "no"; then
|
||||||
|
dnl Write more examples of tests here...
|
||||||
|
|
||||||
|
dnl # --with-symfony_debug -> check with-path
|
||||||
|
dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
|
||||||
|
dnl SEARCH_FOR="/include/symfony_debug.h" # you most likely want to change this
|
||||||
|
dnl if test -r $PHP_SYMFONY_DEBUG/$SEARCH_FOR; then # path given as parameter
|
||||||
|
dnl SYMFONY_DEBUG_DIR=$PHP_SYMFONY_DEBUG
|
||||||
|
dnl else # search default path list
|
||||||
|
dnl AC_MSG_CHECKING([for symfony_debug files in default path])
|
||||||
|
dnl for i in $SEARCH_PATH ; do
|
||||||
|
dnl if test -r $i/$SEARCH_FOR; then
|
||||||
|
dnl SYMFONY_DEBUG_DIR=$i
|
||||||
|
dnl AC_MSG_RESULT(found in $i)
|
||||||
|
dnl fi
|
||||||
|
dnl done
|
||||||
|
dnl fi
|
||||||
|
dnl
|
||||||
|
dnl if test -z "$SYMFONY_DEBUG_DIR"; then
|
||||||
|
dnl AC_MSG_RESULT([not found])
|
||||||
|
dnl AC_MSG_ERROR([Please reinstall the symfony_debug distribution])
|
||||||
|
dnl fi
|
||||||
|
|
||||||
|
dnl # --with-symfony_debug -> add include path
|
||||||
|
dnl PHP_ADD_INCLUDE($SYMFONY_DEBUG_DIR/include)
|
||||||
|
|
||||||
|
dnl # --with-symfony_debug -> check for lib and symbol presence
|
||||||
|
dnl LIBNAME=symfony_debug # you may want to change this
|
||||||
|
dnl LIBSYMBOL=symfony_debug # you most likely want to change this
|
||||||
|
|
||||||
|
dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
|
||||||
|
dnl [
|
||||||
|
dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DEBUG_DIR/lib, SYMFONY_DEBUG_SHARED_LIBADD)
|
||||||
|
dnl AC_DEFINE(HAVE_SYMFONY_DEBUGLIB,1,[ ])
|
||||||
|
dnl ],[
|
||||||
|
dnl AC_MSG_ERROR([wrong symfony_debug lib version or lib not found])
|
||||||
|
dnl ],[
|
||||||
|
dnl -L$SYMFONY_DEBUG_DIR/lib -lm
|
||||||
|
dnl ])
|
||||||
|
dnl
|
||||||
|
dnl PHP_SUBST(SYMFONY_DEBUG_SHARED_LIBADD)
|
||||||
|
|
||||||
|
PHP_NEW_EXTENSION(symfony_debug, symfony_debug.c, $ext_shared)
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// $Id$
|
||||||
|
// vim:ft=javascript
|
||||||
|
|
||||||
|
// If your extension references something external, use ARG_WITH
|
||||||
|
// ARG_WITH("symfony_debug", "for symfony_debug support", "no");
|
||||||
|
|
||||||
|
// Otherwise, use ARG_ENABLE
|
||||||
|
// ARG_ENABLE("symfony_debug", "enable symfony_debug support", "no");
|
||||||
|
|
||||||
|
if (PHP_SYMFONY_DEBUG != "no") {
|
||||||
|
EXTENSION("symfony_debug", "symfony_debug.c");
|
||||||
|
}
|
||||||
|
|
||||||
55
core/vendor/symfony/debug/Symfony/Component/Debug/Resources/ext/php_symfony_debug.h
vendored
Normal file
55
core/vendor/symfony/debug/Symfony/Component/Debug/Resources/ext/php_symfony_debug.h
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PHP_SYMFONY_DEBUG_H
|
||||||
|
#define PHP_SYMFONY_DEBUG_H
|
||||||
|
|
||||||
|
extern zend_module_entry symfony_debug_module_entry;
|
||||||
|
#define phpext_symfony_debug_ptr &symfony_debug_module_entry
|
||||||
|
|
||||||
|
#define PHP_SYMFONY_DEBUG_VERSION "1.0"
|
||||||
|
|
||||||
|
#ifdef PHP_WIN32
|
||||||
|
# define PHP_SYMFONY_DEBUG_API __declspec(dllexport)
|
||||||
|
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
# define PHP_SYMFONY_DEBUG_API __attribute__ ((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define PHP_SYMFONY_DEBUG_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ZTS
|
||||||
|
#include "TSRM.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ZEND_BEGIN_MODULE_GLOBALS(symfony_debug)
|
||||||
|
intptr_t req_rand_init;
|
||||||
|
ZEND_END_MODULE_GLOBALS(symfony_debug)
|
||||||
|
|
||||||
|
PHP_MINIT_FUNCTION(symfony_debug);
|
||||||
|
PHP_MSHUTDOWN_FUNCTION(symfony_debug);
|
||||||
|
PHP_RINIT_FUNCTION(symfony_debug);
|
||||||
|
PHP_RSHUTDOWN_FUNCTION(symfony_debug);
|
||||||
|
PHP_MINFO_FUNCTION(symfony_debug);
|
||||||
|
PHP_GINIT_FUNCTION(symfony_debug);
|
||||||
|
PHP_GSHUTDOWN_FUNCTION(symfony_debug);
|
||||||
|
|
||||||
|
PHP_FUNCTION(symfony_zval_info);
|
||||||
|
|
||||||
|
static char *_symfony_debug_memory_address_hash(void *);
|
||||||
|
static const char *_symfony_debug_zval_type(zval *);
|
||||||
|
static const char* _symfony_debug_get_resource_type(long);
|
||||||
|
static int _symfony_debug_get_resource_refcount(long);
|
||||||
|
|
||||||
|
#ifdef ZTS
|
||||||
|
#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v)
|
||||||
|
#else
|
||||||
|
#define SYMFONY_DEBUG_G(v) (symfony_debug_globals.v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PHP_SYMFONY_DEBUG_H */
|
||||||
224
core/vendor/symfony/debug/Symfony/Component/Debug/Resources/ext/symfony_debug.c
vendored
Normal file
224
core/vendor/symfony/debug/Symfony/Component/Debug/Resources/ext/symfony_debug.c
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "php_ini.h"
|
||||||
|
#include "ext/standard/info.h"
|
||||||
|
#include "php_symfony_debug.h"
|
||||||
|
#include "ext/standard/php_rand.h"
|
||||||
|
#include "ext/standard/php_lcg.h"
|
||||||
|
#include "ext/spl/php_spl.h"
|
||||||
|
#include "Zend/zend_gc.h"
|
||||||
|
|
||||||
|
ZEND_DECLARE_MODULE_GLOBALS(symfony_debug)
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(symfony_zval_arginfo, 0, 0, 2)
|
||||||
|
ZEND_ARG_INFO(0, key)
|
||||||
|
ZEND_ARG_ARRAY_INFO(0, array, 0)
|
||||||
|
ZEND_ARG_INFO(0, options)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
const zend_function_entry symfony_debug_functions[] = {
|
||||||
|
PHP_FE(symfony_zval_info, symfony_zval_arginfo)
|
||||||
|
PHP_FE_END
|
||||||
|
};
|
||||||
|
|
||||||
|
PHP_FUNCTION(symfony_zval_info)
|
||||||
|
{
|
||||||
|
zval *key = NULL, *arg = NULL;
|
||||||
|
zval **data = NULL;
|
||||||
|
HashTable *array = NULL;
|
||||||
|
long options = 0;
|
||||||
|
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zh|l", &key, &array, &options) == FAILURE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Z_TYPE_P(key)) {
|
||||||
|
case IS_STRING:
|
||||||
|
if (zend_symtable_find(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&data) == FAILURE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IS_LONG:
|
||||||
|
if (zend_hash_index_find(array, Z_LVAL_P(key), (void **)&data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = *data;
|
||||||
|
|
||||||
|
array_init(return_value);
|
||||||
|
|
||||||
|
add_assoc_string(return_value, "type", (char *)_symfony_debug_zval_type(arg), 1);
|
||||||
|
add_assoc_stringl(return_value, "zval_hash", _symfony_debug_memory_address_hash((void *)arg), 16, 1);
|
||||||
|
add_assoc_long(return_value, "zval_refcount", Z_REFCOUNT_P(arg));
|
||||||
|
add_assoc_bool(return_value, "zval_isref", (zend_bool)Z_ISREF_P(arg));
|
||||||
|
|
||||||
|
if (Z_TYPE_P(arg) == IS_OBJECT) {
|
||||||
|
static char hash[33] = {0};
|
||||||
|
php_spl_object_hash(arg, (char *)hash);
|
||||||
|
add_assoc_stringl(return_value, "object_class", (char *)Z_OBJCE_P(arg)->name, Z_OBJCE_P(arg)->name_length, 1);
|
||||||
|
add_assoc_long(return_value, "object_refcount", EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(arg)].bucket.obj.refcount);
|
||||||
|
add_assoc_string(return_value, "object_hash", hash, 1);
|
||||||
|
add_assoc_long(return_value, "object_handle", Z_OBJ_HANDLE_P(arg));
|
||||||
|
} else if (Z_TYPE_P(arg) == IS_ARRAY) {
|
||||||
|
add_assoc_long(return_value, "array_count", zend_hash_num_elements(Z_ARRVAL_P(arg)));
|
||||||
|
} else if(Z_TYPE_P(arg) == IS_RESOURCE) {
|
||||||
|
add_assoc_long(return_value, "resource_handle", Z_LVAL_P(arg));
|
||||||
|
add_assoc_string(return_value, "resource_type", (char *)_symfony_debug_get_resource_type(Z_LVAL_P(arg)), 1);
|
||||||
|
add_assoc_long(return_value, "resource_refcount", _symfony_debug_get_resource_refcount(Z_LVAL_P(arg)));
|
||||||
|
} else if (Z_TYPE_P(arg) == IS_STRING) {
|
||||||
|
add_assoc_long(return_value, "strlen", Z_STRLEN_P(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* _symfony_debug_get_resource_type(long rsid)
|
||||||
|
{
|
||||||
|
const char *res_type;
|
||||||
|
res_type = zend_rsrc_list_get_rsrc_type(rsid);
|
||||||
|
|
||||||
|
if (!res_type) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return res_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _symfony_debug_get_resource_refcount(long rsid)
|
||||||
|
{
|
||||||
|
zend_rsrc_list_entry *le;
|
||||||
|
|
||||||
|
if (zend_hash_index_find(&EG(regular_list), rsid, (void **) &le)==SUCCESS) {
|
||||||
|
return le->refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *_symfony_debug_memory_address_hash(void *address)
|
||||||
|
{
|
||||||
|
static char result[17] = {0};
|
||||||
|
intptr_t address_rand;
|
||||||
|
|
||||||
|
if (!SYMFONY_DEBUG_G(req_rand_init)) {
|
||||||
|
if (!BG(mt_rand_is_seeded)) {
|
||||||
|
php_mt_srand(GENERATE_SEED() TSRMLS_CC);
|
||||||
|
}
|
||||||
|
SYMFONY_DEBUG_G(req_rand_init) = (intptr_t)php_mt_rand();
|
||||||
|
}
|
||||||
|
|
||||||
|
address_rand = (intptr_t)address ^ SYMFONY_DEBUG_G(req_rand_init);
|
||||||
|
|
||||||
|
snprintf(result, 17, "%016zx", address_rand);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *_symfony_debug_zval_type(zval *zv)
|
||||||
|
{
|
||||||
|
switch (Z_TYPE_P(zv)) {
|
||||||
|
case IS_NULL:
|
||||||
|
return "NULL";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_BOOL:
|
||||||
|
return "boolean";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_LONG:
|
||||||
|
return "integer";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_DOUBLE:
|
||||||
|
return "double";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_STRING:
|
||||||
|
return "string";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_ARRAY:
|
||||||
|
return "array";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IS_OBJECT:
|
||||||
|
return "object";
|
||||||
|
|
||||||
|
case IS_RESOURCE:
|
||||||
|
return "resource";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "unknown type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_module_entry symfony_debug_module_entry = {
|
||||||
|
STANDARD_MODULE_HEADER,
|
||||||
|
"symfony_debug",
|
||||||
|
symfony_debug_functions,
|
||||||
|
PHP_MINIT(symfony_debug),
|
||||||
|
PHP_MSHUTDOWN(symfony_debug),
|
||||||
|
PHP_RINIT(symfony_debug),
|
||||||
|
PHP_RSHUTDOWN(symfony_debug),
|
||||||
|
PHP_MINFO(symfony_debug),
|
||||||
|
PHP_SYMFONY_DEBUG_VERSION,
|
||||||
|
PHP_MODULE_GLOBALS(symfony_debug),
|
||||||
|
PHP_GINIT(symfony_debug),
|
||||||
|
PHP_GSHUTDOWN(symfony_debug),
|
||||||
|
NULL,
|
||||||
|
STANDARD_MODULE_PROPERTIES_EX
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef COMPILE_DL_SYMFONY_DEBUG
|
||||||
|
ZEND_GET_MODULE(symfony_debug)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PHP_GINIT_FUNCTION(symfony_debug)
|
||||||
|
{
|
||||||
|
symfony_debug_globals->req_rand_init = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_GSHUTDOWN_FUNCTION(symfony_debug)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_MINIT_FUNCTION(symfony_debug)
|
||||||
|
{
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_MSHUTDOWN_FUNCTION(symfony_debug)
|
||||||
|
{
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_RINIT_FUNCTION(symfony_debug)
|
||||||
|
{
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_RSHUTDOWN_FUNCTION(symfony_debug)
|
||||||
|
{
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_MINFO_FUNCTION(symfony_debug)
|
||||||
|
{
|
||||||
|
php_info_print_table_start();
|
||||||
|
php_info_print_table_header(2, "Symfony Debug support", "enabled");
|
||||||
|
php_info_print_table_header(2, "Symfony Debug version", PHP_SYMFONY_DEBUG_VERSION);
|
||||||
|
php_info_print_table_end();
|
||||||
|
}
|
||||||
151
core/vendor/symfony/debug/Symfony/Component/Debug/Resources/ext/tests/001.phpt
vendored
Normal file
151
core/vendor/symfony/debug/Symfony/Component/Debug/Resources/ext/tests/001.phpt
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
--TEST--
|
||||||
|
Test symfony_zval_info API
|
||||||
|
--SKIPIF--
|
||||||
|
<?php if (!extension_loaded("symfony_debug")) print "skip"; ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$int = 42;
|
||||||
|
$float = 42.42;
|
||||||
|
$str = "foobar";
|
||||||
|
$object = new StdClass;
|
||||||
|
$array = array('foo', 'bar');
|
||||||
|
$resource = tmpfile();
|
||||||
|
$null = null;
|
||||||
|
$bool = true;
|
||||||
|
|
||||||
|
$anotherint = 42;
|
||||||
|
$refcount2 = &$anotherint;
|
||||||
|
|
||||||
|
$var = array('int' => $int,
|
||||||
|
'float' => $float,
|
||||||
|
'str' => $str,
|
||||||
|
'object' => $object,
|
||||||
|
'array' => $array,
|
||||||
|
'resource' => $resource,
|
||||||
|
'null' => $null,
|
||||||
|
'bool' => $bool,
|
||||||
|
'refcount' => &$refcount2);
|
||||||
|
|
||||||
|
var_dump(symfony_zval_info('int', $var));
|
||||||
|
var_dump(symfony_zval_info('float', $var));
|
||||||
|
var_dump(symfony_zval_info('str', $var));
|
||||||
|
var_dump(symfony_zval_info('object', $var));
|
||||||
|
var_dump(symfony_zval_info('array', $var));
|
||||||
|
var_dump(symfony_zval_info('resource', $var));
|
||||||
|
var_dump(symfony_zval_info('null', $var));
|
||||||
|
var_dump(symfony_zval_info('bool', $var));
|
||||||
|
|
||||||
|
var_dump(symfony_zval_info('refcount', $var));
|
||||||
|
var_dump(symfony_zval_info('not-exist', $var));
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
array(4) {
|
||||||
|
["type"]=>
|
||||||
|
string(7) "integer"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
}
|
||||||
|
array(4) {
|
||||||
|
["type"]=>
|
||||||
|
string(6) "double"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
}
|
||||||
|
array(5) {
|
||||||
|
["type"]=>
|
||||||
|
string(6) "string"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
["strlen"]=>
|
||||||
|
int(6)
|
||||||
|
}
|
||||||
|
array(8) {
|
||||||
|
["type"]=>
|
||||||
|
string(6) "object"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
["object_class"]=>
|
||||||
|
string(8) "stdClass"
|
||||||
|
["object_refcount"]=>
|
||||||
|
int(1)
|
||||||
|
["object_hash"]=>
|
||||||
|
string(32) "%s"
|
||||||
|
["object_handle"]=>
|
||||||
|
int(1)
|
||||||
|
}
|
||||||
|
array(5) {
|
||||||
|
["type"]=>
|
||||||
|
string(5) "array"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
["array_count"]=>
|
||||||
|
int(2)
|
||||||
|
}
|
||||||
|
array(7) {
|
||||||
|
["type"]=>
|
||||||
|
string(8) "resource"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
["resource_handle"]=>
|
||||||
|
int(4)
|
||||||
|
["resource_type"]=>
|
||||||
|
string(6) "stream"
|
||||||
|
["resource_refcount"]=>
|
||||||
|
int(1)
|
||||||
|
}
|
||||||
|
array(4) {
|
||||||
|
["type"]=>
|
||||||
|
string(4) "NULL"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
}
|
||||||
|
array(4) {
|
||||||
|
["type"]=>
|
||||||
|
string(7) "boolean"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(2)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(false)
|
||||||
|
}
|
||||||
|
array(4) {
|
||||||
|
["type"]=>
|
||||||
|
string(7) "integer"
|
||||||
|
["zval_hash"]=>
|
||||||
|
string(16) "%s"
|
||||||
|
["zval_refcount"]=>
|
||||||
|
int(3)
|
||||||
|
["zval_isref"]=>
|
||||||
|
bool(true)
|
||||||
|
}
|
||||||
|
NULL
|
||||||
|
|
@ -106,11 +106,11 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals(E_STRICT, $exception->getSeverity());
|
$this->assertEquals(E_STRICT, $exception->getSeverity());
|
||||||
$this->assertStringStartsWith(__FILE__, $exception->getFile());
|
$this->assertStringStartsWith(__FILE__, $exception->getFile());
|
||||||
$this->assertRegexp('/^Runtime Notice: Declaration/', $exception->getMessage());
|
$this->assertRegexp('/^Runtime Notice: Declaration/', $exception->getMessage());
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
restore_exception_handler();
|
restore_exception_handler();
|
||||||
|
|
||||||
throw $e;
|
throw $exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace Symfony\Component\Debug\Tests;
|
namespace Symfony\Component\Debug\Tests;
|
||||||
|
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
use Symfony\Component\Debug\ErrorHandler;
|
use Symfony\Component\Debug\ErrorHandler;
|
||||||
use Symfony\Component\Debug\Exception\ContextErrorException;
|
use Symfony\Component\Debug\Exception\ContextErrorException;
|
||||||
|
|
||||||
|
|
@ -18,6 +19,7 @@ use Symfony\Component\Debug\Exception\ContextErrorException;
|
||||||
* ErrorHandlerTest
|
* ErrorHandlerTest
|
||||||
*
|
*
|
||||||
* @author Robert Schönthal <seroscho@googlemail.com>
|
* @author Robert Schönthal <seroscho@googlemail.com>
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
@ -44,6 +46,46 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
error_reporting($this->errorReporting);
|
error_reporting($this->errorReporting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRegister()
|
||||||
|
{
|
||||||
|
$handler = ErrorHandler::register();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->assertInstanceOf('Symfony\Component\Debug\ErrorHandler', $handler);
|
||||||
|
$this->assertSame($handler, ErrorHandler::register());
|
||||||
|
|
||||||
|
$newHandler = new ErrorHandler();
|
||||||
|
|
||||||
|
$this->assertSame($newHandler, ErrorHandler::register($newHandler, false));
|
||||||
|
$h = set_error_handler('var_dump');
|
||||||
|
restore_error_handler();
|
||||||
|
$this->assertSame(array($handler, 'handleError'), $h);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->assertSame($newHandler, ErrorHandler::register($newHandler, true));
|
||||||
|
$h = set_error_handler('var_dump');
|
||||||
|
restore_error_handler();
|
||||||
|
$this->assertSame(array($newHandler, 'handleError'), $h);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
|
if (isset($e)) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
|
if (isset($e)) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testNotice()
|
public function testNotice()
|
||||||
{
|
{
|
||||||
ErrorHandler::register();
|
ErrorHandler::register();
|
||||||
|
|
@ -54,6 +96,8 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
} catch (ContextErrorException $exception) {
|
} catch (ContextErrorException $exception) {
|
||||||
// if an exception is thrown, the test passed
|
// if an exception is thrown, the test passed
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
$this->assertEquals(E_NOTICE, $exception->getSeverity());
|
$this->assertEquals(E_NOTICE, $exception->getSeverity());
|
||||||
$this->assertEquals(__FILE__, $exception->getFile());
|
$this->assertEquals(__FILE__, $exception->getFile());
|
||||||
$this->assertRegexp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
|
$this->assertRegexp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
|
||||||
|
|
@ -62,7 +106,7 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
$trace = $exception->getTrace();
|
$trace = $exception->getTrace();
|
||||||
$this->assertEquals(__FILE__, $trace[0]['file']);
|
$this->assertEquals(__FILE__, $trace[0]['file']);
|
||||||
$this->assertEquals('Symfony\Component\Debug\ErrorHandler', $trace[0]['class']);
|
$this->assertEquals('Symfony\Component\Debug\ErrorHandler', $trace[0]['class']);
|
||||||
$this->assertEquals('handle', $trace[0]['function']);
|
$this->assertEquals('handleError', $trace[0]['function']);
|
||||||
$this->assertEquals('->', $trace[0]['type']);
|
$this->assertEquals('->', $trace[0]['type']);
|
||||||
|
|
||||||
$this->assertEquals(__FILE__, $trace[1]['file']);
|
$this->assertEquals(__FILE__, $trace[1]['file']);
|
||||||
|
|
@ -70,16 +114,16 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals('triggerNotice', $trace[1]['function']);
|
$this->assertEquals('triggerNotice', $trace[1]['function']);
|
||||||
$this->assertEquals('::', $trace[1]['type']);
|
$this->assertEquals('::', $trace[1]['type']);
|
||||||
|
|
||||||
|
$this->assertEquals(__FILE__, $trace[1]['file']);
|
||||||
$this->assertEquals(__CLASS__, $trace[2]['class']);
|
$this->assertEquals(__CLASS__, $trace[2]['class']);
|
||||||
$this->assertEquals('testNotice', $trace[2]['function']);
|
$this->assertEquals(__FUNCTION__, $trace[2]['function']);
|
||||||
$this->assertEquals('->', $trace[2]['type']);
|
$this->assertEquals('->', $trace[2]['type']);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_error_handler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy function to test trace in error handler.
|
// dummy function to test trace in error handler.
|
||||||
|
|
@ -93,78 +137,257 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
public function testConstruct()
|
public function testConstruct()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$handler = ErrorHandler::register(3);
|
$handler = ErrorHandler::register();
|
||||||
|
$handler->throwAt(3, true);
|
||||||
$level = new \ReflectionProperty($handler, 'level');
|
$this->assertEquals(3 | E_RECOVERABLE_ERROR | E_USER_ERROR, $handler->throwAt(0));
|
||||||
$level->setAccessible(true);
|
|
||||||
|
|
||||||
$this->assertEquals(3, $level->getValue($handler));
|
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHandle()
|
public function testDefaultLogger()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$handler = ErrorHandler::register(0);
|
$handler = ErrorHandler::register();
|
||||||
$this->assertFalse($handler->handle(0, 'foo', 'foo.php', 12, array()));
|
|
||||||
|
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||||
|
|
||||||
|
$handler->setDefaultLogger($logger, E_NOTICE);
|
||||||
|
$handler->setDefaultLogger($logger, array(E_USER_NOTICE => LogLevel::CRITICAL));
|
||||||
|
|
||||||
|
$loggers = array(
|
||||||
|
E_DEPRECATED => array(null, LogLevel::INFO),
|
||||||
|
E_USER_DEPRECATED => array(null, LogLevel::INFO),
|
||||||
|
E_NOTICE => array($logger, LogLevel::NOTICE),
|
||||||
|
E_USER_NOTICE => array($logger, LogLevel::CRITICAL),
|
||||||
|
E_STRICT => array(null, LogLevel::NOTICE),
|
||||||
|
E_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_USER_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_COMPILE_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_CORE_WARNING => array(null, LogLevel::WARNING),
|
||||||
|
E_USER_ERROR => array(null, LogLevel::ERROR),
|
||||||
|
E_RECOVERABLE_ERROR => array(null, LogLevel::ERROR),
|
||||||
|
E_COMPILE_ERROR => array(null, LogLevel::EMERGENCY),
|
||||||
|
E_PARSE => array(null, LogLevel::EMERGENCY),
|
||||||
|
E_ERROR => array(null, LogLevel::EMERGENCY),
|
||||||
|
E_CORE_ERROR => array(null, LogLevel::EMERGENCY),
|
||||||
|
);
|
||||||
|
$this->assertSame($loggers, $handler->setLoggers(array()));
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
$handler = ErrorHandler::register(3);
|
throw $e;
|
||||||
$this->assertFalse($handler->handle(4, 'foo', 'foo.php', 12, array()));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleError()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$handler = ErrorHandler::register();
|
||||||
|
$handler->throwAt(0, true);
|
||||||
|
$this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, array()));
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
$handler = ErrorHandler::register(3);
|
$handler = ErrorHandler::register();
|
||||||
|
$handler->throwAt(3, true);
|
||||||
|
$this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, array()));
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
|
$handler = ErrorHandler::register();
|
||||||
|
$handler->throwAt(3, true);
|
||||||
try {
|
try {
|
||||||
$handler->handle(111, 'foo', 'foo.php', 12, array());
|
$handler->handleError(4, 'foo', 'foo.php', 12, array());
|
||||||
} catch (\ErrorException $e) {
|
} catch (\ErrorException $e) {
|
||||||
$this->assertSame('111: foo in foo.php line 12', $e->getMessage());
|
$this->assertSame('Parse Error: foo', $e->getMessage());
|
||||||
$this->assertSame(111, $e->getSeverity());
|
$this->assertSame(4, $e->getSeverity());
|
||||||
$this->assertSame('foo.php', $e->getFile());
|
$this->assertSame('foo.php', $e->getFile());
|
||||||
$this->assertSame(12, $e->getLine());
|
$this->assertSame(12, $e->getLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
$handler = ErrorHandler::register(E_USER_DEPRECATED);
|
$handler = ErrorHandler::register();
|
||||||
$this->assertFalse($handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
$handler->throwAt(E_USER_DEPRECATED, true);
|
||||||
|
$this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
$handler = ErrorHandler::register(E_DEPRECATED);
|
$handler = ErrorHandler::register();
|
||||||
$this->assertFalse($handler->handle(E_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
$handler->throwAt(E_DEPRECATED, true);
|
||||||
|
$this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||||
|
|
||||||
$that = $this;
|
$that = $this;
|
||||||
$warnArgCheck = function ($message, $context) use ($that) {
|
$warnArgCheck = function ($logLevel, $message, $context) use ($that) {
|
||||||
|
$that->assertEquals('info', $logLevel);
|
||||||
$that->assertEquals('foo', $message);
|
$that->assertEquals('foo', $message);
|
||||||
$that->assertArrayHasKey('type', $context);
|
$that->assertArrayHasKey('type', $context);
|
||||||
$that->assertEquals($context['type'], ErrorHandler::TYPE_DEPRECATION);
|
$that->assertEquals($context['type'], E_USER_DEPRECATED);
|
||||||
$that->assertArrayHasKey('stack', $context);
|
$that->assertArrayHasKey('stack', $context);
|
||||||
$that->assertInternalType('array', $context['stack']);
|
$that->assertInternalType('array', $context['stack']);
|
||||||
};
|
};
|
||||||
|
|
||||||
$logger
|
$logger
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('warning')
|
->method('log')
|
||||||
->will($this->returnCallback($warnArgCheck))
|
->will($this->returnCallback($warnArgCheck))
|
||||||
;
|
;
|
||||||
|
|
||||||
$handler = ErrorHandler::register(E_USER_DEPRECATED);
|
$handler = ErrorHandler::register();
|
||||||
$handler->setLogger($logger);
|
$handler->setDefaultLogger($logger, E_USER_DEPRECATED);
|
||||||
$this->assertTrue($handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
$this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
|
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
$logArgCheck = function ($level, $message, $context) use ($that) {
|
||||||
|
$that->assertEquals('Undefined variable: undefVar', $message);
|
||||||
|
$that->assertArrayHasKey('type', $context);
|
||||||
|
$that->assertEquals($context['type'], E_NOTICE);
|
||||||
|
};
|
||||||
|
|
||||||
|
$logger
|
||||||
|
->expects($this->once())
|
||||||
|
->method('log')
|
||||||
|
->will($this->returnCallback($logArgCheck))
|
||||||
|
;
|
||||||
|
|
||||||
|
$handler = ErrorHandler::register();
|
||||||
|
$handler->setDefaultLogger($logger, E_NOTICE);
|
||||||
|
$handler->screamAt(E_NOTICE);
|
||||||
|
unset($undefVar);
|
||||||
|
@$undefVar++;
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleException()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$handler = ErrorHandler::register();
|
||||||
|
|
||||||
|
$exception = new \Exception('foo');
|
||||||
|
|
||||||
|
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
$logArgCheck = function ($level, $message, $context) use ($that) {
|
||||||
|
$that->assertEquals('Uncaught Exception: foo', $message);
|
||||||
|
$that->assertArrayHasKey('type', $context);
|
||||||
|
$that->assertEquals($context['type'], E_ERROR);
|
||||||
|
};
|
||||||
|
|
||||||
|
$logger
|
||||||
|
->expects($this->exactly(2))
|
||||||
|
->method('log')
|
||||||
|
->will($this->returnCallback($logArgCheck))
|
||||||
|
;
|
||||||
|
|
||||||
|
$handler->setDefaultLogger($logger, E_ERROR);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$handler->handleException($exception);
|
||||||
|
$this->fail('Exception expected');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->assertSame($exception, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
$handler->setExceptionHandler(function ($e) use ($exception, $that) {
|
||||||
|
$that->assertSame($exception, $e);
|
||||||
|
});
|
||||||
|
|
||||||
|
$handler->handleException($exception);
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleFatalError()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$handler = ErrorHandler::register();
|
||||||
|
|
||||||
|
$error = array(
|
||||||
|
'type' => E_PARSE,
|
||||||
|
'message' => 'foo',
|
||||||
|
'file' => 'bar',
|
||||||
|
'line' => 123,
|
||||||
|
);
|
||||||
|
|
||||||
|
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
$logArgCheck = function ($level, $message, $context) use ($that) {
|
||||||
|
$that->assertEquals('Fatal Parse Error: foo', $message);
|
||||||
|
$that->assertArrayHasKey('type', $context);
|
||||||
|
$that->assertEquals($context['type'], E_ERROR);
|
||||||
|
};
|
||||||
|
|
||||||
|
$logger
|
||||||
|
->expects($this->once())
|
||||||
|
->method('log')
|
||||||
|
->will($this->returnCallback($logArgCheck))
|
||||||
|
;
|
||||||
|
|
||||||
|
$handler->setDefaultLogger($logger, E_ERROR);
|
||||||
|
|
||||||
|
$handler->handleFatalError($error);
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDeprecatedInterface()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$handler = ErrorHandler::register(0);
|
||||||
|
$this->assertFalse($handler->handle(0, 'foo', 'foo.php', 12, array()));
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||||
|
|
||||||
|
|
@ -187,63 +410,12 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
@$undefVar++;
|
@$undefVar++;
|
||||||
|
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
restore_exception_handler();
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider provideFatalErrorHandlersData
|
|
||||||
*/
|
|
||||||
public function testFatalErrorHandlers($error, $class, $translatedMessage)
|
|
||||||
{
|
|
||||||
$handler = new ErrorHandler();
|
|
||||||
$exceptionHandler = new MockExceptionHandler();
|
|
||||||
|
|
||||||
$m = new \ReflectionMethod($handler, 'handleFatalError');
|
|
||||||
$m->setAccessible(true);
|
|
||||||
$m->invoke($handler, array($exceptionHandler, 'handle'), $error);
|
|
||||||
|
|
||||||
restore_error_handler();
|
|
||||||
$this->assertInstanceof($class, $exceptionHandler->e);
|
|
||||||
// class names are case insensitive and PHP/HHVM do not return the same
|
|
||||||
$this->assertSame(strtolower($translatedMessage), strtolower($exceptionHandler->e->getMessage()));
|
|
||||||
$this->assertSame($error['type'], $exceptionHandler->e->getSeverity());
|
|
||||||
$this->assertSame($error['file'], $exceptionHandler->e->getFile());
|
|
||||||
$this->assertSame($error['line'], $exceptionHandler->e->getLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function provideFatalErrorHandlersData()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
// undefined function
|
|
||||||
array(
|
|
||||||
array(
|
|
||||||
'type' => 1,
|
|
||||||
'line' => 12,
|
|
||||||
'file' => 'foo.php',
|
|
||||||
'message' => 'Call to undefined function test_namespaced_function_again()',
|
|
||||||
),
|
|
||||||
'Symfony\Component\Debug\Exception\UndefinedFunctionException',
|
|
||||||
'Attempted to call function "test_namespaced_function_again" from the global namespace in foo.php line 12. Did you mean to call: "\\symfony\\component\\debug\\tests\\test_namespaced_function_again"?',
|
|
||||||
),
|
|
||||||
// class not found
|
|
||||||
array(
|
|
||||||
array(
|
|
||||||
'type' => 1,
|
|
||||||
'line' => 12,
|
|
||||||
'file' => 'foo.php',
|
|
||||||
'message' => 'Class \'WhizBangFactory\' not found',
|
|
||||||
),
|
|
||||||
'Symfony\Component\Debug\Exception\ClassNotFoundException',
|
|
||||||
'Attempted to load class "WhizBangFactory" from the global namespace in foo.php line 12. Did you forget a use statement for this class?',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_namespaced_function_again()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,8 +162,8 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
|
||||||
'message' => 'test',
|
'message' => 'test',
|
||||||
'class' => 'Exception',
|
'class' => 'Exception',
|
||||||
'trace' => array(array(
|
'trace' => array(array(
|
||||||
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => '', 'file' => 'foo.php', 'line' => 123,
|
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => '', 'file' => 'foo.php', 'line' => 123,
|
||||||
'args' => array(),
|
'args' => array(),
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
), $flattened->toArray());
|
), $flattened->toArray());
|
||||||
|
|
@ -214,14 +214,14 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
|
||||||
'class' => 'Exception',
|
'class' => 'Exception',
|
||||||
'trace' => array(
|
'trace' => array(
|
||||||
array(
|
array(
|
||||||
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => '',
|
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => '',
|
||||||
'file' => 'foo.php', 'line' => 123,
|
'file' => 'foo.php', 'line' => 123,
|
||||||
'args' => array(),
|
'args' => array(),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => 'test',
|
'namespace' => '', 'short_class' => '', 'class' => '','type' => '','function' => 'test',
|
||||||
'file' => __FILE__, 'line' => 123,
|
'file' => __FILE__, 'line' => 123,
|
||||||
'args' => array(
|
'args' => array(
|
||||||
array(
|
array(
|
||||||
'incomplete-object', 'BogusTestClass',
|
'incomplete-object', 'BogusTestClass',
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
namespace Symfony\Component\Debug\Tests;
|
namespace Symfony\Component\Debug\Tests;
|
||||||
|
|
||||||
use Symfony\Component\Debug\ExceptionHandler;
|
use Symfony\Component\Debug\ExceptionHandler;
|
||||||
|
use Symfony\Component\Debug\Exception\OutOfMemoryException;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||||
|
|
||||||
|
|
@ -23,13 +25,13 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
$response = $handler->createResponse(new \RuntimeException('Foo'));
|
$response = $handler->createResponse(new \RuntimeException('Foo'));
|
||||||
|
|
||||||
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response->getContent());
|
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response->getContent());
|
||||||
$this->assertNotContains('<div class="block_exception clear_fix">', $response->getContent());
|
$this->assertNotContains('<h2 class="block_exception clear_fix">', $response->getContent());
|
||||||
|
|
||||||
$handler = new ExceptionHandler(true);
|
$handler = new ExceptionHandler(true);
|
||||||
$response = $handler->createResponse(new \RuntimeException('Foo'));
|
$response = $handler->createResponse(new \RuntimeException('Foo'));
|
||||||
|
|
||||||
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response->getContent());
|
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response->getContent());
|
||||||
$this->assertContains('<div class="block_exception clear_fix">', $response->getContent());
|
$this->assertContains('<h2 class="block_exception clear_fix">', $response->getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStatusCode()
|
public function testStatusCode()
|
||||||
|
|
@ -59,4 +61,56 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
$handler = new ExceptionHandler(true);
|
$handler = new ExceptionHandler(true);
|
||||||
$response = $handler->createResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
|
$response = $handler->createResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testHandle()
|
||||||
|
{
|
||||||
|
$exception = new \Exception('foo');
|
||||||
|
|
||||||
|
if (class_exists('Symfony\Component\HttpFoundation\Response')) {
|
||||||
|
$handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('createResponse'));
|
||||||
|
$handler
|
||||||
|
->expects($this->exactly(2))
|
||||||
|
->method('createResponse')
|
||||||
|
->will($this->returnValue(new Response()));
|
||||||
|
} else {
|
||||||
|
$handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('sendPhpResponse'));
|
||||||
|
$handler
|
||||||
|
->expects($this->exactly(2))
|
||||||
|
->method('sendPhpResponse');
|
||||||
|
}
|
||||||
|
|
||||||
|
$handler->handle($exception);
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
$handler->setHandler(function ($e) use ($exception, $that) {
|
||||||
|
$that->assertSame($exception, $e);
|
||||||
|
});
|
||||||
|
|
||||||
|
$handler->handle($exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHandleOutOfMemoryException()
|
||||||
|
{
|
||||||
|
$exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__);
|
||||||
|
|
||||||
|
if (class_exists('Symfony\Component\HttpFoundation\Response')) {
|
||||||
|
$handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('createResponse'));
|
||||||
|
$handler
|
||||||
|
->expects($this->once())
|
||||||
|
->method('createResponse')
|
||||||
|
->will($this->returnValue(new Response()));
|
||||||
|
} else {
|
||||||
|
$handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('sendPhpResponse'));
|
||||||
|
$handler
|
||||||
|
->expects($this->once())
|
||||||
|
->method('sendPhpResponse');
|
||||||
|
}
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
$handler->setHandler(function ($e) use ($that) {
|
||||||
|
$that->fail('OutOfMemoryException should bypass the handler');
|
||||||
|
});
|
||||||
|
|
||||||
|
$handler->handle($exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Class \'WhizBangFactory\' not found',
|
'message' => 'Class \'WhizBangFactory\' not found',
|
||||||
),
|
),
|
||||||
'Attempted to load class "WhizBangFactory" from the global namespace in foo.php line 12. Did you forget a use statement for this class?',
|
"Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?",
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -50,7 +50,7 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found',
|
'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found',
|
||||||
),
|
),
|
||||||
'Attempted to load class "WhizBangFactory" from namespace "Foo\\Bar" in foo.php line 12. Do you need to "use" it from another namespace?',
|
"Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?",
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -59,7 +59,7 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Class \'UndefinedFunctionException\' not found',
|
'message' => 'Class \'UndefinedFunctionException\' not found',
|
||||||
),
|
),
|
||||||
'Attempted to load class "UndefinedFunctionException" from the global namespace in foo.php line 12. Did you forget a use statement for this class? Perhaps you need to add a use statement for one of the following: Symfony\Component\Debug\Exception\UndefinedFunctionException.',
|
"Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -68,7 +68,7 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Class \'PEARClass\' not found',
|
'message' => 'Class \'PEARClass\' not found',
|
||||||
),
|
),
|
||||||
'Attempted to load class "PEARClass" from the global namespace in foo.php line 12. Did you forget a use statement for this class? Perhaps you need to add a use statement for one of the following: Symfony_Component_Debug_Tests_Fixtures_PEARClass.',
|
"Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"?",
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -77,7 +77,7 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
|
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
|
||||||
),
|
),
|
||||||
'Attempted to load class "UndefinedFunctionException" from namespace "Foo\Bar" in foo.php line 12. Do you need to "use" it from another namespace? Perhaps you need to add a use statement for one of the following: Symfony\Component\Debug\Exception\UndefinedFunctionException.',
|
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class UndefinedFunctionFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Call to undefined function test_namespaced_function()',
|
'message' => 'Call to undefined function test_namespaced_function()',
|
||||||
),
|
),
|
||||||
'Attempted to call function "test_namespaced_function" from the global namespace in foo.php line 12. Did you mean to call: "\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function"?',
|
"Attempted to call function \"test_namespaced_function\" from the global namespace.\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -51,7 +51,7 @@ class UndefinedFunctionFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()',
|
'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()',
|
||||||
),
|
),
|
||||||
'Attempted to call function "test_namespaced_function" from namespace "Foo\\Bar\\Baz" in foo.php line 12. Did you mean to call: "\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function"?',
|
"Attempted to call function \"test_namespaced_function\" from namespace \"Foo\\Bar\\Baz\".\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -60,7 +60,7 @@ class UndefinedFunctionFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Call to undefined function foo()',
|
'message' => 'Call to undefined function foo()',
|
||||||
),
|
),
|
||||||
'Attempted to call function "foo" from the global namespace in foo.php line 12.',
|
'Attempted to call function "foo" from the global namespace.',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -69,7 +69,7 @@ class UndefinedFunctionFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()',
|
'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()',
|
||||||
),
|
),
|
||||||
'Attempted to call function "foo" from namespace "Foo\Bar\Baz" in foo.php line 12.',
|
'Attempted to call function "foo" from namespace "Foo\Bar\Baz".',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class UndefinedMethodFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Call to undefined method SplObjectStorage::what()',
|
'message' => 'Call to undefined method SplObjectStorage::what()',
|
||||||
),
|
),
|
||||||
'Attempted to call method "what" on class "SplObjectStorage" in foo.php line 12.',
|
'Attempted to call method "what" on class "SplObjectStorage".',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -50,7 +50,7 @@ class UndefinedMethodFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Call to undefined method SplObjectStorage::walid()',
|
'message' => 'Call to undefined method SplObjectStorage::walid()',
|
||||||
),
|
),
|
||||||
'Attempted to call method "walid" on class "SplObjectStorage" in foo.php line 12. Did you mean to call: "valid"?',
|
"Attempted to call method \"walid\" on class \"SplObjectStorage\".\nDid you mean to call \"valid\"?",
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
|
@ -59,7 +59,7 @@ class UndefinedMethodFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
|
||||||
'file' => 'foo.php',
|
'file' => 'foo.php',
|
||||||
'message' => 'Call to undefined method SplObjectStorage::offsetFet()',
|
'message' => 'Call to undefined method SplObjectStorage::offsetFet()',
|
||||||
),
|
),
|
||||||
'Attempted to call method "offsetFet" on class "SplObjectStorage" in foo.php line 12. Did you mean to call: "offsetGet", "offsetSet", "offsetUnset"?',
|
"Attempted to call method \"offsetFet\" on class \"SplObjectStorage\".\nDid you mean to call e.g. \"offsetGet\", \"offsetSet\" or \"offsetUnset\"?",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3",
|
||||||
|
"psr/log": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/http-kernel": "~2.1",
|
"symfony/http-kernel": "~2.1",
|
||||||
|
|
@ -33,7 +34,7 @@
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "2.5-dev"
|
"dev-master": "2.6-dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
2.6.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added new factory syntax and deprecated the old one
|
||||||
|
|
||||||
2.5.0
|
2.5.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
|
||||||
public function process(ContainerBuilder $container)
|
public function process(ContainerBuilder $container)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
$this->graph = $container->getCompiler()->getServiceReferenceGraph();
|
$this->graph = $container->getCompiler()->getServiceReferenceGraph();
|
||||||
$this->graph->clear();
|
$this->graph->clear();
|
||||||
|
|
||||||
foreach ($container->getDefinitions() as $id => $definition) {
|
foreach ($container->getDefinitions() as $id => $definition) {
|
||||||
|
|
@ -81,6 +81,9 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
|
||||||
if ($definition->getConfigurator()) {
|
if ($definition->getConfigurator()) {
|
||||||
$this->processArguments(array($definition->getConfigurator()));
|
$this->processArguments(array($definition->getConfigurator()));
|
||||||
}
|
}
|
||||||
|
if ($definition->getFactory()) {
|
||||||
|
$this->processArguments(array($definition->getFactory()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,8 @@ class CheckCircularReferencesPass implements CompilerPassInterface
|
||||||
private function checkOutEdges(array $edges)
|
private function checkOutEdges(array $edges)
|
||||||
{
|
{
|
||||||
foreach ($edges as $edge) {
|
foreach ($edges as $edge) {
|
||||||
$node = $edge->getDestNode();
|
$node = $edge->getDestNode();
|
||||||
$id = $node->getId();
|
$id = $node->getId();
|
||||||
|
|
||||||
if (empty($this->checkedNodes[$id])) {
|
if (empty($this->checkedNodes[$id])) {
|
||||||
$searchKey = array_search($id, $this->currentPath);
|
$searchKey = array_search($id, $this->currentPath);
|
||||||
|
|
|
||||||
|
|
@ -42,28 +42,22 @@ class CheckDefinitionValidityPass implements CompilerPassInterface
|
||||||
foreach ($container->getDefinitions() as $id => $definition) {
|
foreach ($container->getDefinitions() as $id => $definition) {
|
||||||
// synthetic service is public
|
// synthetic service is public
|
||||||
if ($definition->isSynthetic() && !$definition->isPublic()) {
|
if ($definition->isSynthetic() && !$definition->isPublic()) {
|
||||||
throw new RuntimeException(sprintf(
|
throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id));
|
||||||
'A synthetic service ("%s") must be public.',
|
|
||||||
$id
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// synthetic service has non-prototype scope
|
// synthetic service has non-prototype scope
|
||||||
if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
|
if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
|
||||||
throw new RuntimeException(sprintf(
|
throw new RuntimeException(sprintf('A synthetic service ("%s") cannot be of scope "prototype".', $id));
|
||||||
'A synthetic service ("%s") cannot be of scope "prototype".',
|
}
|
||||||
$id
|
|
||||||
));
|
if ($definition->getFactory() && ($definition->getFactoryClass() || $definition->getFactoryService() || $definition->getFactoryMethod())) {
|
||||||
|
throw new RuntimeException(sprintf('A service ("%s") can use either the old or the new factory syntax, not both.', $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-synthetic, non-abstract service has class
|
// non-synthetic, non-abstract service has class
|
||||||
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
|
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
|
||||||
if ($definition->getFactoryClass() || $definition->getFactoryService()) {
|
if ($definition->getFactory() || $definition->getFactoryClass() || $definition->getFactoryService()) {
|
||||||
throw new RuntimeException(sprintf(
|
throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id));
|
||||||
'Please add the class to service "%s" even if it is constructed by a factory '
|
|
||||||
.'since we might need to add method calls based on compile-time checks.',
|
|
||||||
$id
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException(sprintf(
|
throw new RuntimeException(sprintf(
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,10 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
|
||||||
);
|
);
|
||||||
|
|
||||||
$configurator = $this->inlineArguments($container, array($definition->getConfigurator()));
|
$configurator = $this->inlineArguments($container, array($definition->getConfigurator()));
|
||||||
$definition->setConfigurator(
|
$definition->setConfigurator($configurator[0]);
|
||||||
$configurator[0]
|
|
||||||
);
|
$factory = $this->inlineArguments($container, array($definition->getFactory()));
|
||||||
|
$definition->setFactory($factory[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,9 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
|
||||||
if (isset($changes['factory_service'])) {
|
if (isset($changes['factory_service'])) {
|
||||||
$def->setFactoryService($definition->getFactoryService());
|
$def->setFactoryService($definition->getFactoryService());
|
||||||
}
|
}
|
||||||
|
if (isset($changes['factory'])) {
|
||||||
|
$def->setFactory($definition->getFactory());
|
||||||
|
}
|
||||||
if (isset($changes['configurator'])) {
|
if (isset($changes['configurator'])) {
|
||||||
$def->setConfigurator($definition->getConfigurator());
|
$def->setConfigurator($definition->getConfigurator());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Alias;
|
use Symfony\Component\DependencyInjection\Alias;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
|
||||||
|
|
@ -84,7 +85,12 @@ class ResolveReferencesToAliasesPass implements CompilerPassInterface
|
||||||
*/
|
*/
|
||||||
private function getDefinitionId($id)
|
private function getDefinitionId($id)
|
||||||
{
|
{
|
||||||
|
$seen = array();
|
||||||
while ($this->container->hasAlias($id)) {
|
while ($this->container->hasAlias($id)) {
|
||||||
|
if (isset($seen[$id])) {
|
||||||
|
throw new ServiceCircularReferenceException($id, array_keys($seen));
|
||||||
|
}
|
||||||
|
$seen[$id] = true;
|
||||||
$id = (string) $this->container->getAlias($id);
|
$id = (string) $this->container->getAlias($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,11 +217,11 @@ class Container implements IntrospectableContainerInterface
|
||||||
$this->$method();
|
$this->$method();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self::SCOPE_CONTAINER !== $scope && null === $service) {
|
|
||||||
unset($this->scopedServices[$scope][$id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $service) {
|
if (null === $service) {
|
||||||
|
if (self::SCOPE_CONTAINER !== $scope) {
|
||||||
|
unset($this->scopedServices[$scope][$id]);
|
||||||
|
}
|
||||||
|
|
||||||
unset($this->services[$id]);
|
unset($this->services[$id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -450,14 +450,15 @@ class Container implements IntrospectableContainerInterface
|
||||||
// the global service map
|
// the global service map
|
||||||
$services = array($this->services, $this->scopedServices[$name]);
|
$services = array($this->services, $this->scopedServices[$name]);
|
||||||
unset($this->scopedServices[$name]);
|
unset($this->scopedServices[$name]);
|
||||||
foreach ($this->scopeChildren[$name] as $child) {
|
|
||||||
if (!isset($this->scopedServices[$child])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$services[] = $this->scopedServices[$child];
|
foreach ($this->scopeChildren[$name] as $child) {
|
||||||
unset($this->scopedServices[$child]);
|
if (isset($this->scopedServices[$child])) {
|
||||||
|
$services[] = $this->scopedServices[$child];
|
||||||
|
unset($this->scopedServices[$child]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update global map
|
||||||
$this->services = call_user_func_array('array_diff_key', $services);
|
$this->services = call_user_func_array('array_diff_key', $services);
|
||||||
|
|
||||||
// check if we need to restore services of a previous scope of this type
|
// check if we need to restore services of a previous scope of this type
|
||||||
|
|
@ -465,6 +466,10 @@ class Container implements IntrospectableContainerInterface
|
||||||
$services = $this->scopeStacks[$name]->pop();
|
$services = $this->scopeStacks[$name]->pop();
|
||||||
$this->scopedServices += $services;
|
$this->scopedServices += $services;
|
||||||
|
|
||||||
|
if ($this->scopeStacks[$name]->isEmpty()) {
|
||||||
|
unset($this->scopeStacks[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($services as $array) {
|
foreach ($services as $array) {
|
||||||
foreach ($array as $id => $service) {
|
foreach ($array as $id => $service) {
|
||||||
$this->set($id, $service, $name);
|
$this->set($id, $service, $name);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ use Symfony\Component\Config\Resource\ResourceInterface;
|
||||||
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
|
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
|
||||||
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
|
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
|
||||||
use Symfony\Component\ExpressionLanguage\Expression;
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
|
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ContainerBuilder is a DI container that provides an API to easily describe services.
|
* ContainerBuilder is a DI container that provides an API to easily describe services.
|
||||||
|
|
@ -84,6 +85,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||||
*/
|
*/
|
||||||
private $expressionLanguage;
|
private $expressionLanguage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ExpressionFunctionProviderInterface[]
|
||||||
|
*/
|
||||||
|
private $expressionLanguageProviders = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the track resources flag.
|
* Sets the track resources flag.
|
||||||
*
|
*
|
||||||
|
|
@ -464,10 +470,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||||
return $service;
|
return $service;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->loading[$id])) {
|
|
||||||
throw new LogicException(sprintf('The service "%s" has a circular reference to itself.', $id), 0, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->hasDefinition($id) && isset($this->aliasDefinitions[$id])) {
|
if (!$this->hasDefinition($id) && isset($this->aliasDefinitions[$id])) {
|
||||||
return $this->get($this->aliasDefinitions[$id]);
|
return $this->get($this->aliasDefinitions[$id]);
|
||||||
}
|
}
|
||||||
|
|
@ -939,7 +941,19 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||||
|
|
||||||
$arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));
|
$arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));
|
||||||
|
|
||||||
if (null !== $definition->getFactoryMethod()) {
|
if (null !== $definition->getFactory()) {
|
||||||
|
$factory = $definition->getFactory();
|
||||||
|
|
||||||
|
if (is_string($factory)) {
|
||||||
|
$callable = $definition->getFactory();
|
||||||
|
} elseif (is_array($factory)) {
|
||||||
|
$callable = array($this->resolveServices($factory[0]), $factory[1]);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
$service = call_user_func_array($callable, $arguments);
|
||||||
|
} elseif (null !== $definition->getFactoryMethod()) {
|
||||||
if (null !== $definition->getFactoryClass()) {
|
if (null !== $definition->getFactoryClass()) {
|
||||||
$factory = $parameterBag->resolveValue($definition->getFactoryClass());
|
$factory = $parameterBag->resolveValue($definition->getFactoryClass());
|
||||||
} elseif (null !== $definition->getFactoryService()) {
|
} elseif (null !== $definition->getFactoryService()) {
|
||||||
|
|
@ -1056,6 +1070,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||||
return array_unique($tags);
|
return array_unique($tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
|
||||||
|
{
|
||||||
|
$this->expressionLanguageProviders[] = $provider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Service Conditionals.
|
* Returns the Service Conditionals.
|
||||||
*
|
*
|
||||||
|
|
@ -1161,7 +1180,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||||
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
|
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
|
||||||
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
||||||
}
|
}
|
||||||
$this->expressionLanguage = new ExpressionLanguage();
|
$this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->expressionLanguage;
|
return $this->expressionLanguage;
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,10 @@ use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||||
interface ContainerInterface
|
interface ContainerInterface
|
||||||
{
|
{
|
||||||
const EXCEPTION_ON_INVALID_REFERENCE = 1;
|
const EXCEPTION_ON_INVALID_REFERENCE = 1;
|
||||||
const NULL_ON_INVALID_REFERENCE = 2;
|
const NULL_ON_INVALID_REFERENCE = 2;
|
||||||
const IGNORE_ON_INVALID_REFERENCE = 3;
|
const IGNORE_ON_INVALID_REFERENCE = 3;
|
||||||
const SCOPE_CONTAINER = 'container';
|
const SCOPE_CONTAINER = 'container';
|
||||||
const SCOPE_PROTOTYPE = 'prototype';
|
const SCOPE_PROTOTYPE = 'prototype';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a service.
|
* Sets a service.
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ class Definition
|
||||||
{
|
{
|
||||||
private $class;
|
private $class;
|
||||||
private $file;
|
private $file;
|
||||||
|
private $factory;
|
||||||
private $factoryClass;
|
private $factoryClass;
|
||||||
private $factoryMethod;
|
private $factoryMethod;
|
||||||
private $factoryService;
|
private $factoryService;
|
||||||
|
|
@ -56,6 +57,34 @@ class Definition
|
||||||
$this->arguments = $arguments;
|
$this->arguments = $arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a factory.
|
||||||
|
*
|
||||||
|
* @param string|array $factory A PHP function or an array containing a class/Reference and a method to call
|
||||||
|
*
|
||||||
|
* @return Definition The current instance
|
||||||
|
*/
|
||||||
|
public function setFactory($factory)
|
||||||
|
{
|
||||||
|
if (is_string($factory) && strpos($factory, '::') !== false) {
|
||||||
|
$factory = explode('::', $factory, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->factory = $factory;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the factory.
|
||||||
|
*
|
||||||
|
* @return string|array The PHP function or an array containing a class/Reference and a method to call
|
||||||
|
*/
|
||||||
|
public function getFactory()
|
||||||
|
{
|
||||||
|
return $this->factory;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the name of the class that acts as a factory using the factory method,
|
* Sets the name of the class that acts as a factory using the factory method,
|
||||||
* which will be invoked statically.
|
* which will be invoked statically.
|
||||||
|
|
@ -65,6 +94,7 @@ class Definition
|
||||||
* @return Definition The current instance
|
* @return Definition The current instance
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
|
* @deprecated Deprecated since version 2.6, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
public function setFactoryClass($factoryClass)
|
public function setFactoryClass($factoryClass)
|
||||||
{
|
{
|
||||||
|
|
@ -79,6 +109,7 @@ class Definition
|
||||||
* @return string|null The factory class name
|
* @return string|null The factory class name
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
|
* @deprecated Deprecated since version 2.6, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
public function getFactoryClass()
|
public function getFactoryClass()
|
||||||
{
|
{
|
||||||
|
|
@ -93,6 +124,7 @@ class Definition
|
||||||
* @return Definition The current instance
|
* @return Definition The current instance
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
|
* @deprecated Deprecated since version 2.6, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
public function setFactoryMethod($factoryMethod)
|
public function setFactoryMethod($factoryMethod)
|
||||||
{
|
{
|
||||||
|
|
@ -142,6 +174,7 @@ class Definition
|
||||||
* @return string|null The factory method name
|
* @return string|null The factory method name
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
|
* @deprecated Deprecated since version 2.6, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
public function getFactoryMethod()
|
public function getFactoryMethod()
|
||||||
{
|
{
|
||||||
|
|
@ -156,6 +189,7 @@ class Definition
|
||||||
* @return Definition The current instance
|
* @return Definition The current instance
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
|
* @deprecated Deprecated since version 2.6, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
public function setFactoryService($factoryService)
|
public function setFactoryService($factoryService)
|
||||||
{
|
{
|
||||||
|
|
@ -170,6 +204,7 @@ class Definition
|
||||||
* @return string|null The factory service id
|
* @return string|null The factory service id
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
|
* @deprecated Deprecated since version 2.6, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
public function getFactoryService()
|
public function getFactoryService()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,16 @@ class DefinitionDecorator extends Definition
|
||||||
return parent::setClass($class);
|
return parent::setClass($class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setFactory($callable)
|
||||||
|
{
|
||||||
|
$this->changes['factory'] = true;
|
||||||
|
|
||||||
|
return parent::setFactory($callable);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ class GraphvizDumper extends Dumper
|
||||||
private $edges;
|
private $edges;
|
||||||
private $options = array(
|
private $options = array(
|
||||||
'graph' => array('ratio' => 'compress'),
|
'graph' => array('ratio' => 'compress'),
|
||||||
'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'),
|
'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'),
|
||||||
'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5),
|
'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5),
|
||||||
'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'),
|
'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'),
|
||||||
'node.definition' => array('fillcolor' => '#eeeeee'),
|
'node.definition' => array('fillcolor' => '#eeeeee'),
|
||||||
'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'),
|
'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'),
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as
|
||||||
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
|
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
|
||||||
use Symfony\Component\DependencyInjection\ExpressionLanguage;
|
use Symfony\Component\DependencyInjection\ExpressionLanguage;
|
||||||
use Symfony\Component\ExpressionLanguage\Expression;
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
|
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PhpDumper dumps a service container as a PHP class.
|
* PhpDumper dumps a service container as a PHP class.
|
||||||
|
|
@ -55,6 +56,11 @@ class PhpDumper extends Dumper
|
||||||
private $reservedVariables = array('instance', 'class');
|
private $reservedVariables = array('instance', 'class');
|
||||||
private $expressionLanguage;
|
private $expressionLanguage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ExpressionFunctionProviderInterface[]
|
||||||
|
*/
|
||||||
|
private $expressionLanguageProviders = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface
|
* @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface
|
||||||
*/
|
*/
|
||||||
|
|
@ -100,7 +106,7 @@ class PhpDumper extends Dumper
|
||||||
public function dump(array $options = array())
|
public function dump(array $options = array())
|
||||||
{
|
{
|
||||||
$options = array_merge(array(
|
$options = array_merge(array(
|
||||||
'class' => 'ProjectServiceContainer',
|
'class' => 'ProjectServiceContainer',
|
||||||
'base_class' => 'Container',
|
'base_class' => 'Container',
|
||||||
'namespace' => '',
|
'namespace' => '',
|
||||||
), $options);
|
), $options);
|
||||||
|
|
@ -109,6 +115,7 @@ class PhpDumper extends Dumper
|
||||||
|
|
||||||
if ($this->container->isFrozen()) {
|
if ($this->container->isFrozen()) {
|
||||||
$code .= $this->addFrozenConstructor();
|
$code .= $this->addFrozenConstructor();
|
||||||
|
$code .= $this->addFrozenCompile();
|
||||||
} else {
|
} else {
|
||||||
$code .= $this->addConstructor();
|
$code .= $this->addConstructor();
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +167,7 @@ class PhpDumper extends Dumper
|
||||||
$this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
|
$this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
|
||||||
$this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
|
$this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
|
||||||
$this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior);
|
$this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior);
|
||||||
|
$this->getServiceCallsFromArguments(array($iDefinition->getFactory()), $calls, $behavior);
|
||||||
}
|
}
|
||||||
|
|
||||||
$code = '';
|
$code = '';
|
||||||
|
|
@ -339,9 +347,9 @@ class PhpDumper extends Dumper
|
||||||
throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
|
throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
$simple = $this->isSimpleInstance($id, $definition);
|
$simple = $this->isSimpleInstance($id, $definition);
|
||||||
$isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
|
$isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
|
||||||
$instantiation = '';
|
$instantiation = '';
|
||||||
|
|
||||||
if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) {
|
if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) {
|
||||||
$instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance');
|
$instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance');
|
||||||
|
|
@ -522,6 +530,17 @@ class PhpDumper extends Dumper
|
||||||
$return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
|
$return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
|
||||||
} elseif ($class = $definition->getClass()) {
|
} elseif ($class = $definition->getClass()) {
|
||||||
$return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : "\\".$class, $class);
|
$return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : "\\".$class, $class);
|
||||||
|
} elseif ($definition->getFactory()) {
|
||||||
|
$factory = $definition->getFactory();
|
||||||
|
if (is_string($factory)) {
|
||||||
|
$return[] = sprintf('@return object An instance returned by %s().', $factory);
|
||||||
|
} elseif (is_array($factory) && (is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
|
||||||
|
if (is_string($factory[0]) || $factory[0] instanceof Reference) {
|
||||||
|
$return[] = sprintf('@return object An instance returned by %s::%s().', (string) $factory[0], $factory[1]);
|
||||||
|
} elseif ($factory[0] instanceof Definition) {
|
||||||
|
$return[] = sprintf('@return object An instance returned by %s::%s().', $factory[0]->getClass(), $factory[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
} elseif ($definition->getFactoryClass()) {
|
} elseif ($definition->getFactoryClass()) {
|
||||||
$return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod());
|
$return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod());
|
||||||
} elseif ($definition->getFactoryService()) {
|
} elseif ($definition->getFactoryService()) {
|
||||||
|
|
@ -559,17 +578,17 @@ EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($definition->isLazy()) {
|
if ($definition->isLazy()) {
|
||||||
$lazyInitialization = '$lazyLoad = true';
|
$lazyInitialization = '$lazyLoad = true';
|
||||||
$lazyInitializationDoc = "\n * @param bool \$lazyLoad whether to try lazy-loading the service with a proxy\n *";
|
$lazyInitializationDoc = "\n * @param bool \$lazyLoad whether to try lazy-loading the service with a proxy\n *";
|
||||||
} else {
|
} else {
|
||||||
$lazyInitialization = '';
|
$lazyInitialization = '';
|
||||||
$lazyInitializationDoc = '';
|
$lazyInitializationDoc = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
|
// with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
|
||||||
$isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
|
$isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
|
||||||
$visibility = $isProxyCandidate ? 'public' : 'protected';
|
$visibility = $isProxyCandidate ? 'public' : 'protected';
|
||||||
$code = <<<EOF
|
$code = <<<EOF
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the '$id' service.$doc
|
* Gets the '$id' service.$doc
|
||||||
|
|
@ -700,7 +719,25 @@ EOF;
|
||||||
$arguments[] = $this->dumpValue($value);
|
$arguments[] = $this->dumpValue($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $definition->getFactoryMethod()) {
|
if (null !== $definition->getFactory()) {
|
||||||
|
$callable = $definition->getFactory();
|
||||||
|
if (is_array($callable)) {
|
||||||
|
if ($callable[0] instanceof Reference
|
||||||
|
|| ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
|
||||||
|
return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = $this->dumpValue($callable[0]);
|
||||||
|
// If the class is a string we can optimize call_user_func away
|
||||||
|
if (strpos($class, "'") === 0) {
|
||||||
|
return sprintf(" $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(" $return{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : '');
|
||||||
|
} elseif (null !== $definition->getFactoryMethod()) {
|
||||||
if (null !== $definition->getFactoryClass()) {
|
if (null !== $definition->getFactoryClass()) {
|
||||||
$class = $this->dumpValue($definition->getFactoryClass());
|
$class = $this->dumpValue($definition->getFactoryClass());
|
||||||
|
|
||||||
|
|
@ -769,16 +806,18 @@ EOF;
|
||||||
*/
|
*/
|
||||||
private function addConstructor()
|
private function addConstructor()
|
||||||
{
|
{
|
||||||
$arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;
|
$parameters = $this->exportParameters($this->container->getParameterBag()->all());
|
||||||
|
|
||||||
$code = <<<EOF
|
$code = <<<EOF
|
||||||
|
|
||||||
|
private static \$parameters = $parameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct($arguments);
|
parent::__construct(new ParameterBag(self::\$parameters));
|
||||||
|
|
||||||
EOF;
|
EOF;
|
||||||
|
|
||||||
|
|
@ -806,23 +845,17 @@ EOF;
|
||||||
*/
|
*/
|
||||||
private function addFrozenConstructor()
|
private function addFrozenConstructor()
|
||||||
{
|
{
|
||||||
|
$parameters = $this->exportParameters($this->container->getParameterBag()->all());
|
||||||
|
|
||||||
$code = <<<EOF
|
$code = <<<EOF
|
||||||
|
|
||||||
private \$parameters;
|
private static \$parameters = $parameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
EOF;
|
|
||||||
|
|
||||||
if ($this->container->getParameterBag()->all()) {
|
|
||||||
$code .= "\n \$this->parameters = \$this->getDefaultParameters();\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$code .= <<<EOF
|
|
||||||
|
|
||||||
\$this->services =
|
\$this->services =
|
||||||
\$this->scopedServices =
|
\$this->scopedServices =
|
||||||
\$this->scopeStacks = array();
|
\$this->scopeStacks = array();
|
||||||
|
|
@ -851,6 +884,26 @@ EOF;
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the constructor for a frozen container.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function addFrozenCompile()
|
||||||
|
{
|
||||||
|
return <<<EOF
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
throw new LogicException('You cannot compile a dumped frozen container.');
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the methodMap property definition
|
* Adds the methodMap property definition
|
||||||
*
|
*
|
||||||
|
|
@ -910,8 +963,6 @@ EOF;
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$parameters = $this->exportParameters($this->container->getParameterBag()->all());
|
|
||||||
|
|
||||||
$code = '';
|
$code = '';
|
||||||
if ($this->container->isFrozen()) {
|
if ($this->container->isFrozen()) {
|
||||||
$code .= <<<EOF
|
$code .= <<<EOF
|
||||||
|
|
@ -923,11 +974,11 @@ EOF;
|
||||||
{
|
{
|
||||||
\$name = strtolower(\$name);
|
\$name = strtolower(\$name);
|
||||||
|
|
||||||
if (!(isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters))) {
|
if (!(isset(self::\$parameters[\$name]) || array_key_exists(\$name, self::\$parameters))) {
|
||||||
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', \$name));
|
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', \$name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return \$this->parameters[\$name];
|
return self::\$parameters[\$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -937,7 +988,7 @@ EOF;
|
||||||
{
|
{
|
||||||
\$name = strtolower(\$name);
|
\$name = strtolower(\$name);
|
||||||
|
|
||||||
return isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters);
|
return isset(self::\$parameters[\$name]) || array_key_exists(\$name, self::\$parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -954,28 +1005,15 @@ EOF;
|
||||||
public function getParameterBag()
|
public function getParameterBag()
|
||||||
{
|
{
|
||||||
if (null === \$this->parameterBag) {
|
if (null === \$this->parameterBag) {
|
||||||
\$this->parameterBag = new FrozenParameterBag(\$this->parameters);
|
\$this->parameterBag = new FrozenParameterBag(self::\$parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return \$this->parameterBag;
|
return \$this->parameterBag;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOF;
|
EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
$code .= <<<EOF
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the default parameters.
|
|
||||||
*
|
|
||||||
* @return array An array of the default parameters
|
|
||||||
*/
|
|
||||||
protected function getDefaultParameters()
|
|
||||||
{
|
|
||||||
return $parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOF;
|
|
||||||
|
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1095,7 +1133,8 @@ EOF;
|
||||||
$this->getDefinitionsFromArguments($definition->getArguments()),
|
$this->getDefinitionsFromArguments($definition->getArguments()),
|
||||||
$this->getDefinitionsFromArguments($definition->getMethodCalls()),
|
$this->getDefinitionsFromArguments($definition->getMethodCalls()),
|
||||||
$this->getDefinitionsFromArguments($definition->getProperties()),
|
$this->getDefinitionsFromArguments($definition->getProperties()),
|
||||||
$this->getDefinitionsFromArguments(array($definition->getConfigurator()))
|
$this->getDefinitionsFromArguments(array($definition->getConfigurator())),
|
||||||
|
$this->getDefinitionsFromArguments(array($definition->getFactory()))
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->inlinedDefinitions->offsetSet($definition, $definitions);
|
$this->inlinedDefinitions->offsetSet($definition, $definitions);
|
||||||
|
|
@ -1173,7 +1212,7 @@ EOF;
|
||||||
/**
|
/**
|
||||||
* Dumps values.
|
* Dumps values.
|
||||||
*
|
*
|
||||||
* @param array $value
|
* @param mixed $value
|
||||||
* @param bool $interpolate
|
* @param bool $interpolate
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
|
@ -1210,6 +1249,30 @@ EOF;
|
||||||
throw new RuntimeException('Cannot dump definitions which have a variable class name.');
|
throw new RuntimeException('Cannot dump definitions which have a variable class name.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null !== $value->getFactory()) {
|
||||||
|
$factory = $value->getFactory();
|
||||||
|
|
||||||
|
if (is_string($factory)) {
|
||||||
|
return sprintf('\\%s(%s)', $factory, implode(', ', $arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($factory)) {
|
||||||
|
if (is_string($factory[0])) {
|
||||||
|
return sprintf('\\%s::%s(%s)', $factory[0], $factory[1], implode(', ', $arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($factory[0] instanceof Definition) {
|
||||||
|
return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($factory[0]), $factory[1], count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($factory[0] instanceof Reference) {
|
||||||
|
return sprintf('%s->%s(%s)', $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException('Cannot dump definition because of invalid factory');
|
||||||
|
}
|
||||||
|
|
||||||
if (null !== $value->getFactoryMethod()) {
|
if (null !== $value->getFactoryMethod()) {
|
||||||
if (null !== $value->getFactoryClass()) {
|
if (null !== $value->getFactoryClass()) {
|
||||||
return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass()), $value->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
|
return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass()), $value->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
|
||||||
|
|
@ -1283,6 +1346,11 @@ EOF;
|
||||||
return sprintf("\$this->getParameter('%s')", strtolower($name));
|
return sprintf("\$this->getParameter('%s')", strtolower($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
|
||||||
|
{
|
||||||
|
$this->expressionLanguageProviders[] = $provider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a service call
|
* Gets a service call
|
||||||
*
|
*
|
||||||
|
|
@ -1372,7 +1440,7 @@ EOF;
|
||||||
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
|
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
|
||||||
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
||||||
}
|
}
|
||||||
$this->expressionLanguage = new ExpressionLanguage();
|
$this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->expressionLanguage;
|
return $this->expressionLanguage;
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,17 @@ class XmlDumper extends Dumper
|
||||||
|
|
||||||
$this->addMethodCalls($definition->getMethodCalls(), $service);
|
$this->addMethodCalls($definition->getMethodCalls(), $service);
|
||||||
|
|
||||||
|
if ($callable = $definition->getFactory()) {
|
||||||
|
$factory = $this->document->createElement('factory');
|
||||||
|
if (is_array($callable)) {
|
||||||
|
$factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
|
||||||
|
$factory->setAttribute('method', $callable[1]);
|
||||||
|
} else {
|
||||||
|
$factory->setAttribute('function', $callable);
|
||||||
|
}
|
||||||
|
$service->appendChild($factory);
|
||||||
|
}
|
||||||
|
|
||||||
if ($callable = $definition->getConfigurator()) {
|
if ($callable = $definition->getConfigurator()) {
|
||||||
$configurator = $this->document->createElement('configurator');
|
$configurator = $this->document->createElement('configurator');
|
||||||
if (is_array($callable)) {
|
if (is_array($callable)) {
|
||||||
|
|
|
||||||
|
|
@ -147,16 +147,12 @@ class YamlDumper extends Dumper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($callable = $definition->getConfigurator()) {
|
if ($callable = $definition->getFactory()) {
|
||||||
if (is_array($callable)) {
|
$code .= sprintf(" factory: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0));
|
||||||
if ($callable[0] instanceof Reference) {
|
}
|
||||||
$callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]);
|
|
||||||
} else {
|
|
||||||
$callable = array($callable[0], $callable[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$code .= sprintf(" configurator: %s\n", $this->dumper->dump($callable, 0));
|
if ($callable = $definition->getConfigurator()) {
|
||||||
|
$code .= sprintf(" configurator: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $code;
|
return $code;
|
||||||
|
|
@ -222,6 +218,26 @@ class YamlDumper extends Dumper
|
||||||
return $this->dumper->dump(array('parameters' => $parameters), 2);
|
return $this->dumper->dump(array('parameters' => $parameters), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dumps callable to YAML format
|
||||||
|
*
|
||||||
|
* @param callable $callable
|
||||||
|
*
|
||||||
|
* @return callable
|
||||||
|
*/
|
||||||
|
private function dumpCallable($callable)
|
||||||
|
{
|
||||||
|
if (is_array($callable)) {
|
||||||
|
if ($callable[0] instanceof Reference) {
|
||||||
|
$callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]);
|
||||||
|
} else {
|
||||||
|
$callable = array($callable[0], $callable[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $callable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps the value to YAML format
|
* Dumps the value to YAML format
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -12,31 +12,22 @@
|
||||||
namespace Symfony\Component\DependencyInjection;
|
namespace Symfony\Component\DependencyInjection;
|
||||||
|
|
||||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
|
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
|
||||||
|
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds some function to the default ExpressionLanguage.
|
* Adds some function to the default ExpressionLanguage.
|
||||||
*
|
*
|
||||||
* To get a service, use service('request').
|
|
||||||
* To get a parameter, use parameter('kernel.debug').
|
|
||||||
*
|
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* @see ExpressionLanguageProvider
|
||||||
*/
|
*/
|
||||||
class ExpressionLanguage extends BaseExpressionLanguage
|
class ExpressionLanguage extends BaseExpressionLanguage
|
||||||
{
|
{
|
||||||
protected function registerFunctions()
|
public function __construct(ParserCacheInterface $cache = null, array $providers = array())
|
||||||
{
|
{
|
||||||
parent::registerFunctions();
|
// prepend the default provider to let users overide it easily
|
||||||
|
array_unshift($providers, new ExpressionLanguageProvider());
|
||||||
|
|
||||||
$this->register('service', function ($arg) {
|
parent::__construct($cache, $providers);
|
||||||
return sprintf('$this->get(%s)', $arg);
|
|
||||||
}, function (array $variables, $value) {
|
|
||||||
return $variables['container']->get($value);
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->register('parameter', function ($arg) {
|
|
||||||
return sprintf('$this->getParameter(%s)', $arg);
|
|
||||||
}, function (array $variables, $value) {
|
|
||||||
return $variables['container']->getParameter($value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
|
||||||
|
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define some ExpressionLanguage functions.
|
||||||
|
*
|
||||||
|
* To get a service, use service('request').
|
||||||
|
* To get a parameter, use parameter('kernel.debug').
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
|
||||||
|
{
|
||||||
|
public function getFunctions()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
new ExpressionFunction('service', function ($arg) {
|
||||||
|
return sprintf('$this->get(%s)', $arg);
|
||||||
|
}, function (array $variables, $value) {
|
||||||
|
return $variables['container']->get($value);
|
||||||
|
}),
|
||||||
|
|
||||||
|
new ExpressionFunction('parameter', function ($arg) {
|
||||||
|
return sprintf('$this->getParameter(%s)', $arg);
|
||||||
|
}, function (array $variables, $value) {
|
||||||
|
return $variables['container']->getParameter($value);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,23 +36,15 @@ class ClosureLoader extends Loader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a Closure.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param \Closure $closure The resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*/
|
*/
|
||||||
public function load($closure, $type = null)
|
public function load($resource, $type = null)
|
||||||
{
|
{
|
||||||
call_user_func($closure, $this->container);
|
call_user_func($resource, $this->container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this class supports the given resource.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $resource A resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*
|
|
||||||
* @return bool true if this class supports the given resource, false otherwise
|
|
||||||
*/
|
*/
|
||||||
public function supports($resource, $type = null)
|
public function supports($resource, $type = null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ abstract class FileLoader extends BaseFileLoader
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||||
* @param FileLocatorInterface $locator A FileLocator instance
|
* @param FileLocatorInterface $locator A FileLocator instance
|
||||||
*/
|
*/
|
||||||
public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
|
public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,22 +22,17 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||||
class IniFileLoader extends FileLoader
|
class IniFileLoader extends FileLoader
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Loads a resource.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $file The resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException When ini file is not valid
|
|
||||||
*/
|
*/
|
||||||
public function load($file, $type = null)
|
public function load($resource, $type = null)
|
||||||
{
|
{
|
||||||
$path = $this->locator->locate($file);
|
$path = $this->locator->locate($resource);
|
||||||
|
|
||||||
$this->container->addResource(new FileResource($path));
|
$this->container->addResource(new FileResource($path));
|
||||||
|
|
||||||
$result = parse_ini_file($path, true);
|
$result = parse_ini_file($path, true);
|
||||||
if (false === $result || array() === $result) {
|
if (false === $result || array() === $result) {
|
||||||
throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $file));
|
throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($result['parameters']) && is_array($result['parameters'])) {
|
if (isset($result['parameters']) && is_array($result['parameters'])) {
|
||||||
|
|
@ -48,12 +43,7 @@ class IniFileLoader extends FileLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this class supports the given resource.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $resource A resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*
|
|
||||||
* @return bool true if this class supports the given resource, false otherwise
|
|
||||||
*/
|
*/
|
||||||
public function supports($resource, $type = null)
|
public function supports($resource, $type = null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,18 +24,15 @@ use Symfony\Component\Config\Resource\FileResource;
|
||||||
class PhpFileLoader extends FileLoader
|
class PhpFileLoader extends FileLoader
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Loads a PHP file.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $file The resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*/
|
*/
|
||||||
public function load($file, $type = null)
|
public function load($resource, $type = null)
|
||||||
{
|
{
|
||||||
// the container and loader variables are exposed to the included file below
|
// the container and loader variables are exposed to the included file below
|
||||||
$container = $this->container;
|
$container = $this->container;
|
||||||
$loader = $this;
|
$loader = $this;
|
||||||
|
|
||||||
$path = $this->locator->locate($file);
|
$path = $this->locator->locate($resource);
|
||||||
$this->setCurrentDir(dirname($path));
|
$this->setCurrentDir(dirname($path));
|
||||||
$this->container->addResource(new FileResource($path));
|
$this->container->addResource(new FileResource($path));
|
||||||
|
|
||||||
|
|
@ -43,12 +40,7 @@ class PhpFileLoader extends FileLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this class supports the given resource.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $resource A resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*
|
|
||||||
* @return bool true if this class supports the given resource, false otherwise
|
|
||||||
*/
|
*/
|
||||||
public function supports($resource, $type = null)
|
public function supports($resource, $type = null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,14 +32,11 @@ class XmlFileLoader extends FileLoader
|
||||||
const NS = 'http://symfony.com/schema/dic/services';
|
const NS = 'http://symfony.com/schema/dic/services';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an XML file.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $file The resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*/
|
*/
|
||||||
public function load($file, $type = null)
|
public function load($resource, $type = null)
|
||||||
{
|
{
|
||||||
$path = $this->locator->locate($file);
|
$path = $this->locator->locate($resource);
|
||||||
|
|
||||||
$xml = $this->parseFileToDOM($path);
|
$xml = $this->parseFileToDOM($path);
|
||||||
|
|
||||||
|
|
@ -62,12 +59,7 @@ class XmlFileLoader extends FileLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this class supports the given resource.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $resource A resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*
|
|
||||||
* @return bool true if this class supports the given resource, false otherwise
|
|
||||||
*/
|
*/
|
||||||
public function supports($resource, $type = null)
|
public function supports($resource, $type = null)
|
||||||
{
|
{
|
||||||
|
|
@ -167,6 +159,21 @@ class XmlFileLoader extends FileLoader
|
||||||
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument'));
|
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument'));
|
||||||
$definition->setProperties($this->getArgumentsAsPhp($service, 'property'));
|
$definition->setProperties($this->getArgumentsAsPhp($service, 'property'));
|
||||||
|
|
||||||
|
if ($factories = $this->getChildren($service, 'factory')) {
|
||||||
|
$factory = $factories[0];
|
||||||
|
if ($function = $factory->getAttribute('function')) {
|
||||||
|
$definition->setFactory($function);
|
||||||
|
} else {
|
||||||
|
if ($childService = $factory->getAttribute('service')) {
|
||||||
|
$class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
|
||||||
|
} else {
|
||||||
|
$class = $factory->getAttribute('class');
|
||||||
|
}
|
||||||
|
|
||||||
|
$definition->setFactory(array($class, $factory->getAttribute('method')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($configurators = $this->getChildren($service, 'configurator')) {
|
if ($configurators = $this->getChildren($service, 'configurator')) {
|
||||||
$configurator = $configurators[0];
|
$configurator = $configurators[0];
|
||||||
if ($function = $configurator->getAttribute('function')) {
|
if ($function = $configurator->getAttribute('function')) {
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,11 @@ class YamlFileLoader extends FileLoader
|
||||||
private $yamlParser;
|
private $yamlParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a Yaml file.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $file The resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*/
|
*/
|
||||||
public function load($file, $type = null)
|
public function load($resource, $type = null)
|
||||||
{
|
{
|
||||||
$path = $this->locator->locate($file);
|
$path = $this->locator->locate($resource);
|
||||||
|
|
||||||
$content = $this->loadFile($path);
|
$content = $this->loadFile($path);
|
||||||
|
|
||||||
|
|
@ -57,7 +54,7 @@ class YamlFileLoader extends FileLoader
|
||||||
// parameters
|
// parameters
|
||||||
if (isset($content['parameters'])) {
|
if (isset($content['parameters'])) {
|
||||||
if (!is_array($content['parameters'])) {
|
if (!is_array($content['parameters'])) {
|
||||||
throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $file));
|
throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($content['parameters'] as $key => $value) {
|
foreach ($content['parameters'] as $key => $value) {
|
||||||
|
|
@ -69,16 +66,11 @@ class YamlFileLoader extends FileLoader
|
||||||
$this->loadFromExtensions($content);
|
$this->loadFromExtensions($content);
|
||||||
|
|
||||||
// services
|
// services
|
||||||
$this->parseDefinitions($content, $file);
|
$this->parseDefinitions($content, $resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this class supports the given resource.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param mixed $resource A resource
|
|
||||||
* @param string $type The resource type
|
|
||||||
*
|
|
||||||
* @return bool true if this class supports the given resource, false otherwise
|
|
||||||
*/
|
*/
|
||||||
public function supports($resource, $type = null)
|
public function supports($resource, $type = null)
|
||||||
{
|
{
|
||||||
|
|
@ -194,6 +186,19 @@ class YamlFileLoader extends FileLoader
|
||||||
$definition->setAbstract($service['abstract']);
|
$definition->setAbstract($service['abstract']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($service['factory'])) {
|
||||||
|
if (is_string($service['factory'])) {
|
||||||
|
if (strpos($service['factory'], ':') !== false && strpos($service['factory'], '::') === false) {
|
||||||
|
$parts = explode(':', $service['factory']);
|
||||||
|
$definition->setFactory(array($this->resolveServices('@'.$parts[0]), $parts[1]));
|
||||||
|
} else {
|
||||||
|
$definition->setFactory($service['factory']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$definition->setFactory(array($this->resolveServices($service['factory'][0]), $service['factory'][1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($service['factory_class'])) {
|
if (isset($service['factory_class'])) {
|
||||||
$definition->setFactoryClass($service['factory_class']);
|
$definition->setFactoryClass($service['factory_class']);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
<xsd:attribute name="ignore-errors" type="boolean" />
|
<xsd:attribute name="ignore-errors" type="boolean" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="configurator">
|
<xsd:complexType name="callable">
|
||||||
<xsd:attribute name="id" type="xsd:string" />
|
<xsd:attribute name="id" type="xsd:string" />
|
||||||
<xsd:attribute name="service" type="xsd:string" />
|
<xsd:attribute name="service" type="xsd:string" />
|
||||||
<xsd:attribute name="class" type="xsd:string" />
|
<xsd:attribute name="class" type="xsd:string" />
|
||||||
|
|
@ -76,7 +76,8 @@
|
||||||
<xsd:choice maxOccurs="unbounded">
|
<xsd:choice maxOccurs="unbounded">
|
||||||
<xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" />
|
<xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" />
|
||||||
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
|
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
|
||||||
<xsd:element name="configurator" type="configurator" minOccurs="0" maxOccurs="1" />
|
<xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
|
||||||
|
<xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" />
|
||||||
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
|
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
|
||||||
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
|
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
|
||||||
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
|
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
|
|
||||||
|
|
@ -6,45 +6,50 @@ Injection Container.
|
||||||
|
|
||||||
Here is a simple example that shows how to register services and parameters:
|
Here is a simple example that shows how to register services and parameters:
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
```php
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
$sc = new ContainerBuilder();
|
$sc = new ContainerBuilder();
|
||||||
$sc
|
$sc
|
||||||
->register('foo', '%foo.class%')
|
->register('foo', '%foo.class%')
|
||||||
->addArgument(new Reference('bar'))
|
->addArgument(new Reference('bar'))
|
||||||
;
|
;
|
||||||
$sc->setParameter('foo.class', 'Foo');
|
$sc->setParameter('foo.class', 'Foo');
|
||||||
|
|
||||||
$sc->get('foo');
|
$sc->get('foo');
|
||||||
|
```
|
||||||
|
|
||||||
Method Calls (Setter Injection):
|
Method Calls (Setter Injection):
|
||||||
|
|
||||||
$sc = new ContainerBuilder();
|
```php
|
||||||
|
$sc = new ContainerBuilder();
|
||||||
|
|
||||||
$sc
|
$sc
|
||||||
->register('bar', '%bar.class%')
|
->register('bar', '%bar.class%')
|
||||||
->addMethodCall('setFoo', array(new Reference('foo')))
|
->addMethodCall('setFoo', array(new Reference('foo')))
|
||||||
;
|
;
|
||||||
$sc->setParameter('bar.class', 'Bar');
|
$sc->setParameter('bar.class', 'Bar');
|
||||||
|
|
||||||
$sc->get('bar');
|
$sc->get('bar');
|
||||||
|
```
|
||||||
|
|
||||||
Factory Class:
|
Factory Class:
|
||||||
|
|
||||||
If your service is retrieved by calling a static method:
|
If your service is retrieved by calling a static method:
|
||||||
|
|
||||||
$sc = new ContainerBuilder();
|
```php
|
||||||
|
$sc = new ContainerBuilder();
|
||||||
|
|
||||||
$sc
|
$sc
|
||||||
->register('bar', '%bar.class%')
|
->register('bar', '%bar.class%')
|
||||||
->setFactoryClass('%bar.class%')
|
->setFactory(array('%bar.class%', 'getInstance'))
|
||||||
->setFactoryMethod('getInstance')
|
->addArgument('Aarrg!!!')
|
||||||
->addArgument('Aarrg!!!')
|
;
|
||||||
;
|
$sc->setParameter('bar.class', 'Bar');
|
||||||
$sc->setParameter('bar.class', 'Bar');
|
|
||||||
|
|
||||||
$sc->get('bar');
|
$sc->get('bar');
|
||||||
|
```
|
||||||
|
|
||||||
File Include:
|
File Include:
|
||||||
|
|
||||||
|
|
@ -52,16 +57,18 @@ For some services, especially those that are difficult or impossible to
|
||||||
autoload, you may need the container to include a file before
|
autoload, you may need the container to include a file before
|
||||||
instantiating your class.
|
instantiating your class.
|
||||||
|
|
||||||
$sc = new ContainerBuilder();
|
```php
|
||||||
|
$sc = new ContainerBuilder();
|
||||||
|
|
||||||
$sc
|
$sc
|
||||||
->register('bar', '%bar.class%')
|
->register('bar', '%bar.class%')
|
||||||
->setFile('/path/to/file')
|
->setFile('/path/to/file')
|
||||||
->addArgument('Aarrg!!!')
|
->addArgument('Aarrg!!!')
|
||||||
;
|
;
|
||||||
$sc->setParameter('bar.class', 'Bar');
|
$sc->setParameter('bar.class', 'Bar');
|
||||||
|
|
||||||
$sc->get('bar');
|
$sc->get('bar');
|
||||||
|
```
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,17 @@ class CheckDefinitionValidityPassTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->process($container);
|
$this->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||||
|
*/
|
||||||
|
public function testProcessDetectsBothFactorySyntaxesUsed()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->register('a')->setFactory(array('a', 'b'))->setFactoryClass('a');
|
||||||
|
|
||||||
|
$this->process($container);
|
||||||
|
}
|
||||||
|
|
||||||
public function testProcess()
|
public function testProcess()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,17 @@ class ResolveReferencesToAliasesPassTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals('foo', (string) $arguments[0]);
|
$this->assertEquals('foo', (string) $arguments[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
|
||||||
|
*/
|
||||||
|
public function testAliasCircularReference()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->setAlias('bar', 'foo');
|
||||||
|
$container->setAlias('foo', 'bar');
|
||||||
|
$this->process($container);
|
||||||
|
}
|
||||||
|
|
||||||
protected function process(ContainerBuilder $container)
|
protected function process(ContainerBuilder $container)
|
||||||
{
|
{
|
||||||
$pass = new ResolveReferencesToAliasesPass();
|
$pass = new ResolveReferencesToAliasesPass();
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue