Issue #2461863 by stefan.r: Upgrade PHPUnit to the latest stable release

8.0.x
webchick 2015-04-29 20:45:28 -07:00
parent 412f4774a0
commit 736289f224
583 changed files with 24935 additions and 9271 deletions

View File

@ -23,7 +23,7 @@
"guzzlehttp/guzzle": "~5.0",
"symfony-cmf/routing": "1.3.*",
"easyrdf/easyrdf": "0.9.*",
"phpunit/phpunit": "4.4.*",
"phpunit/phpunit": "4.6.*",
"zendframework/zend-feed": "2.4.*",
"mikey179/vfsStream": "1.*",
"stack/builder": "1.0.*",

333
core/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "304089b3fa329c66764fdc353c5e0e83",
"hash": "c523fe48318d98a520d2bc45286106e2",
"packages": [
{
"name": "behat/mink",
@ -1044,17 +1044,126 @@
"time": "2014-09-14 10:18:53"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.0.11",
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "53603b3c995f5aab6b59c8e08c3a663d2cc810b7"
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/53603b3c995f5aab6b59c8e08c3a663d2cc810b7",
"reference": "53603b3c995f5aab6b59c8e08c3a663d2cc810b7",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2015-02-03 12:10:50"
},
{
"name": "phpspec/prophecy",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5",
"reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"phpdocumentor/reflection-docblock": "~2.0",
"sebastian/comparator": "~1.1"
},
"require-dev": {
"phpspec/phpspec": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2015-03-27 19:31:25"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.0.16",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c",
"reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c",
"shasum": ""
},
"require": {
@ -1067,7 +1176,7 @@
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4.1"
"phpunit/phpunit": "~4"
},
"suggest": {
"ext-dom": "*",
@ -1086,9 +1195,6 @@
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
@ -1106,35 +1212,37 @@
"testing",
"xunit"
],
"time": "2014-08-31 06:33:04"
"time": "2015-04-11 04:35:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.3.4",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
"reference": "a923bb15680d0089e2316f7a4af8f437046e96bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
"reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb",
"reference": "a923bb15680d0089e2316f7a4af8f437046e96bb",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"File/"
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
@ -1151,7 +1259,7 @@
"filesystem",
"iterator"
],
"time": "2013-10-10 15:34:57"
"time": "2015-04-02 05:19:05"
},
{
"name": "phpunit/php-text-template",
@ -1243,16 +1351,16 @@
},
{
"name": "phpunit/php-token-stream",
"version": "1.3.0",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "f8d5d08c56de5cfd592b3340424a81733259a876"
"reference": "eab81d02569310739373308137284e0158424330"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/f8d5d08c56de5cfd592b3340424a81733259a876",
"reference": "f8d5d08c56de5cfd592b3340424a81733259a876",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330",
"reference": "eab81d02569310739373308137284e0158424330",
"shasum": ""
},
"require": {
@ -1265,7 +1373,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
"dev-master": "1.4-dev"
}
},
"autoload": {
@ -1288,20 +1396,20 @@
"keywords": [
"tokenizer"
],
"time": "2014-08-31 06:12:13"
"time": "2015-04-08 04:46:07"
},
{
"name": "phpunit/phpunit",
"version": "4.4.2",
"version": "4.6.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "e90575c2bb86290d57a262862dab1da125431576"
"reference": "163232991e652e6efed2f8470326fffa61e848e2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e90575c2bb86290d57a262862dab1da125431576",
"reference": "e90575c2bb86290d57a262862dab1da125431576",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/163232991e652e6efed2f8470326fffa61e848e2",
"reference": "163232991e652e6efed2f8470326fffa61e848e2",
"shasum": ""
},
"require": {
@ -1311,18 +1419,19 @@
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpunit/php-code-coverage": "~2.0",
"phpunit/php-file-iterator": "~1.3.2",
"phpspec/prophecy": "~1.3,>=1.3.1",
"phpunit/php-code-coverage": "~2.0,>=2.0.11",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "~1.0.2",
"phpunit/php-timer": "~1.0",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.0",
"sebastian/diff": "~1.1",
"sebastian/environment": "~1.1",
"sebastian/exporter": "~1.0",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.2",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.0"
"symfony/yaml": "~2.1|~3.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
@ -1333,7 +1442,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.4.x-dev"
"dev-master": "4.6.x-dev"
}
},
"autoload": {
@ -1359,29 +1468,29 @@
"testing",
"xunit"
],
"time": "2015-01-17 11:24:41"
"time": "2015-04-11 05:23:21"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "2.3.0",
"version": "2.3.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "c63d2367247365f688544f0d500af90a11a44c65"
"reference": "74ffb87f527f24616f72460e54b595f508dccb5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c63d2367247365f688544f0d500af90a11a44c65",
"reference": "c63d2367247365f688544f0d500af90a11a44c65",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c",
"reference": "74ffb87f527f24616f72460e54b595f508dccb5c",
"shasum": ""
},
"require": {
"doctrine/instantiator": "~1.0,>=1.0.1",
"doctrine/instantiator": "~1.0,>=1.0.2",
"php": ">=5.3.3",
"phpunit/php-text-template": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.3"
"phpunit/phpunit": "~4.4"
},
"suggest": {
"ext-soap": "*"
@ -1414,7 +1523,7 @@
"mock",
"xunit"
],
"time": "2014-10-03 05:12:11"
"time": "2015-04-02 05:36:41"
},
{
"name": "psr/log",
@ -1548,30 +1657,30 @@
},
{
"name": "sebastian/comparator",
"version": "1.0.1",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "e54a01c0da1b87db3c5a3c4c5277ddf331da4aef"
"reference": "1dd8869519a225f7f2b9eb663e225298fade819e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e54a01c0da1b87db3c5a3c4c5277ddf331da4aef",
"reference": "e54a01c0da1b87db3c5a3c4c5277ddf331da4aef",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e",
"reference": "1dd8869519a225f7f2b9eb663e225298fade819e",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.1",
"sebastian/exporter": "~1.0"
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.1"
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.1.x-dev"
}
},
"autoload": {
@ -1608,20 +1717,20 @@
"compare",
"equality"
],
"time": "2014-05-11 23:00:21"
"time": "2015-01-29 16:28:08"
},
{
"name": "sebastian/diff",
"version": "1.2.0",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "5843509fed39dee4b356a306401e9dd1a931fec7"
"reference": "863df9687835c62aa423a22412d26fa2ebde3fd3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/5843509fed39dee4b356a306401e9dd1a931fec7",
"reference": "5843509fed39dee4b356a306401e9dd1a931fec7",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3",
"reference": "863df9687835c62aa423a22412d26fa2ebde3fd3",
"shasum": ""
},
"require": {
@ -1633,7 +1742,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
"dev-master": "1.3-dev"
}
},
"autoload": {
@ -1660,32 +1769,32 @@
"keywords": [
"diff"
],
"time": "2014-08-15 10:29:00"
"time": "2015-02-22 15:13:53"
},
{
"name": "sebastian/environment",
"version": "1.2.0",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "0d9bf79554d2a999da194a60416c15cf461eb67d"
"reference": "5a8c7d31914337b69923db26c4221b81ff5a196e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/0d9bf79554d2a999da194a60416c15cf461eb67d",
"reference": "0d9bf79554d2a999da194a60416c15cf461eb67d",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e",
"reference": "5a8c7d31914337b69923db26c4221b81ff5a196e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.3"
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
"dev-master": "1.3.x-dev"
}
},
"autoload": {
@ -1710,32 +1819,33 @@
"environment",
"hhvm"
],
"time": "2014-10-22 06:38:05"
"time": "2015-01-01 10:01:08"
},
{
"name": "sebastian/exporter",
"version": "1.0.2",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0"
"reference": "84839970d05254c73cde183a721c7af13aede943"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c7d59948d6e82818e1bdff7cadb6c34710eb7dc0",
"reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943",
"reference": "84839970d05254c73cde183a721c7af13aede943",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=5.3.3",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.2.x-dev"
}
},
"autoload": {
@ -1775,7 +1885,7 @@
"export",
"exporter"
],
"time": "2014-09-10 00:51:36"
"time": "2015-01-27 07:23:06"
},
{
"name": "sebastian/global-state",
@ -1829,17 +1939,70 @@
"time": "2014-10-06 09:23:50"
},
{
"name": "sebastian/version",
"version": "1.0.3",
"name": "sebastian/recursion-context",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43"
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "3989662bbb30a29d20d9faa04a846af79b276252"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43",
"reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252",
"reference": "3989662bbb30a29d20d9faa04a846af79b276252",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2015-01-24 09:48:32"
},
{
"name": "sebastian/version",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
"reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
"shasum": ""
},
"type": "library",
@ -1861,7 +2024,7 @@
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2014-03-07 15:35:33"
"time": "2015-02-24 06:35:25"
},
{
"name": "stack/builder",

View File

@ -12,9 +12,9 @@ return array(
'Drupal\\Core\\DrupalKernel' => $baseDir . '/lib/Drupal/Core/DrupalKernel.php',
'Drupal\\Core\\DrupalKernelInterface' => $baseDir . '/lib/Drupal/Core/DrupalKernelInterface.php',
'Drupal\\Core\\Site\\Settings' => $baseDir . '/lib/Drupal/Core/Site/Settings.php',
'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator.php',
'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator/Facade.php',
'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator/Factory.php',
'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php',
'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php',
'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php',
'PHPUnit_Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
'PHPUnit_Extensions_GroupTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/GroupTestSuite.php',
'PHPUnit_Extensions_PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestCase.php',
@ -297,6 +297,7 @@ return array(
'PHP_Token_HALT_COMPILER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IMPLEMENTS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
@ -313,6 +314,10 @@ return array(
'PHP_Token_IS_NOT_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_SMALLER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_Includes' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_JOIN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_CP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_OP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LINE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LIST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
@ -355,6 +360,7 @@ return array(
'PHP_Token_REQUIRE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_RETURN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SEMICOLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SHAPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
@ -372,6 +378,9 @@ return array(
'PHP_Token_TRAIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRAIT_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_USE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
@ -406,14 +415,15 @@ return array(
'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php',
'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php',
'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php',
'SebastianBergmann\\Exporter\\Context' => $vendorDir . '/sebastian/exporter/src/Context.php',
'SebastianBergmann\\Exporter\\Exception' => $vendorDir . '/sebastian/exporter/src/Exception.php',
'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php',
'SebastianBergmann\\GlobalState\\Blacklist' => $vendorDir . '/sebastian/global-state/src/Blacklist.php',
'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/Exception.php',
'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php',
'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/RuntimeException.php',
'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php',
'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php',
'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php',
'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php',
'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php',
'SessionHandlerInterface' => $vendorDir . '/symfony/http-foundation/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php',
'Symfony\\Component\\HttpFoundation\\FileBag' => $vendorDir . '/symfony/http-foundation/Symfony/Component/HttpFoundation/FileBag.php',

View File

@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'phpDocumentor' => array($vendorDir . '/phpdocumentor/reflection-docblock/src'),
'org\\bovigo\\vfs\\' => array($vendorDir . '/mikey179/vfsStream/src/main/php'),
'Twig_' => array($vendorDir . '/twig/twig/lib'),
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
@ -25,6 +26,7 @@ return array(
'Symfony\\Component\\BrowserKit\\' => array($vendorDir . '/symfony/browser-kit'),
'Stack' => array($vendorDir . '/stack/builder/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'),
'Gliph' => array($vendorDir . '/sdboyer/gliph/src'),
'Egulias\\' => array($vendorDir . '/egulias/email-validator/src'),
'EasyRdf_' => array($vendorDir . '/easyrdf/easyrdf/lib'),

View File

@ -8,6 +8,4 @@ $baseDir = dirname($vendorDir);
return array(
$vendorDir . '/phpunit/php-text-template',
$vendorDir . '/phpunit/php-timer',
$vendorDir . '/phpunit/php-file-iterator',
$vendorDir . '/phpunit/php-code-coverage',
);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
.idea
vendor

View File

@ -0,0 +1,32 @@
language: php
php:
- 5.3.3
- 5.3
- 5.4
- 5.5
- 5.6
- hhvm
- hhvm-nightly
matrix:
allow_failures:
- php: hhvm
- php: hhvm-nightly
script:
- vendor/bin/phpunit
before_script:
- sudo apt-get -qq update > /dev/null
- phpenv rehash > /dev/null
- composer selfupdate --quiet
- composer install --no-interaction --prefer-source --dev
- vendor/bin/phpunit
- composer update --no-interaction --prefer-source --dev
notifications:
irc: "irc.freenode.org#phpdocumentor"
email:
- mike.vanriel@naenius.com
- ashnazg@php.net
- boen.robot@gmail.com

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2010 Mike van Riel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,57 @@
The ReflectionDocBlock Component [![Build Status](https://secure.travis-ci.org/phpDocumentor/ReflectionDocBlock.png)](https://travis-ci.org/phpDocumentor/ReflectionDocBlock)
================================
Introduction
------------
The ReflectionDocBlock component of phpDocumentor provides a DocBlock parser
that is 100% compatible with the [PHPDoc standard](http://phpdoc.org/docs/latest).
With this component, a library can provide support for annotations via DocBlocks
or otherwise retrieve information that is embedded in a DocBlock.
> **Note**: *this is a core component of phpDocumentor and is constantly being
> optimized for performance.*
Installation
------------
You can install the component in the following ways:
* Use the official Github repository (https://github.com/phpDocumentor/ReflectionDocBlock)
* Via Composer (http://packagist.org/packages/phpdocumentor/reflection-docblock)
Usage
-----
The ReflectionDocBlock component is designed to work in an identical fashion to
PHP's own Reflection extension (http://php.net/manual/en/book.reflection.php).
Parsing can be initiated by instantiating the
`\phpDocumentor\Reflection\DocBlock()` class and passing it a string containing
a DocBlock (including asterisks) or by passing an object supporting the
`getDocComment()` method.
> *Examples of objects having the `getDocComment()` method are the
> `ReflectionClass` and the `ReflectionMethod` classes of the PHP
> Reflection extension*
Example:
$class = new ReflectionClass('MyClass');
$phpdoc = new \phpDocumentor\Reflection\DocBlock($class);
or
$docblock = <<<DOCBLOCK
/**
* This is a short description.
*
* This is a *long* description.
*
* @return void
*/
DOCBLOCK;
$phpdoc = new \phpDocumentor\Reflection\DocBlock($docblock);

View File

@ -0,0 +1,26 @@
{
"name": "phpdocumentor/reflection-docblock",
"type": "library",
"license": "MIT",
"authors": [
{"name": "Mike van Riel", "email": "mike.vanriel@naenius.com"}
],
"require": {
"php": ">=5.3.3"
},
"autoload": {
"psr-0": {"phpDocumentor": ["src/"]}
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
}
}

View File

@ -0,0 +1,827 @@
{
"_readme": [
"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",
"This file is @generated automatically"
],
"hash": "ea1734d11b8c878445c2c6e58de8b85f",
"packages": [],
"packages-dev": [
{
"name": "ocramius/instantiator",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/Instantiator.git",
"reference": "a7abbb5fc9df6e7126af741dd6c140d1a7369435"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Ocramius/Instantiator/zipball/a7abbb5fc9df6e7126af741dd6c140d1a7369435",
"reference": "a7abbb5fc9df6e7126af741dd6c140d1a7369435",
"shasum": ""
},
"require": {
"ocramius/lazy-map": "1.0.*",
"php": "~5.3"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "2.0.*@ALPHA"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Instantiator\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/Ocramius/Instantiator",
"keywords": [
"constructor",
"instantiate"
],
"time": "2014-08-14 15:10:55"
},
{
"name": "ocramius/lazy-map",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/LazyMap.git",
"reference": "7fe3d347f5e618bcea7d39345ff83f3651d8b752"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Ocramius/LazyMap/zipball/7fe3d347f5e618bcea7d39345ff83f3651d8b752",
"reference": "7fe3d347f5e618bcea7d39345ff83f3651d8b752",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"athletic/athletic": "~0.1.6",
"phpmd/phpmd": "1.5.*",
"phpunit/phpunit": ">=3.7",
"satooshi/php-coveralls": "~0.6",
"squizlabs/php_codesniffer": "1.4.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"LazyMap\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/",
"role": "Developer"
}
],
"description": "A library that provides lazy instantiation logic for a map of objects",
"homepage": "https://github.com/Ocramius/LazyMap",
"keywords": [
"lazy",
"lazy instantiation",
"lazy loading",
"map",
"service location"
],
"time": "2013-11-09 22:30:54"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.0.10",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "6d196af48e8c100a3ae881940123e693da5a9217"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6d196af48e8c100a3ae881940123e693da5a9217",
"reference": "6d196af48e8c100a3ae881940123e693da5a9217",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"phpunit/php-file-iterator": "~1.3.1",
"phpunit/php-text-template": "~1.2.0",
"phpunit/php-token-stream": "~1.2.2",
"sebastian/environment": "~1.0.0",
"sebastian/version": "~1.0.3"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4.0.14"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.2.1",
"ext-xmlwriter": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"time": "2014-08-06 06:39:42"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.3.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
"reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"File/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"time": "2013-10-10 15:34:57"
},
{
"name": "phpunit/php-text-template",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
"reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"Text/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"time": "2014-01-30 17:20:04"
},
{
"name": "phpunit/php-timer",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
"reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"PHP/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"time": "2013-08-02 07:42:54"
},
{
"name": "phpunit/php-token-stream",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32",
"reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
},
"autoload": {
"classmap": [
"PHP/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [
"tokenizer"
],
"time": "2014-03-03 05:10:30"
},
{
"name": "phpunit/phpunit",
"version": "4.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "a33fa68ece9f8c68589bfc2da8d2794e27b820bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a33fa68ece9f8c68589bfc2da8d2794e27b820bc",
"reference": "a33fa68ece9f8c68589bfc2da8d2794e27b820bc",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpunit/php-code-coverage": "~2.0",
"phpunit/php-file-iterator": "~1.3.1",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "~1.0.2",
"phpunit/phpunit-mock-objects": "~2.2",
"sebastian/comparator": "~1.0",
"sebastian/diff": "~1.1",
"sebastian/environment": "~1.0",
"sebastian/exporter": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
"",
"../../symfony/yaml/"
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "http://www.phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"time": "2014-08-18 05:12:30"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "42e589e08bc86e3e9bdf20d385e948347788505b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/42e589e08bc86e3e9bdf20d385e948347788505b",
"reference": "42e589e08bc86e3e9bdf20d385e948347788505b",
"shasum": ""
},
"require": {
"ocramius/instantiator": "~1.0",
"php": ">=5.3.3",
"phpunit/php-text-template": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "4.2.*@dev"
},
"suggest": {
"ext-soap": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Mock Object library for PHPUnit",
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
"keywords": [
"mock",
"xunit"
],
"time": "2014-08-02 13:50:58"
},
{
"name": "sebastian/comparator",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "f7069ee51fa9fb6c038e16a9d0e3439f5449dcf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/f7069ee51fa9fb6c038e16a9d0e3439f5449dcf2",
"reference": "f7069ee51fa9fb6c038e16a9d0e3439f5449dcf2",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.1",
"sebastian/exporter": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"time": "2014-05-02 07:05:58"
},
{
"name": "sebastian/diff",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d",
"reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "http://www.github.com/sebastianbergmann/diff",
"keywords": [
"diff"
],
"time": "2013-08-03 16:46:33"
},
{
"name": "sebastian/environment",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/79517609ec01139cd7e9fded0dd7ce08c952ef6a",
"reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "4.0.*@dev"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"time": "2014-02-18 16:17:19"
},
{
"name": "sebastian/exporter",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529",
"reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "4.0.*@dev"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net",
"role": "Lead"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"time": "2014-02-16 08:26:31"
},
{
"name": "sebastian/version",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43",
"reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43",
"shasum": ""
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2014-03-07 15:35:33"
},
{
"name": "symfony/yaml",
"version": "v2.5.3",
"target-dir": "Symfony/Component/Yaml",
"source": {
"type": "git",
"url": "https://github.com/symfony/Yaml.git",
"reference": "5a75366ae9ca8b4792cd0083e4ca4dff9fe96f1f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/5a75366ae9ca8b4792cd0083e4ca4dff9fe96f1f",
"reference": "5a75366ae9ca8b4792cd0083e4ca4dff9fe96f1f",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5-dev"
}
},
"autoload": {
"psr-0": {
"Symfony\\Component\\Yaml\\": ""
}
},
"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 Yaml Component",
"homepage": "http://symfony.com",
"time": "2014-08-05 09:00:40"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"platform": {
"php": ">=5.3.3"
},
"platform-dev": []
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit colors="true" strict="true" bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="phpDocumentor\Reflection\DocBlock">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">./src/</directory>
</whitelist>
</filter>
</phpunit>

View File

@ -0,0 +1,468 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Context;
use phpDocumentor\Reflection\DocBlock\Location;
/**
* Parses the DocBlock for any structure.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class DocBlock implements \Reflector
{
/** @var string The opening line for this docblock. */
protected $short_description = '';
/**
* @var DocBlock\Description The actual
* description for this docblock.
*/
protected $long_description = null;
/**
* @var Tag[] An array containing all
* the tags in this docblock; except inline.
*/
protected $tags = array();
/** @var Context Information about the context of this DocBlock. */
protected $context = null;
/** @var Location Information about the location of this DocBlock. */
protected $location = null;
/** @var bool Is this DocBlock (the start of) a template? */
protected $isTemplateStart = false;
/** @var bool Does this DocBlock signify the end of a DocBlock template? */
protected $isTemplateEnd = false;
/**
* Parses the given docblock and populates the member fields.
*
* The constructor may also receive namespace information such as the
* current namespace and aliases. This information is used by some tags
* (e.g. @return, @param, etc.) to turn a relative Type into a FQCN.
*
* @param \Reflector|string $docblock A docblock comment (including
* asterisks) or reflector supporting the getDocComment method.
* @param Context $context The context in which the DocBlock
* occurs.
* @param Location $location The location within the file that this
* DocBlock occurs in.
*
* @throws \InvalidArgumentException if the given argument does not have the
* getDocComment method.
*/
public function __construct(
$docblock,
Context $context = null,
Location $location = null
) {
if (is_object($docblock)) {
if (!method_exists($docblock, 'getDocComment')) {
throw new \InvalidArgumentException(
'Invalid object passed; the given reflector must support '
. 'the getDocComment method'
);
}
$docblock = $docblock->getDocComment();
}
$docblock = $this->cleanInput($docblock);
list($templateMarker, $short, $long, $tags) = $this->splitDocBlock($docblock);
$this->isTemplateStart = $templateMarker === '#@+';
$this->isTemplateEnd = $templateMarker === '#@-';
$this->short_description = $short;
$this->long_description = new DocBlock\Description($long, $this);
$this->parseTags($tags);
$this->context = $context;
$this->location = $location;
}
/**
* Strips the asterisks from the DocBlock comment.
*
* @param string $comment String containing the comment text.
*
* @return string
*/
protected function cleanInput($comment)
{
$comment = trim(
preg_replace(
'#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u',
'$1',
$comment
)
);
// reg ex above is not able to remove */ from a single line docblock
if (substr($comment, -2) == '*/') {
$comment = trim(substr($comment, 0, -2));
}
// normalize strings
$comment = str_replace(array("\r\n", "\r"), "\n", $comment);
return $comment;
}
/**
* Splits the DocBlock into a template marker, summary, description and block of tags.
*
* @param string $comment Comment to split into the sub-parts.
*
* @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split.
* @author Mike van Riel <me@mikevanriel.com> for extending the regex with template marker support.
*
* @return string[] containing the template marker (if any), summary, description and a string containing the tags.
*/
protected function splitDocBlock($comment)
{
// Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This
// method does not split tags so we return this verbatim as the fourth result (tags). This saves us the
// performance impact of running a regular expression
if (strpos($comment, '@') === 0) {
return array('', '', '', $comment);
}
// clears all extra horizontal whitespace from the line endings to prevent parsing issues
$comment = preg_replace('/\h*$/Sum', '', $comment);
/*
* Splits the docblock into a template marker, short description, long description and tags section
*
* - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may
* occur after it and will be stripped).
* - The short description is started from the first character until a dot is encountered followed by a
* newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing
* errors). This is optional.
* - The long description, any character until a new line is encountered followed by an @ and word
* characters (a tag). This is optional.
* - Tags; the remaining characters
*
* Big thanks to RichardJ for contributing this Regular Expression
*/
preg_match(
'/
\A
# 1. Extract the template marker
(?:(\#\@\+|\#\@\-)\n?)?
# 2. Extract the summary
(?:
(?! @\pL ) # The summary may not start with an @
(
[^\n.]+
(?:
(?! \. \n | \n{2} ) # End summary upon a dot followed by newline or two newlines
[\n.] (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line
[^\n.]+ # Include anything else
)*
\.?
)?
)
# 3. Extract the description
(?:
\s* # Some form of whitespace _must_ precede a description because a summary must be there
(?! @\pL ) # The description may not start with an @
(
[^\n]+
(?: \n+
(?! [ \t]* @\pL ) # End description when an @ is found as first character on a new line
[^\n]+ # Include anything else
)*
)
)?
# 4. Extract the tags (anything that follows)
(\s+ [\s\S]*)? # everything that follows
/ux',
$comment,
$matches
);
array_shift($matches);
while (count($matches) < 4) {
$matches[] = '';
}
return $matches;
}
/**
* Creates the tag objects.
*
* @param string $tags Tag block to parse.
*
* @return void
*/
protected function parseTags($tags)
{
$result = array();
$tags = trim($tags);
if ('' !== $tags) {
if ('@' !== $tags[0]) {
throw new \LogicException(
'A tag block started with text instead of an actual tag,'
. ' this makes the tag block invalid: ' . $tags
);
}
foreach (explode("\n", $tags) as $tag_line) {
if (isset($tag_line[0]) && ($tag_line[0] === '@')) {
$result[] = $tag_line;
} else {
$result[count($result) - 1] .= "\n" . $tag_line;
}
}
// create proper Tag objects
foreach ($result as $key => $tag_line) {
$result[$key] = Tag::createInstance(trim($tag_line), $this);
}
}
$this->tags = $result;
}
/**
* Gets the text portion of the doc block.
*
* Gets the text portion (short and long description combined) of the doc
* block.
*
* @return string The text portion of the doc block.
*/
public function getText()
{
$short = $this->getShortDescription();
$long = $this->getLongDescription()->getContents();
if ($long) {
return "{$short}\n\n{$long}";
} else {
return $short;
}
}
/**
* Set the text portion of the doc block.
*
* Sets the text portion (short and long description combined) of the doc
* block.
*
* @param string $docblock The new text portion of the doc block.
*
* @return $this This doc block.
*/
public function setText($comment)
{
list(,$short, $long) = $this->splitDocBlock($comment);
$this->short_description = $short;
$this->long_description = new DocBlock\Description($long, $this);
return $this;
}
/**
* Returns the opening line or also known as short description.
*
* @return string
*/
public function getShortDescription()
{
return $this->short_description;
}
/**
* Returns the full description or also known as long description.
*
* @return DocBlock\Description
*/
public function getLongDescription()
{
return $this->long_description;
}
/**
* Returns whether this DocBlock is the start of a Template section.
*
* A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker
* (`#@+`) that is appended directly after the opening `/**` of a DocBlock.
*
* An example of such an opening is:
*
* ```
* /**#@+
* * My DocBlock
* * /
* ```
*
* The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all
* elements that follow until another DocBlock is found that contains the closing marker (`#@-`).
*
* @see self::isTemplateEnd() for the check whether a closing marker was provided.
*
* @return boolean
*/
public function isTemplateStart()
{
return $this->isTemplateStart;
}
/**
* Returns whether this DocBlock is the end of a Template section.
*
* @see self::isTemplateStart() for a more complete description of the Docblock Template functionality.
*
* @return boolean
*/
public function isTemplateEnd()
{
return $this->isTemplateEnd;
}
/**
* Returns the current context.
*
* @return Context
*/
public function getContext()
{
return $this->context;
}
/**
* Returns the current location.
*
* @return Location
*/
public function getLocation()
{
return $this->location;
}
/**
* Returns the tags for this DocBlock.
*
* @return Tag[]
*/
public function getTags()
{
return $this->tags;
}
/**
* Returns an array of tags matching the given name. If no tags are found
* an empty array is returned.
*
* @param string $name String to search by.
*
* @return Tag[]
*/
public function getTagsByName($name)
{
$result = array();
/** @var Tag $tag */
foreach ($this->getTags() as $tag) {
if ($tag->getName() != $name) {
continue;
}
$result[] = $tag;
}
return $result;
}
/**
* Checks if a tag of a certain type is present in this DocBlock.
*
* @param string $name Tag name to check for.
*
* @return bool
*/
public function hasTag($name)
{
/** @var Tag $tag */
foreach ($this->getTags() as $tag) {
if ($tag->getName() == $name) {
return true;
}
}
return false;
}
/**
* Appends a tag at the end of the list of tags.
*
* @param Tag $tag The tag to add.
*
* @return Tag The newly added tag.
*
* @throws \LogicException When the tag belongs to a different DocBlock.
*/
public function appendTag(Tag $tag)
{
if (null === $tag->getDocBlock()) {
$tag->setDocBlock($this);
}
if ($tag->getDocBlock() === $this) {
$this->tags[] = $tag;
} else {
throw new \LogicException(
'This tag belongs to a different DocBlock object.'
);
}
return $tag;
}
/**
* Builds a string representation of this object.
*
* @todo determine the exact format as used by PHP Reflection and
* implement it.
*
* @return string
* @codeCoverageIgnore Not yet implemented
*/
public static function export()
{
throw new \Exception('Not yet implemented');
}
/**
* Returns the exported information (we should use the export static method
* BUT this throws an exception at this point).
*
* @return string
* @codeCoverageIgnore Not yet implemented
*/
public function __toString()
{
return 'Not yet implemented';
}
}

View File

@ -0,0 +1,154 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock;
/**
* The context in which a DocBlock occurs.
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class Context
{
/** @var string The current namespace. */
protected $namespace = '';
/** @var array List of namespace aliases => Fully Qualified Namespace. */
protected $namespace_aliases = array();
/** @var string Name of the structural element, within the namespace. */
protected $lsen = '';
/**
* Cteates a new context.
* @param string $namespace The namespace where this DocBlock
* resides in.
* @param array $namespace_aliases List of namespace aliases => Fully
* Qualified Namespace.
* @param string $lsen Name of the structural element, within
* the namespace.
*/
public function __construct(
$namespace = '',
array $namespace_aliases = array(),
$lsen = ''
) {
if (!empty($namespace)) {
$this->setNamespace($namespace);
}
$this->setNamespaceAliases($namespace_aliases);
$this->setLSEN($lsen);
}
/**
* @return string The namespace where this DocBlock resides in.
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* @return array List of namespace aliases => Fully Qualified Namespace.
*/
public function getNamespaceAliases()
{
return $this->namespace_aliases;
}
/**
* Returns the Local Structural Element Name.
*
* @return string Name of the structural element, within the namespace.
*/
public function getLSEN()
{
return $this->lsen;
}
/**
* Sets a new namespace.
*
* Sets a new namespace for the context. Leading and trailing slashes are
* trimmed, and the keywords "global" and "default" are treated as aliases
* to no namespace.
*
* @param string $namespace The new namespace to set.
*
* @return $this
*/
public function setNamespace($namespace)
{
if ('global' !== $namespace
&& 'default' !== $namespace
) {
// Srip leading and trailing slash
$this->namespace = trim((string)$namespace, '\\');
} else {
$this->namespace = '';
}
return $this;
}
/**
* Sets the namespace aliases, replacing all previous ones.
*
* @param array $namespace_aliases List of namespace aliases => Fully
* Qualified Namespace.
*
* @return $this
*/
public function setNamespaceAliases(array $namespace_aliases)
{
$this->namespace_aliases = array();
foreach ($namespace_aliases as $alias => $fqnn) {
$this->setNamespaceAlias($alias, $fqnn);
}
return $this;
}
/**
* Adds a namespace alias to the context.
*
* @param string $alias The alias name (the part after "as", or the last
* part of the Fully Qualified Namespace Name) to add.
* @param string $fqnn The Fully Qualified Namespace Name for this alias.
* Any form of leading/trailing slashes are accepted, but what will be
* stored is a name, prefixed with a slash, and no trailing slash.
*
* @return $this
*/
public function setNamespaceAlias($alias, $fqnn)
{
$this->namespace_aliases[$alias] = '\\' . trim((string)$fqnn, '\\');
return $this;
}
/**
* Sets a new Local Structural Element Name.
*
* Sets a new Local Structural Element Name. A local name also contains
* punctuation determining the kind of structural element (e.g. trailing "("
* and ")" for functions and methods).
*
* @param string $lsen The new local name of a structural element.
*
* @return $this
*/
public function setLSEN($lsen)
{
$this->lsen = (string)$lsen;
return $this;
}
}

View File

@ -0,0 +1,223 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock;
/**
* Parses a Description of a DocBlock or tag.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class Description implements \Reflector
{
/** @var string */
protected $contents = '';
/** @var array The contents, as an array of strings and Tag objects. */
protected $parsedContents = null;
/** @var DocBlock The DocBlock which this description belongs to. */
protected $docblock = null;
/**
* Populates the fields of a description.
*
* @param string $content The description's conetnts.
* @param DocBlock $docblock The DocBlock which this description belongs to.
*/
public function __construct($content, DocBlock $docblock = null)
{
$this->setContent($content)->setDocBlock($docblock);
}
/**
* Gets the text of this description.
*
* @return string
*/
public function getContents()
{
return $this->contents;
}
/**
* Sets the text of this description.
*
* @param string $content The new text of this description.
*
* @return $this
*/
public function setContent($content)
{
$this->contents = trim($content);
$this->parsedContents = null;
return $this;
}
/**
* Returns the parsed text of this description.
*
* @return array An array of strings and tag objects, in the order they
* occur within the description.
*/
public function getParsedContents()
{
if (null === $this->parsedContents) {
$this->parsedContents = preg_split(
'/\{
# "{@}" is not a valid inline tag. This ensures that
# we do not treat it as one, but treat it literally.
(?!@\})
# We want to capture the whole tag line, but without the
# inline tag delimiters.
(\@
# Match everything up to the next delimiter.
[^{}]*
# Nested inline tag content should not be captured, or
# it will appear in the result separately.
(?:
# Match nested inline tags.
(?:
# Because we did not catch the tag delimiters
# earlier, we must be explicit with them here.
# Notice that this also matches "{}", as a way
# to later introduce it as an escape sequence.
\{(?1)?\}
|
# Make sure we match hanging "{".
\{
)
# Match content after the nested inline tag.
[^{}]*
)* # If there are more inline tags, match them as well.
# We use "*" since there may not be any nested inline
# tags.
)
\}/Sux',
$this->contents,
null,
PREG_SPLIT_DELIM_CAPTURE
);
$count = count($this->parsedContents);
for ($i=1; $i<$count; $i += 2) {
$this->parsedContents[$i] = Tag::createInstance(
$this->parsedContents[$i],
$this->docblock
);
}
//In order to allow "literal" inline tags, the otherwise invalid
//sequence "{@}" is changed to "@", and "{}" is changed to "}".
//See unit tests for examples.
for ($i=0; $i<$count; $i += 2) {
$this->parsedContents[$i] = str_replace(
array('{@}', '{}'),
array('@', '}'),
$this->parsedContents[$i]
);
}
}
return $this->parsedContents;
}
/**
* Return a formatted variant of the Long Description using MarkDown.
*
* @todo this should become a more intelligent piece of code where the
* configuration contains a setting what format long descriptions are.
*
* @codeCoverageIgnore Will be removed soon, in favor of adapters at
* PhpDocumentor itself that will process text in various formats.
*
* @return string
*/
public function getFormattedContents()
{
$result = $this->contents;
// if the long description contains a plain HTML <code> element, surround
// it with a pre element. Please note that we explicitly used str_replace
// and not preg_replace to gain performance
if (strpos($result, '<code>') !== false) {
$result = str_replace(
array('<code>', "<code>\r\n", "<code>\n", "<code>\r", '</code>'),
array('<pre><code>', '<code>', '<code>', '<code>', '</code></pre>'),
$result
);
}
if (class_exists('Parsedown')) {
$markdown = \Parsedown::instance();
$result = $markdown->parse($result);
} elseif (class_exists('dflydev\markdown\MarkdownExtraParser')) {
$markdown = new \dflydev\markdown\MarkdownExtraParser();
$result = $markdown->transformMarkdown($result);
}
return trim($result);
}
/**
* Gets the docblock this tag belongs to.
*
* @return DocBlock The docblock this description belongs to.
*/
public function getDocBlock()
{
return $this->docblock;
}
/**
* Sets the docblock this tag belongs to.
*
* @param DocBlock $docblock The new docblock this description belongs to.
* Setting NULL removes any association.
*
* @return $this
*/
public function setDocBlock(DocBlock $docblock = null)
{
$this->docblock = $docblock;
return $this;
}
/**
* Builds a string representation of this object.
*
* @todo determine the exact format as used by PHP Reflection
* and implement it.
*
* @return void
* @codeCoverageIgnore Not yet implemented
*/
public static function export()
{
throw new \Exception('Not yet implemented');
}
/**
* Returns the long description as a string.
*
* @return string
*/
public function __toString()
{
return $this->getContents();
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock;
/**
* The location a DocBlock occurs within a file.
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class Location
{
/** @var int Line where the DocBlock text starts. */
protected $lineNumber = 0;
/** @var int Column where the DocBlock text starts. */
protected $columnNumber = 0;
public function __construct(
$lineNumber = 0,
$columnNumber = 0
) {
$this->setLineNumber($lineNumber)->setColumnNumber($columnNumber);
}
/**
* @return int Line where the DocBlock text starts.
*/
public function getLineNumber()
{
return $this->lineNumber;
}
/**
*
* @param type $lineNumber
* @return $this
*/
public function setLineNumber($lineNumber)
{
$this->lineNumber = (int)$lineNumber;
return $this;
}
/**
* @return int Column where the DocBlock text starts.
*/
public function getColumnNumber()
{
return $this->columnNumber;
}
/**
*
* @param int $columnNumber
* @return $this
*/
public function setColumnNumber($columnNumber)
{
$this->columnNumber = (int)$columnNumber;
return $this;
}
}

View File

@ -0,0 +1,198 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
* @copyright 2013 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock;
/**
* Serializes a DocBlock instance.
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class Serializer
{
/** @var string The string to indent the comment with. */
protected $indentString = ' ';
/** @var int The number of times the indent string is repeated. */
protected $indent = 0;
/** @var bool Whether to indent the first line. */
protected $isFirstLineIndented = true;
/** @var int|null The max length of a line. */
protected $lineLength = null;
/**
* Create a Serializer instance.
*
* @param int $indent The number of times the indent string is
* repeated.
* @param string $indentString The string to indent the comment with.
* @param bool $indentFirstLine Whether to indent the first line.
* @param int|null $lineLength The max length of a line or NULL to
* disable line wrapping.
*/
public function __construct(
$indent = 0,
$indentString = ' ',
$indentFirstLine = true,
$lineLength = null
) {
$this->setIndentationString($indentString);
$this->setIndent($indent);
$this->setIsFirstLineIndented($indentFirstLine);
$this->setLineLength($lineLength);
}
/**
* Sets the string to indent comments with.
*
* @param string $indentationString The string to indent comments with.
*
* @return $this This serializer object.
*/
public function setIndentationString($indentString)
{
$this->indentString = (string)$indentString;
return $this;
}
/**
* Gets the string to indent comments with.
*
* @return string The indent string.
*/
public function getIndentationString()
{
return $this->indentString;
}
/**
* Sets the number of indents.
*
* @param int $indent The number of times the indent string is repeated.
*
* @return $this This serializer object.
*/
public function setIndent($indent)
{
$this->indent = (int)$indent;
return $this;
}
/**
* Gets the number of indents.
*
* @return int The number of times the indent string is repeated.
*/
public function getIndent()
{
return $this->indent;
}
/**
* Sets whether or not the first line should be indented.
*
* Sets whether or not the first line (the one with the "/**") should be
* indented.
*
* @param bool $indentFirstLine The new value for this setting.
*
* @return $this This serializer object.
*/
public function setIsFirstLineIndented($indentFirstLine)
{
$this->isFirstLineIndented = (bool)$indentFirstLine;
return $this;
}
/**
* Gets whether or not the first line should be indented.
*
* @return bool Whether or not the first line should be indented.
*/
public function isFirstLineIndented()
{
return $this->isFirstLineIndented;
}
/**
* Sets the line length.
*
* Sets the length of each line in the serialization. Content will be
* wrapped within this limit.
*
* @param int|null $lineLength The length of each line. NULL to disable line
* wrapping altogether.
*
* @return $this This serializer object.
*/
public function setLineLength($lineLength)
{
$this->lineLength = null === $lineLength ? null : (int)$lineLength;
return $this;
}
/**
* Gets the line length.
*
* @return int|null The length of each line or NULL if line wrapping is
* disabled.
*/
public function getLineLength()
{
return $this->lineLength;
}
/**
* Generate a DocBlock comment.
*
* @param DocBlock The DocBlock to serialize.
*
* @return string The serialized doc block.
*/
public function getDocComment(DocBlock $docblock)
{
$indent = str_repeat($this->indentString, $this->indent);
$firstIndent = $this->isFirstLineIndented ? $indent : '';
$text = $docblock->getText();
if ($this->lineLength) {
//3 === strlen(' * ')
$wrapLength = $this->lineLength - strlen($indent) - 3;
$text = wordwrap($text, $wrapLength);
}
$text = str_replace("\n", "\n{$indent} * ", $text);
$comment = "{$firstIndent}/**\n{$indent} * {$text}\n{$indent} *\n";
/** @var Tag $tag */
foreach ($docblock->getTags() as $tag) {
$tagText = (string) $tag;
if ($this->lineLength) {
$tagText = wordwrap($tagText, $wrapLength);
}
$tagText = str_replace("\n", "\n{$indent} * ", $tagText);
$comment .= "{$indent} * {$tagText}\n";
}
$comment .= $indent . ' */';
return $comment;
}
}

View File

@ -0,0 +1,377 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock;
/**
* Parses a tag definition for a DocBlock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class Tag implements \Reflector
{
/**
* PCRE regular expression matching a tag name.
*/
const REGEX_TAGNAME = '[\w\-\_\\\\]+';
/** @var string Name of the tag */
protected $tag = '';
/**
* @var string|null Content of the tag.
* When set to NULL, it means it needs to be regenerated.
*/
protected $content = '';
/** @var string Description of the content of this tag */
protected $description = '';
/**
* @var array|null The description, as an array of strings and Tag objects.
* When set to NULL, it means it needs to be regenerated.
*/
protected $parsedDescription = null;
/** @var Location Location of the tag. */
protected $location = null;
/** @var DocBlock The DocBlock which this tag belongs to. */
protected $docblock = null;
/**
* @var array An array with a tag as a key, and an FQCN to a class that
* handles it as an array value. The class is expected to inherit this
* class.
*/
private static $tagHandlerMappings = array(
'author'
=> '\phpDocumentor\Reflection\DocBlock\Tag\AuthorTag',
'covers'
=> '\phpDocumentor\Reflection\DocBlock\Tag\CoversTag',
'deprecated'
=> '\phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag',
'example'
=> '\phpDocumentor\Reflection\DocBlock\Tag\ExampleTag',
'link'
=> '\phpDocumentor\Reflection\DocBlock\Tag\LinkTag',
'method'
=> '\phpDocumentor\Reflection\DocBlock\Tag\MethodTag',
'param'
=> '\phpDocumentor\Reflection\DocBlock\Tag\ParamTag',
'property-read'
=> '\phpDocumentor\Reflection\DocBlock\Tag\PropertyReadTag',
'property'
=> '\phpDocumentor\Reflection\DocBlock\Tag\PropertyTag',
'property-write'
=> '\phpDocumentor\Reflection\DocBlock\Tag\PropertyWriteTag',
'return'
=> '\phpDocumentor\Reflection\DocBlock\Tag\ReturnTag',
'see'
=> '\phpDocumentor\Reflection\DocBlock\Tag\SeeTag',
'since'
=> '\phpDocumentor\Reflection\DocBlock\Tag\SinceTag',
'source'
=> '\phpDocumentor\Reflection\DocBlock\Tag\SourceTag',
'throw'
=> '\phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag',
'throws'
=> '\phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag',
'uses'
=> '\phpDocumentor\Reflection\DocBlock\Tag\UsesTag',
'var'
=> '\phpDocumentor\Reflection\DocBlock\Tag\VarTag',
'version'
=> '\phpDocumentor\Reflection\DocBlock\Tag\VersionTag'
);
/**
* Factory method responsible for instantiating the correct sub type.
*
* @param string $tag_line The text for this tag, including description.
* @param DocBlock $docblock The DocBlock which this tag belongs to.
* @param Location $location Location of the tag.
*
* @throws \InvalidArgumentException if an invalid tag line was presented.
*
* @return static A new tag object.
*/
final public static function createInstance(
$tag_line,
DocBlock $docblock = null,
Location $location = null
) {
if (!preg_match(
'/^@(' . self::REGEX_TAGNAME . ')(?:\s*([^\s].*)|$)?/us',
$tag_line,
$matches
)) {
throw new \InvalidArgumentException(
'Invalid tag_line detected: ' . $tag_line
);
}
$handler = __CLASS__;
if (isset(self::$tagHandlerMappings[$matches[1]])) {
$handler = self::$tagHandlerMappings[$matches[1]];
} elseif (isset($docblock)) {
$tagName = (string)new Type\Collection(
array($matches[1]),
$docblock->getContext()
);
if (isset(self::$tagHandlerMappings[$tagName])) {
$handler = self::$tagHandlerMappings[$tagName];
}
}
return new $handler(
$matches[1],
isset($matches[2]) ? $matches[2] : '',
$docblock,
$location
);
}
/**
* Registers a handler for tags.
*
* Registers a handler for tags. The class specified is autoloaded if it's
* not available. It must inherit from this class.
*
* @param string $tag Name of tag to regiser a handler for. When
* registering a namespaced tag, the full name, along with a prefixing
* slash MUST be provided.
* @param string|null $handler FQCN of handler. Specifing NULL removes the
* handler for the specified tag, if any.
*
* @return bool TRUE on success, FALSE on failure.
*/
final public static function registerTagHandler($tag, $handler)
{
$tag = trim((string)$tag);
if (null === $handler) {
unset(self::$tagHandlerMappings[$tag]);
return true;
}
if ('' !== $tag
&& class_exists($handler, true)
&& is_subclass_of($handler, __CLASS__)
&& !strpos($tag, '\\') //Accept no slash, and 1st slash at offset 0.
) {
self::$tagHandlerMappings[$tag] = $handler;
return true;
}
return false;
}
/**
* Parses a tag and populates the member variables.
*
* @param string $name Name of the tag.
* @param string $content The contents of the given tag.
* @param DocBlock $docblock The DocBlock which this tag belongs to.
* @param Location $location Location of the tag.
*/
public function __construct(
$name,
$content,
DocBlock $docblock = null,
Location $location = null
) {
$this
->setName($name)
->setContent($content)
->setDocBlock($docblock)
->setLocation($location);
}
/**
* Gets the name of this tag.
*
* @return string The name of this tag.
*/
public function getName()
{
return $this->tag;
}
/**
* Sets the name of this tag.
*
* @param string $name The new name of this tag.
*
* @return $this
* @throws \InvalidArgumentException When an invalid tag name is provided.
*/
public function setName($name)
{
if (!preg_match('/^' . self::REGEX_TAGNAME . '$/u', $name)) {
throw new \InvalidArgumentException(
'Invalid tag name supplied: ' . $name
);
}
$this->tag = $name;
return $this;
}
/**
* Gets the content of this tag.
*
* @return string
*/
public function getContent()
{
if (null === $this->content) {
$this->content = $this->description;
}
return $this->content;
}
/**
* Sets the content of this tag.
*
* @param string $content The new content of this tag.
*
* @return $this
*/
public function setContent($content)
{
$this->setDescription($content);
$this->content = $content;
return $this;
}
/**
* Gets the description component of this tag.
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets the description component of this tag.
*
* @param string $description The new description component of this tag.
*
* @return $this
*/
public function setDescription($description)
{
$this->content = null;
$this->parsedDescription = null;
$this->description = trim($description);
return $this;
}
/**
* Gets the parsed text of this description.
*
* @return array An array of strings and tag objects, in the order they
* occur within the description.
*/
public function getParsedDescription()
{
if (null === $this->parsedDescription) {
$description = new Description($this->description, $this->docblock);
$this->parsedDescription = $description->getParsedContents();
}
return $this->parsedDescription;
}
/**
* Gets the docblock this tag belongs to.
*
* @return DocBlock The docblock this tag belongs to.
*/
public function getDocBlock()
{
return $this->docblock;
}
/**
* Sets the docblock this tag belongs to.
*
* @param DocBlock $docblock The new docblock this tag belongs to. Setting
* NULL removes any association.
*
* @return $this
*/
public function setDocBlock(DocBlock $docblock = null)
{
$this->docblock = $docblock;
return $this;
}
/**
* Gets the location of the tag.
*
* @return Location The tag's location.
*/
public function getLocation()
{
return $this->location;
}
/**
* Sets the location of the tag.
*
* @param Location $location The new location of the tag.
*
* @return $this
*/
public function setLocation(Location $location = null)
{
$this->location = $location;
return $this;
}
/**
* Builds a string representation of this object.
*
* @todo determine the exact format as used by PHP Reflection and implement it.
*
* @return void
* @codeCoverageIgnore Not yet implemented
*/
public static function export()
{
throw new \Exception('Not yet implemented');
}
/**
* Returns the tag as a serialized string
*
* @return string
*/
public function __toString()
{
return "@{$this->getName()} {$this->getContent()}";
}
}

View File

@ -0,0 +1,131 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for an @author tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class AuthorTag extends Tag
{
/**
* PCRE regular expression matching any valid value for the name component.
*/
const REGEX_AUTHOR_NAME = '[^\<]*';
/**
* PCRE regular expression matching any valid value for the email component.
*/
const REGEX_AUTHOR_EMAIL = '[^\>]*';
/** @var string The name of the author */
protected $authorName = '';
/** @var string The email of the author */
protected $authorEmail = '';
public function getContent()
{
if (null === $this->content) {
$this->content = $this->authorName;
if ('' != $this->authorEmail) {
$this->content .= "<{$this->authorEmail}>";
}
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
parent::setContent($content);
if (preg_match(
'/^(' . self::REGEX_AUTHOR_NAME .
')(\<(' . self::REGEX_AUTHOR_EMAIL .
')\>)?$/u',
$this->description,
$matches
)) {
$this->authorName = trim($matches[1]);
if (isset($matches[3])) {
$this->authorEmail = trim($matches[3]);
}
}
return $this;
}
/**
* Gets the author's name.
*
* @return string The author's name.
*/
public function getAuthorName()
{
return $this->authorName;
}
/**
* Sets the author's name.
*
* @param string $authorName The new author name.
* An invalid value will set an empty string.
*
* @return $this
*/
public function setAuthorName($authorName)
{
$this->content = null;
$this->authorName
= preg_match('/^' . self::REGEX_AUTHOR_NAME . '$/u', $authorName)
? $authorName : '';
return $this;
}
/**
* Gets the author's email.
*
* @return string The author's email.
*/
public function getAuthorEmail()
{
return $this->authorEmail;
}
/**
* Sets the author's email.
*
* @param string $authorEmail The new author email.
* An invalid value will set an empty string.
*
* @return $this
*/
public function setAuthorEmail($authorEmail)
{
$this->authorEmail
= preg_match('/^' . self::REGEX_AUTHOR_EMAIL . '$/u', $authorEmail)
? $authorEmail : '';
$this->content = null;
return $this;
}
}

View File

@ -0,0 +1,24 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @covers tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class CoversTag extends SeeTag
{
}

View File

@ -0,0 +1,26 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag\VersionTag;
/**
* Reflection class for a @deprecated tag in a Docblock.
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class DeprecatedTag extends VersionTag
{
}

View File

@ -0,0 +1,156 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @example tag in a Docblock.
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ExampleTag extends SourceTag
{
/**
* @var string Path to a file to use as an example.
* May also be an absolute URI.
*/
protected $filePath = '';
/**
* @var bool Whether the file path component represents an URI.
* This determines how the file portion appears at {@link getContent()}.
*/
protected $isURI = false;
/**
* {@inheritdoc}
*/
public function getContent()
{
if (null === $this->content) {
$filePath = '';
if ($this->isURI) {
if (false === strpos($this->filePath, ':')) {
$filePath = str_replace(
'%2F',
'/',
rawurlencode($this->filePath)
);
} else {
$filePath = $this->filePath;
}
} else {
$filePath = '"' . $this->filePath . '"';
}
$this->content = $filePath . ' ' . parent::getContent();
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
Tag::setContent($content);
if (preg_match(
'/^
# File component
(?:
# File path in quotes
\"([^\"]+)\"
|
# File URI
(\S+)
)
# Remaining content (parsed by SourceTag)
(?:\s+(.*))?
$/sux',
$this->description,
$matches
)) {
if ('' !== $matches[1]) {
$this->setFilePath($matches[1]);
} else {
$this->setFileURI($matches[2]);
}
if (isset($matches[3])) {
parent::setContent($matches[3]);
} else {
$this->setDescription('');
}
$this->content = $content;
}
return $this;
}
/**
* Returns the file path.
*
* @return string Path to a file to use as an example.
* May also be an absolute URI.
*/
public function getFilePath()
{
return $this->filePath;
}
/**
* Sets the file path.
*
* @param string $filePath The new file path to use for the example.
*
* @return $this
*/
public function setFilePath($filePath)
{
$this->isURI = false;
$this->filePath = trim($filePath);
$this->content = null;
return $this;
}
/**
* Sets the file path as an URI.
*
* This function is equivalent to {@link setFilePath()}, except that it
* convers an URI to a file path before that.
*
* There is no getFileURI(), as {@link getFilePath()} is compatible.
*
* @param type $uri The new file URI to use as an example.
*/
public function setFileURI($uri)
{
$this->isURI = true;
if (false === strpos($uri, ':')) {
//Relative URL
$this->filePath = rawurldecode(
str_replace(array('/', '\\'), '%2F', $uri)
);
} else {
//Absolute URL or URI.
$this->filePath = $uri;
}
$this->content = null;
return $this;
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Ben Selby <benmatselby@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @link tag in a Docblock.
*
* @author Ben Selby <benmatselby@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class LinkTag extends Tag
{
/** @var string */
protected $link = '';
/**
* {@inheritdoc}
*/
public function getContent()
{
if (null === $this->content) {
$this->content = "{$this->link} {$this->description}";
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
parent::setContent($content);
$parts = preg_split('/\s+/Su', $this->description, 2);
$this->link = $parts[0];
$this->setDescription(isset($parts[1]) ? $parts[1] : $parts[0]);
$this->content = $content;
return $this;
}
/**
* Gets the link
*
* @return string
*/
public function getLink()
{
return $this->link;
}
/**
* Sets the link
*
* @param string $link The link
*
* @return $this
*/
public function setLink($link)
{
$this->link = $link;
$this->content = null;
return $this;
}
}

View File

@ -0,0 +1,209 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @method in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class MethodTag extends ReturnTag
{
/** @var string */
protected $method_name = '';
/** @var string */
protected $arguments = '';
/** @var bool */
protected $isStatic = false;
/**
* {@inheritdoc}
*/
public function getContent()
{
if (null === $this->content) {
$this->content = '';
if ($this->isStatic) {
$this->content .= 'static ';
}
$this->content .= $this->type .
" {$this->method_name}({$this->arguments}) " .
$this->description;
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
Tag::setContent($content);
// 1. none or more whitespace
// 2. optionally the keyword "static" followed by whitespace
// 3. optionally a word with underscores followed by whitespace : as
// type for the return value
// 4. then optionally a word with underscores followed by () and
// whitespace : as method name as used by phpDocumentor
// 5. then a word with underscores, followed by ( and any character
// until a ) and whitespace : as method name with signature
// 6. any remaining text : as description
if (preg_match(
'/^
# Static keyword
# Declates a static method ONLY if type is also present
(?:
(static)
\s+
)?
# Return type
(?:
([\w\|_\\\\]+)
\s+
)?
# Legacy method name (not captured)
(?:
[\w_]+\(\)\s+
)?
# Method name
([\w\|_\\\\]+)
# Arguments
\(([^\)]*)\)
\s*
# Description
(.*)
$/sux',
$this->description,
$matches
)) {
list(
,
$static,
$this->type,
$this->method_name,
$this->arguments,
$this->description
) = $matches;
if ($static) {
if (!$this->type) {
$this->type = 'static';
} else {
$this->isStatic = true;
}
} else {
if (!$this->type) {
$this->type = 'void';
}
}
$this->parsedDescription = null;
}
return $this;
}
/**
* Sets the name of this method.
*
* @param string $method_name The name of the method.
*
* @return $this
*/
public function setMethodName($method_name)
{
$this->method_name = $method_name;
$this->content = null;
return $this;
}
/**
* Retrieves the method name.
*
* @return string
*/
public function getMethodName()
{
return $this->method_name;
}
/**
* Sets the arguments for this method.
*
* @param string $arguments A comma-separated arguments line.
*
* @return void
*/
public function setArguments($arguments)
{
$this->arguments = $arguments;
$this->content = null;
return $this;
}
/**
* Returns an array containing each argument as array of type and name.
*
* Please note that the argument sub-array may only contain 1 element if no
* type was specified.
*
* @return string[]
*/
public function getArguments()
{
if (empty($this->arguments)) {
return array();
}
$arguments = explode(',', $this->arguments);
foreach ($arguments as $key => $value) {
$arguments[$key] = explode(' ', trim($value));
}
return $arguments;
}
/**
* Checks whether the method tag describes a static method or not.
*
* @return bool TRUE if the method declaration is for a static method, FALSE
* otherwise.
*/
public function isStatic()
{
return $this->isStatic;
}
/**
* Sets a new value for whether the method is static or not.
*
* @param bool $isStatic The new value to set.
*
* @return $this
*/
public function setIsStatic($isStatic)
{
$this->isStatic = $isStatic;
$this->content = null;
return $this;
}
}

View File

@ -0,0 +1,119 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @param tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ParamTag extends ReturnTag
{
/** @var string */
protected $variableName = '';
/** @var bool determines whether this is a variadic argument */
protected $isVariadic = false;
/**
* {@inheritdoc}
*/
public function getContent()
{
if (null === $this->content) {
$this->content
= "{$this->type} {$this->variableName} {$this->description}";
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
Tag::setContent($content);
$parts = preg_split(
'/(\s+)/Su',
$this->description,
3,
PREG_SPLIT_DELIM_CAPTURE
);
// if the first item that is encountered is not a variable; it is a type
if (isset($parts[0])
&& (strlen($parts[0]) > 0)
&& ($parts[0][0] !== '$')
) {
$this->type = array_shift($parts);
array_shift($parts);
}
// if the next item starts with a $ or ...$ it must be the variable name
if (isset($parts[0])
&& (strlen($parts[0]) > 0)
&& ($parts[0][0] == '$' || substr($parts[0], 0, 4) === '...$')
) {
$this->variableName = array_shift($parts);
array_shift($parts);
if (substr($this->variableName, 0, 3) === '...') {
$this->isVariadic = true;
$this->variableName = substr($this->variableName, 3);
}
}
$this->setDescription(implode('', $parts));
$this->content = $content;
return $this;
}
/**
* Returns the variable's name.
*
* @return string
*/
public function getVariableName()
{
return $this->variableName;
}
/**
* Sets the variable's name.
*
* @param string $name The new name for this variable.
*
* @return $this
*/
public function setVariableName($name)
{
$this->variableName = $name;
$this->content = null;
return $this;
}
/**
* Returns whether this tag is variadic.
*
* @return boolean
*/
public function isVariadic()
{
return $this->isVariadic;
}
}

View File

@ -0,0 +1,24 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @property-read tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class PropertyReadTag extends PropertyTag
{
}

View File

@ -0,0 +1,24 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @property tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class PropertyTag extends ParamTag
{
}

View File

@ -0,0 +1,24 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @property-write tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class PropertyWriteTag extends PropertyTag
{
}

View File

@ -0,0 +1,99 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Type\Collection;
/**
* Reflection class for a @return tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ReturnTag extends Tag
{
/** @var string The raw type component. */
protected $type = '';
/** @var Collection The parsed type component. */
protected $types = null;
/**
* {@inheritdoc}
*/
public function getContent()
{
if (null === $this->content) {
$this->content = "{$this->type} {$this->description}";
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
parent::setContent($content);
$parts = preg_split('/\s+/Su', $this->description, 2);
// any output is considered a type
$this->type = $parts[0];
$this->types = null;
$this->setDescription(isset($parts[1]) ? $parts[1] : '');
$this->content = $content;
return $this;
}
/**
* Returns the unique types of the variable.
*
* @return string[]
*/
public function getTypes()
{
return $this->getTypesCollection()->getArrayCopy();
}
/**
* Returns the type section of the variable.
*
* @return string
*/
public function getType()
{
return (string) $this->getTypesCollection();
}
/**
* Returns the type collection.
*
* @return void
*/
protected function getTypesCollection()
{
if (null === $this->types) {
$this->types = new Collection(
array($this->type),
$this->docblock ? $this->docblock->getContext() : null
);
}
return $this->types;
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @see tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class SeeTag extends Tag
{
/** @var string */
protected $refers = null;
/**
* {@inheritdoc}
*/
public function getContent()
{
if (null === $this->content) {
$this->content = "{$this->refers} {$this->description}";
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
parent::setContent($content);
$parts = preg_split('/\s+/Su', $this->description, 2);
// any output is considered a type
$this->refers = $parts[0];
$this->setDescription(isset($parts[1]) ? $parts[1] : '');
$this->content = $content;
return $this;
}
/**
* Gets the structural element this tag refers to.
*
* @return string
*/
public function getReference()
{
return $this->refers;
}
/**
* Sets the structural element this tag refers to.
*
* @param string $refers The new type this tag refers to.
*
* @return $this
*/
public function setReference($refers)
{
$this->refers = $refers;
$this->content = null;
return $this;
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag\VersionTag;
/**
* Reflection class for a @since tag in a Docblock.
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class SinceTag extends VersionTag
{
}

View File

@ -0,0 +1,137 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @source tag in a Docblock.
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class SourceTag extends Tag
{
/**
* @var int The starting line, relative to the structural element's
* location.
*/
protected $startingLine = 1;
/**
* @var int|null The number of lines, relative to the starting line. NULL
* means "to the end".
*/
protected $lineCount = null;
/**
* {@inheritdoc}
*/
public function getContent()
{
if (null === $this->content) {
$this->content
= "{$this->startingLine} {$this->lineCount} {$this->description}";
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
parent::setContent($content);
if (preg_match(
'/^
# Starting line
([1-9]\d*)
\s*
# Number of lines
(?:
((?1))
\s+
)?
# Description
(.*)
$/sux',
$this->description,
$matches
)) {
$this->startingLine = (int)$matches[1];
if (isset($matches[2]) && '' !== $matches[2]) {
$this->lineCount = (int)$matches[2];
}
$this->setDescription($matches[3]);
$this->content = $content;
}
return $this;
}
/**
* Gets the starting line.
*
* @return int The starting line, relative to the structural element's
* location.
*/
public function getStartingLine()
{
return $this->startingLine;
}
/**
* Sets the starting line.
*
* @param int $startingLine The new starting line, relative to the
* structural element's location.
*
* @return $this
*/
public function setStartingLine($startingLine)
{
$this->startingLine = $startingLine;
$this->content = null;
return $this;
}
/**
* Returns the number of lines.
*
* @return int|null The number of lines, relative to the starting line. NULL
* means "to the end".
*/
public function getLineCount()
{
return $this->lineCount;
}
/**
* Sets the number of lines.
*
* @param int|null $lineCount The new number of lines, relative to the
* starting line. NULL means "to the end".
*
* @return $this
*/
public function setLineCount($lineCount)
{
$this->lineCount = $lineCount;
$this->content = null;
return $this;
}
}

View File

@ -0,0 +1,24 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @throws tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ThrowsTag extends ReturnTag
{
}

View File

@ -0,0 +1,24 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @uses tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class UsesTag extends SeeTag
{
}

View File

@ -0,0 +1,24 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @var tag in a Docblock.
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class VarTag extends ParamTag
{
}

View File

@ -0,0 +1,108 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tag;
/**
* Reflection class for a @version tag in a Docblock.
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class VersionTag extends Tag
{
/**
* PCRE regular expression matching a version vector.
* Assumes the "x" modifier.
*/
const REGEX_VECTOR = '(?:
# Normal release vectors.
\d\S*
|
# VCS version vectors. Per PHPCS, they are expected to
# follow the form of the VCS name, followed by ":", followed
# by the version vector itself.
# By convention, popular VCSes like CVS, SVN and GIT use "$"
# around the actual version vector.
[^\s\:]+\:\s*\$[^\$]+\$
)';
/** @var string The version vector. */
protected $version = '';
public function getContent()
{
if (null === $this->content) {
$this->content = "{$this->version} {$this->description}";
}
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setContent($content)
{
parent::setContent($content);
if (preg_match(
'/^
# The version vector
(' . self::REGEX_VECTOR . ')
\s*
# The description
(.+)?
$/sux',
$this->description,
$matches
)) {
$this->version = $matches[1];
$this->setDescription(isset($matches[2]) ? $matches[2] : '');
$this->content = $content;
}
return $this;
}
/**
* Gets the version section of the tag.
*
* @return string The version section of the tag.
*/
public function getVersion()
{
return $this->version;
}
/**
* Sets the version section of the tag.
*
* @param string $version The new version section of the tag.
* An invalid value will set an empty string.
*
* @return $this
*/
public function setVersion($version)
{
$this->version
= preg_match('/^' . self::REGEX_VECTOR . '$/ux', $version)
? $version
: '';
$this->content = null;
return $this;
}
}

View File

@ -0,0 +1,221 @@
<?php
/**
* phpDocumentor
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Type;
use phpDocumentor\Reflection\DocBlock\Context;
/**
* Collection
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class Collection extends \ArrayObject
{
/** @var string Definition of the OR operator for types */
const OPERATOR_OR = '|';
/** @var string Definition of the ARRAY operator for types */
const OPERATOR_ARRAY = '[]';
/** @var string Definition of the NAMESPACE operator in PHP */
const OPERATOR_NAMESPACE = '\\';
/** @var string[] List of recognized keywords */
protected static $keywords = array(
'string', 'int', 'integer', 'bool', 'boolean', 'float', 'double',
'object', 'mixed', 'array', 'resource', 'void', 'null', 'scalar',
'callback', 'callable', 'false', 'true', 'self', '$this', 'static'
);
/**
* Current invoking location.
*
* This is used to prepend to type with a relative location.
* May also be 'default' or 'global', in which case they are ignored.
*
* @var Context
*/
protected $context = null;
/**
* Registers the namespace and aliases; uses that to add and expand the
* given types.
*
* @param string[] $types Array containing a list of types to add to this
* container.
* @param Context $location The current invoking location.
*/
public function __construct(
array $types = array(),
Context $context = null
) {
$this->context = null === $context ? new Context() : $context;
foreach ($types as $type) {
$this->add($type);
}
}
/**
* Returns the current invoking location.
*
* @return Context
*/
public function getContext()
{
return $this->context;
}
/**
* Adds a new type to the collection and expands it if it contains a
* relative namespace.
*
* If a class in the type contains a relative namespace than this collection
* will try to expand that into a FQCN.
*
* @param string $type A 'Type' as defined in the phpDocumentor
* documentation.
*
* @throws \InvalidArgumentException if a non-string argument is passed.
*
* @see http://phpdoc.org/docs/latest/for-users/types.html for the
* definition of a type.
*
* @return void
*/
public function add($type)
{
if (!is_string($type)) {
throw new \InvalidArgumentException(
'A type should be represented by a string, received: '
.var_export($type, true)
);
}
// separate the type by the OR operator
$type_parts = explode(self::OPERATOR_OR, $type);
foreach ($type_parts as $part) {
$expanded_type = $this->expand($part);
if ($expanded_type) {
$this[] = $expanded_type;
}
}
}
/**
* Returns a string representation of the collection.
*
* @return string The resolved types across the collection, separated with
* {@link self::OPERATOR_OR}.
*/
public function __toString()
{
return implode(self::OPERATOR_OR, $this->getArrayCopy());
}
/**
* Analyzes the given type and returns the FQCN variant.
*
* When a type is provided this method checks whether it is not a keyword or
* Fully Qualified Class Name. If so it will use the given namespace and
* aliases to expand the type to a FQCN representation.
*
* This method only works as expected if the namespace and aliases are set;
* no dynamic reflection is being performed here.
*
* @param string $type The relative or absolute type.
*
* @uses getNamespace to determine with what to prefix the type name.
* @uses getNamespaceAliases to check whether the first part of the relative
* type name should not be replaced with another namespace.
*
* @return string
*/
protected function expand($type)
{
$type = trim($type);
if (!$type) {
return '';
}
if ($this->isTypeAnArray($type)) {
return $this->expand(substr($type, 0, -2)) . self::OPERATOR_ARRAY;
}
if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type)) {
$type_parts = explode(self::OPERATOR_NAMESPACE, $type, 2);
$namespace_aliases = $this->context->getNamespaceAliases();
// if the first segment is not an alias; prepend namespace name and
// return
if (!isset($namespace_aliases[$type_parts[0]])) {
$namespace = $this->context->getNamespace();
if ('' !== $namespace) {
$namespace .= self::OPERATOR_NAMESPACE;
}
return self::OPERATOR_NAMESPACE . $namespace . $type;
}
$type_parts[0] = $namespace_aliases[$type_parts[0]];
$type = implode(self::OPERATOR_NAMESPACE, $type_parts);
}
return $type;
}
/**
* Detects whether the given type represents an array.
*
* @param string $type A relative or absolute type as defined in the
* phpDocumentor documentation.
*
* @return bool
*/
protected function isTypeAnArray($type)
{
return substr($type, -2) === self::OPERATOR_ARRAY;
}
/**
* Detects whether the given type represents a PHPDoc keyword.
*
* @param string $type A relative or absolute type as defined in the
* phpDocumentor documentation.
*
* @return bool
*/
protected function isTypeAKeyword($type)
{
return in_array(strtolower($type), static::$keywords, true);
}
/**
* Detects whether the given type represents a relative or absolute path.
*
* This method will detect keywords as being absolute; even though they are
* not preceeded by a namespace separator.
*
* @param string $type A relative or absolute type as defined in the
* phpDocumentor documentation.
*
* @return bool
*/
protected function isRelativeType($type)
{
return ($type[0] !== self::OPERATOR_NAMESPACE)
|| $this->isTypeAKeyword($type);
}
}

View File

@ -0,0 +1,245 @@
<?php
/**
* phpDocumentor Description Test
*
* PHP Version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Description
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class DescriptionTest extends \PHPUnit_Framework_TestCase
{
public function testConstruct()
{
$fixture = <<<LONGDESC
This is text for a description.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(1, $parsedContents);
$this->assertSame($fixture, $parsedContents[0]);
}
public function testInlineTagParsing()
{
$fixture = <<<LONGDESC
This is text for a {@link http://phpdoc.org/ description} that uses inline
tags.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(3, $parsedContents);
$this->assertSame('This is text for a ', $parsedContents[0]);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag\LinkTag',
$parsedContents[1]
);
$this->assertSame(
' that uses inline
tags.',
$parsedContents[2]
);
}
public function testInlineTagAtStartParsing()
{
$fixture = <<<LONGDESC
{@link http://phpdoc.org/ This} is text for a description that uses inline
tags.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(3, $parsedContents);
$this->assertSame('', $parsedContents[0]);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag\LinkTag',
$parsedContents[1]
);
$this->assertSame(
' is text for a description that uses inline
tags.',
$parsedContents[2]
);
}
public function testNestedInlineTagParsing()
{
$fixture = <<<LONGDESC
This is text for a description with {@internal inline tag with
{@link http://phpdoc.org another inline tag} in it}.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(3, $parsedContents);
$this->assertSame(
'This is text for a description with ',
$parsedContents[0]
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$parsedContents[1]
);
$this->assertSame('.', $parsedContents[2]);
$parsedDescription = $parsedContents[1]->getParsedDescription();
$this->assertCount(3, $parsedDescription);
$this->assertSame("inline tag with\n", $parsedDescription[0]);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag\LinkTag',
$parsedDescription[1]
);
$this->assertSame(' in it', $parsedDescription[2]);
}
public function testLiteralOpeningDelimiter()
{
$fixture = <<<LONGDESC
This is text for a description containing { that is literal.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(1, $parsedContents);
$this->assertSame($fixture, $parsedContents[0]);
}
public function testNestedLiteralOpeningDelimiter()
{
$fixture = <<<LONGDESC
This is text for a description containing {@internal inline tag that has { that
is literal}.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(3, $parsedContents);
$this->assertSame(
'This is text for a description containing ',
$parsedContents[0]
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$parsedContents[1]
);
$this->assertSame('.', $parsedContents[2]);
$this->assertSame(
array('inline tag that has { that
is literal'),
$parsedContents[1]->getParsedDescription()
);
}
public function testLiteralClosingDelimiter()
{
$fixture = <<<LONGDESC
This is text for a description with {} that is not a tag.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(1, $parsedContents);
$this->assertSame(
'This is text for a description with } that is not a tag.',
$parsedContents[0]
);
}
public function testNestedLiteralClosingDelimiter()
{
$fixture = <<<LONGDESC
This is text for a description with {@internal inline tag with {} that is not an
inline tag}.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(3, $parsedContents);
$this->assertSame(
'This is text for a description with ',
$parsedContents[0]
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$parsedContents[1]
);
$this->assertSame('.', $parsedContents[2]);
$this->assertSame(
array('inline tag with } that is not an
inline tag'),
$parsedContents[1]->getParsedDescription()
);
}
public function testInlineTagEscapingSequence()
{
$fixture = <<<LONGDESC
This is text for a description with literal {{@}link}.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(1, $parsedContents);
$this->assertSame(
'This is text for a description with literal {@link}.',
$parsedContents[0]
);
}
public function testNestedInlineTagEscapingSequence()
{
$fixture = <<<LONGDESC
This is text for a description with an {@internal inline tag with literal
{{@}link{} in it}.
LONGDESC;
$object = new Description($fixture);
$this->assertSame($fixture, $object->getContents());
$parsedContents = $object->getParsedContents();
$this->assertCount(3, $parsedContents);
$this->assertSame(
'This is text for a description with an ',
$parsedContents[0]
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$parsedContents[1]
);
$this->assertSame('.', $parsedContents[2]);
$this->assertSame(
array('inline tag with literal
{@link} in it'),
$parsedContents[1]->getParsedDescription()
);
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* phpDocumentor Covers Tag Test
*
* PHP version 5.3
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\CoversTag
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class CoversTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\CoversTag can create
* a link for the covers doc block.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exReference
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\CoversTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exReference
) {
$tag = new CoversTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exReference, $tag->getReference());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exReference
return array(
array(
'covers',
'Foo::bar()',
'Foo::bar()',
'',
'Foo::bar()'
),
array(
'covers',
'Foo::bar() Testing',
'Foo::bar() Testing',
'Testing',
'Foo::bar()',
),
array(
'covers',
'Foo::bar() Testing comments',
'Foo::bar() Testing comments',
'Testing comments',
'Foo::bar()',
),
);
}
}

View File

@ -0,0 +1,115 @@
<?php
/**
* phpDocumentor Deprecated Tag Test
*
* PHP version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class DeprecatedTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\LinkTag can create
* a link for the @deprecated doc block.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exDescription
* @param string $exVersion
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exVersion
) {
$tag = new DeprecatedTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exVersion, $tag->getVersion());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exVersion
return array(
array(
'deprecated',
'1.0 First release.',
'1.0 First release.',
'First release.',
'1.0'
),
array(
'deprecated',
"1.0\nFirst release.",
"1.0\nFirst release.",
'First release.',
'1.0'
),
array(
'deprecated',
"1.0\nFirst\nrelease.",
"1.0\nFirst\nrelease.",
"First\nrelease.",
'1.0'
),
array(
'deprecated',
'Unfinished release',
'Unfinished release',
'Unfinished release',
''
),
array(
'deprecated',
'1.0',
'1.0',
'',
'1.0'
),
array(
'deprecated',
'GIT: $Id$',
'GIT: $Id$',
'',
'GIT: $Id$'
),
array(
'deprecated',
'GIT: $Id$ Dev build',
'GIT: $Id$ Dev build',
'Dev build',
'GIT: $Id$'
)
);
}
}

View File

@ -0,0 +1,203 @@
<?php
/**
* phpDocumentor Example Tag Test
*
* PHP version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\ExampleTag
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ExampleTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\SourceTag can
* understand the @source DocBlock.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exStartingLine
* @param string $exLineCount
* @param string $exFilepath
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ExampleTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exStartingLine,
$exLineCount,
$exFilePath
) {
$tag = new ExampleTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exStartingLine, $tag->getStartingLine());
$this->assertEquals($exLineCount, $tag->getLineCount());
$this->assertEquals($exFilePath, $tag->getFilePath());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type,
// $content,
// $exContent,
// $exDescription,
// $exStartingLine,
// $exLineCount,
// $exFilePath
return array(
array(
'example',
'file.php',
'file.php',
'',
1,
null,
'file.php'
),
array(
'example',
'Testing comments',
'Testing comments',
'comments',
1,
null,
'Testing'
),
array(
'example',
'file.php 2 Testing',
'file.php 2 Testing',
'Testing',
2,
null,
'file.php'
),
array(
'example',
'file.php 2 3 Testing comments',
'file.php 2 3 Testing comments',
'Testing comments',
2,
3,
'file.php'
),
array(
'example',
'file.php 2 -1 Testing comments',
'file.php 2 -1 Testing comments',
'-1 Testing comments',
2,
null,
'file.php'
),
array(
'example',
'file.php -1 1 Testing comments',
'file.php -1 1 Testing comments',
'-1 1 Testing comments',
1,
null,
'file.php'
),
array(
'example',
'"file with spaces.php" Testing comments',
'"file with spaces.php" Testing comments',
'Testing comments',
1,
null,
'file with spaces.php'
),
array(
'example',
'"file with spaces.php" 2 Testing comments',
'"file with spaces.php" 2 Testing comments',
'Testing comments',
2,
null,
'file with spaces.php'
),
array(
'example',
'"file with spaces.php" 2 3 Testing comments',
'"file with spaces.php" 2 3 Testing comments',
'Testing comments',
2,
3,
'file with spaces.php'
),
array(
'example',
'"file with spaces.php" 2 -3 Testing comments',
'"file with spaces.php" 2 -3 Testing comments',
'-3 Testing comments',
2,
null,
'file with spaces.php'
),
array(
'example',
'"file with spaces.php" -2 3 Testing comments',
'"file with spaces.php" -2 3 Testing comments',
'-2 3 Testing comments',
1,
null,
'file with spaces.php'
),
array(
'example',
'file%20with%20spaces.php Testing comments',
'file%20with%20spaces.php Testing comments',
'Testing comments',
1,
null,
'file with spaces.php'
),
array(
'example',
'folder/file%20with%20spaces.php Testing comments',
'folder/file%20with%20spaces.php Testing comments',
'Testing comments',
1,
null,
'folder/file with spaces.php'
),
array(
'example',
'http://example.com/file%20with%20spaces.php Testing comments',
'http://example.com/file%20with%20spaces.php Testing comments',
'Testing comments',
1,
null,
'http://example.com/file%20with%20spaces.php'
)
);
}
}

View File

@ -0,0 +1,87 @@
<?php
/**
* phpDocumentor Link Tag Test
*
* PHP version 5.3
*
* @author Ben Selby <benmatselby@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\LinkTag
*
* @author Ben Selby <benmatselby@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class LinkTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\LinkTag can create
* a link for the @link doc block.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exDescription
* @param string $exLink
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\LinkTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exLink
) {
$tag = new LinkTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exLink, $tag->getLink());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exLink
return array(
array(
'link',
'http://www.phpdoc.org/',
'http://www.phpdoc.org/',
'http://www.phpdoc.org/',
'http://www.phpdoc.org/'
),
array(
'link',
'http://www.phpdoc.org/ Testing',
'http://www.phpdoc.org/ Testing',
'Testing',
'http://www.phpdoc.org/'
),
array(
'link',
'http://www.phpdoc.org/ Testing comments',
'http://www.phpdoc.org/ Testing comments',
'Testing comments',
'http://www.phpdoc.org/'
),
);
}
}

View File

@ -0,0 +1,146 @@
<?php
/**
* phpDocumentor Method Tag Test
*
* PHP version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\MethodTag
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class MethodTagTest extends \PHPUnit_Framework_TestCase
{
/**
* @param string $signature The signature to test.
* @param bool $valid Whether the given signature is expected to
* be valid.
* @param string $expected_name The method name that is expected from this
* signature.
* @param string $expected_return The return type that is expected from this
* signature.
* @param bool $paramCount Number of parameters in the signature.
* @param string $description The short description mentioned in the
* signature.
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\MethodTag
* @dataProvider getTestSignatures
*
* @return void
*/
public function testConstruct(
$signature,
$valid,
$expected_name,
$expected_return,
$expected_isStatic,
$paramCount,
$description
) {
ob_start();
$tag = new MethodTag('method', $signature);
$stdout = ob_get_clean();
$this->assertSame(
$valid,
empty($stdout),
'No error should have been output if the signature is valid'
);
if (!$valid) {
return;
}
$this->assertEquals($expected_name, $tag->getMethodName());
$this->assertEquals($expected_return, $tag->getType());
$this->assertEquals($description, $tag->getDescription());
$this->assertEquals($expected_isStatic, $tag->isStatic());
$this->assertCount($paramCount, $tag->getArguments());
}
public function getTestSignatures()
{
return array(
// TODO: Verify this case
// array(
// 'foo',
// false, 'foo', '', false, 0, ''
// ),
array(
'foo()',
true, 'foo', 'void', false, 0, ''
),
array(
'foo() description',
true, 'foo', 'void', false, 0, 'description'
),
array(
'int foo()',
true, 'foo', 'int', false, 0, ''
),
array(
'int foo() description',
true, 'foo', 'int', false, 0, 'description'
),
array(
'int foo($a, $b)',
true, 'foo', 'int', false, 2, ''
),
array(
'int foo() foo(int $a, int $b)',
true, 'foo', 'int', false, 2, ''
),
array(
'int foo(int $a, int $b)',
true, 'foo', 'int', false, 2, ''
),
array(
'null|int foo(int $a, int $b)',
true, 'foo', 'null|int', false, 2, ''
),
array(
'int foo(null|int $a, int $b)',
true, 'foo', 'int', false, 2, ''
),
array(
'\Exception foo() foo(Exception $a, Exception $b)',
true, 'foo', '\Exception', false, 2, ''
),
array(
'int foo() foo(Exception $a, Exception $b) description',
true, 'foo', 'int', false, 2, 'description'
),
array(
'int foo() foo(\Exception $a, \Exception $b) description',
true, 'foo', 'int', false, 2, 'description'
),
array(
'void()',
true, 'void', 'void', false, 0, ''
),
array(
'static foo()',
true, 'foo', 'static', false, 0, ''
),
array(
'static void foo()',
true, 'foo', 'void', true, 0, ''
),
array(
'static static foo()',
true, 'foo', 'static', true, 0, ''
)
);
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* phpDocumentor Param tag test.
*
* PHP version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\ParamTag
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ParamTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\ParamTag can
* understand the @param DocBlock.
*
* @param string $type
* @param string $content
* @param string $extractedType
* @param string $extractedTypes
* @param string $extractedVarName
* @param string $extractedDescription
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ParamTag
* @dataProvider provideDataForConstructor
*
* @return void
*/
public function testConstructorParsesInputsIntoCorrectFields(
$type,
$content,
$extractedType,
$extractedTypes,
$extractedVarName,
$extractedDescription
) {
$tag = new ParamTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($extractedType, $tag->getType());
$this->assertEquals($extractedTypes, $tag->getTypes());
$this->assertEquals($extractedVarName, $tag->getVariableName());
$this->assertEquals($extractedDescription, $tag->getDescription());
}
/**
* Data provider for testConstructorParsesInputsIntoCorrectFields()
*
* @return array
*/
public function provideDataForConstructor()
{
return array(
array('param', 'int', 'int', array('int'), '', ''),
array('param', '$bob', '', array(), '$bob', ''),
array(
'param',
'int Number of bobs',
'int',
array('int'),
'',
'Number of bobs'
),
array(
'param',
'int $bob',
'int',
array('int'),
'$bob',
''
),
array(
'param',
'int $bob Number of bobs',
'int',
array('int'),
'$bob',
'Number of bobs'
),
array(
'param',
"int Description \n on multiple lines",
'int',
array('int'),
'',
"Description \n on multiple lines"
),
array(
'param',
"int \n\$bob Variable name on a new line",
'int',
array('int'),
'$bob',
"Variable name on a new line"
),
array(
'param',
"\nint \$bob Type on a new line",
'int',
array('int'),
'$bob',
"Type on a new line"
)
);
}
}

View File

@ -0,0 +1,102 @@
<?php
/**
* phpDocumentor Return tag test.
*
* PHP version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\ReturnTag
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ReturnTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag can
* understand the @return DocBlock.
*
* @param string $type
* @param string $content
* @param string $extractedType
* @param string $extractedTypes
* @param string $extractedDescription
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag
* @dataProvider provideDataForConstructor
*
* @return void
*/
public function testConstructorParsesInputsIntoCorrectFields(
$type,
$content,
$extractedType,
$extractedTypes,
$extractedDescription
) {
$tag = new ReturnTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($extractedType, $tag->getType());
$this->assertEquals($extractedTypes, $tag->getTypes());
$this->assertEquals($extractedDescription, $tag->getDescription());
}
/**
* Data provider for testConstructorParsesInputsIntoCorrectFields()
*
* @return array
*/
public function provideDataForConstructor()
{
return array(
array('return', '', '', array(), ''),
array('return', 'int', 'int', array('int'), ''),
array(
'return',
'int Number of Bobs',
'int',
array('int'),
'Number of Bobs'
),
array(
'return',
'int|double Number of Bobs',
'int|double',
array('int', 'double'),
'Number of Bobs'
),
array(
'return',
"int Number of \n Bobs",
'int',
array('int'),
"Number of \n Bobs"
),
array(
'return',
" int Number of Bobs",
'int',
array('int'),
"Number of Bobs"
),
array(
'return',
"int\nNumber of Bobs",
'int',
array('int'),
"Number of Bobs"
)
);
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* phpDocumentor See Tag Test
*
* PHP version 5.3
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\SeeTag
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class SeeTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the phpDocumentor_Reflection_DocBlock_Tag_See can create a link
* for the @see doc block.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exReference
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\SeeTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exReference
) {
$tag = new SeeTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exReference, $tag->getReference());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exReference
return array(
array(
'see',
'Foo::bar()',
'Foo::bar()',
'',
'Foo::bar()'
),
array(
'see',
'Foo::bar() Testing',
'Foo::bar() Testing',
'Testing',
'Foo::bar()',
),
array(
'see',
'Foo::bar() Testing comments',
'Foo::bar() Testing comments',
'Testing comments',
'Foo::bar()',
),
);
}
}

View File

@ -0,0 +1,115 @@
<?php
/**
* phpDocumentor Since Tag Test
*
* PHP version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\SinceTag
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class SinceTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\LinkTag can create
* a link for the @since doc block.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exDescription
* @param string $exVersion
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\SinceTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exVersion
) {
$tag = new SinceTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exVersion, $tag->getVersion());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exVersion
return array(
array(
'since',
'1.0 First release.',
'1.0 First release.',
'First release.',
'1.0'
),
array(
'since',
"1.0\nFirst release.",
"1.0\nFirst release.",
'First release.',
'1.0'
),
array(
'since',
"1.0\nFirst\nrelease.",
"1.0\nFirst\nrelease.",
"First\nrelease.",
'1.0'
),
array(
'since',
'Unfinished release',
'Unfinished release',
'Unfinished release',
''
),
array(
'since',
'1.0',
'1.0',
'',
'1.0'
),
array(
'since',
'GIT: $Id$',
'GIT: $Id$',
'',
'GIT: $Id$'
),
array(
'since',
'GIT: $Id$ Dev build',
'GIT: $Id$ Dev build',
'Dev build',
'GIT: $Id$'
)
);
}
}

View File

@ -0,0 +1,116 @@
<?php
/**
* phpDocumentor Source Tag Test
*
* PHP version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\SourceTag
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class SourceTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\SourceTag can
* understand the @source DocBlock.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exStartingLine
* @param string $exLineCount
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\SourceTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exStartingLine,
$exLineCount
) {
$tag = new SourceTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exStartingLine, $tag->getStartingLine());
$this->assertEquals($exLineCount, $tag->getLineCount());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exStartingLine, $exLineCount
return array(
array(
'source',
'2',
'2',
'',
2,
null
),
array(
'source',
'Testing',
'Testing',
'Testing',
1,
null
),
array(
'source',
'2 Testing',
'2 Testing',
'Testing',
2,
null
),
array(
'source',
'2 3 Testing comments',
'2 3 Testing comments',
'Testing comments',
2,
3
),
array(
'source',
'2 -1 Testing comments',
'2 -1 Testing comments',
'-1 Testing comments',
2,
null
),
array(
'source',
'-1 1 Testing comments',
'-1 1 Testing comments',
'-1 1 Testing comments',
1,
null
)
);
}
}

View File

@ -0,0 +1,102 @@
<?php
/**
* phpDocumentor Throws tag test.
*
* PHP version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\ThrowsTag
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class ThrowsTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag can
* understand the @throws DocBlock.
*
* @param string $type
* @param string $content
* @param string $extractedType
* @param string $extractedTypes
* @param string $extractedDescription
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag
* @dataProvider provideDataForConstructor
*
* @return void
*/
public function testConstructorParsesInputsIntoCorrectFields(
$type,
$content,
$extractedType,
$extractedTypes,
$extractedDescription
) {
$tag = new ThrowsTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($extractedType, $tag->getType());
$this->assertEquals($extractedTypes, $tag->getTypes());
$this->assertEquals($extractedDescription, $tag->getDescription());
}
/**
* Data provider for testConstructorParsesInputsIntoCorrectFields()
*
* @return array
*/
public function provideDataForConstructor()
{
return array(
array('throws', '', '', array(), ''),
array('throws', 'int', 'int', array('int'), ''),
array(
'throws',
'int Number of Bobs',
'int',
array('int'),
'Number of Bobs'
),
array(
'throws',
'int|double Number of Bobs',
'int|double',
array('int', 'double'),
'Number of Bobs'
),
array(
'throws',
"int Number of \n Bobs",
'int',
array('int'),
"Number of \n Bobs"
),
array(
'throws',
" int Number of Bobs",
'int',
array('int'),
"Number of Bobs"
),
array(
'throws',
"int\nNumber of Bobs",
'int',
array('int'),
"Number of Bobs"
)
);
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* phpDocumentor Uses Tag Test
*
* PHP version 5.3
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\UsesTag
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class UsesTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\UsesTag can create
* a link for the @uses doc block.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exReference
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\UsesTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exReference
) {
$tag = new UsesTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exReference, $tag->getReference());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exReference
return array(
array(
'uses',
'Foo::bar()',
'Foo::bar()',
'',
'Foo::bar()'
),
array(
'uses',
'Foo::bar() Testing',
'Foo::bar() Testing',
'Testing',
'Foo::bar()',
),
array(
'uses',
'Foo::bar() Testing comments',
'Foo::bar() Testing comments',
'Testing comments',
'Foo::bar()',
),
);
}
}

View File

@ -0,0 +1,94 @@
<?php
/**
* phpDocumentor Var Tag Test
*
* PHP version 5.3
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\VarTag
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class VarTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\VarTag can
* understand the @var doc block.
*
* @param string $type
* @param string $content
* @param string $exType
* @param string $exVariable
* @param string $exDescription
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\VarTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exType,
$exVariable,
$exDescription
) {
$tag = new VarTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exType, $tag->getType());
$this->assertEquals($exVariable, $tag->getVariableName());
$this->assertEquals($exDescription, $tag->getDescription());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exType, $exVariable, $exDescription
return array(
array(
'var',
'int',
'int',
'',
''
),
array(
'var',
'int $bob',
'int',
'$bob',
''
),
array(
'var',
'int $bob Number of bobs',
'int',
'$bob',
'Number of bobs'
),
array(
'var',
'',
'',
'',
''
),
);
}
}

View File

@ -0,0 +1,115 @@
<?php
/**
* phpDocumentor Version Tag Test
*
* PHP version 5.3
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Tag;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\VersionTag
*
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class VersionTagTest extends \PHPUnit_Framework_TestCase
{
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\LinkTag can create
* a link for the @version doc block.
*
* @param string $type
* @param string $content
* @param string $exContent
* @param string $exDescription
* @param string $exVersion
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag\VersionTag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exContent,
$exDescription,
$exVersion
) {
$tag = new VersionTag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($exContent, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
$this->assertEquals($exVersion, $tag->getVersion());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exContent, $exDescription, $exVersion
return array(
array(
'version',
'1.0 First release.',
'1.0 First release.',
'First release.',
'1.0'
),
array(
'version',
"1.0\nFirst release.",
"1.0\nFirst release.",
'First release.',
'1.0'
),
array(
'version',
"1.0\nFirst\nrelease.",
"1.0\nFirst\nrelease.",
"First\nrelease.",
'1.0'
),
array(
'version',
'Unfinished release',
'Unfinished release',
'Unfinished release',
''
),
array(
'version',
'1.0',
'1.0',
'',
'1.0'
),
array(
'version',
'GIT: $Id$',
'GIT: $Id$',
'',
'GIT: $Id$'
),
array(
'version',
'GIT: $Id$ Dev build',
'GIT: $Id$ Dev build',
'Dev build',
'GIT: $Id$'
)
);
}
}

View File

@ -0,0 +1,313 @@
<?php
/**
* phpDocumentor Var Tag Test
*
* PHP version 5.3
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Tag\VarTag
*
* @author Daniel O'Connor <daniel.oconnor@gmail.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class TagTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException \InvalidArgumentException
*
* @return void
*/
public function testInvalidTagLine()
{
Tag::createInstance('Invalid tag line');
}
/**
* @covers \phpDocumentor\Reflection\DocBlock\Tag::registerTagHandler
*
* @return void
*/
public function testTagHandlerUnregistration()
{
$currentHandler = __NAMESPACE__ . '\Tag\VarTag';
$tagPreUnreg = Tag::createInstance('@var mixed');
$this->assertInstanceOf(
$currentHandler,
$tagPreUnreg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPreUnreg
);
Tag::registerTagHandler('var', null);
$tagPostUnreg = Tag::createInstance('@var mixed');
$this->assertNotInstanceOf(
$currentHandler,
$tagPostUnreg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPostUnreg
);
Tag::registerTagHandler('var', $currentHandler);
}
/**
* @covers \phpDocumentor\Reflection\DocBlock\Tag::registerTagHandler
*
* @return void
*/
public function testTagHandlerCorrectRegistration()
{
if (0 == ini_get('allow_url_include')) {
$this->markTestSkipped('"data" URIs for includes are required.');
}
$currentHandler = __NAMESPACE__ . '\Tag\VarTag';
$tagPreReg = Tag::createInstance('@var mixed');
$this->assertInstanceOf(
$currentHandler,
$tagPreReg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPreReg
);
include 'data:text/plain;base64,'. base64_encode(
<<<TAG_HANDLER
<?php
class MyTagHandler extends \phpDocumentor\Reflection\DocBlock\Tag {}
TAG_HANDLER
);
$this->assertTrue(Tag::registerTagHandler('var', '\MyTagHandler'));
$tagPostReg = Tag::createInstance('@var mixed');
$this->assertNotInstanceOf(
$currentHandler,
$tagPostReg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPostReg
);
$this->assertInstanceOf(
'\MyTagHandler',
$tagPostReg
);
$this->assertTrue(Tag::registerTagHandler('var', $currentHandler));
}
/**
* @depends testTagHandlerCorrectRegistration
* @covers \phpDocumentor\Reflection\DocBlock\Tag::registerTagHandler
* @covers \phpDocumentor\Reflection\DocBlock\Tag::createInstance
*
* @return void
*/
public function testNamespacedTagHandlerCorrectRegistration()
{
$tagPreReg = Tag::createInstance('@T something');
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPreReg
);
$this->assertNotInstanceOf(
'\MyTagHandler',
$tagPreReg
);
$this->assertTrue(
Tag::registerTagHandler('\MyNamespace\MyTag', '\MyTagHandler')
);
$tagPostReg = Tag::createInstance(
'@T something',
new DocBlock(
'',
new Context('', array('T' => '\MyNamespace\MyTag'))
)
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPostReg
);
$this->assertInstanceOf(
'\MyTagHandler',
$tagPostReg
);
$this->assertTrue(
Tag::registerTagHandler('\MyNamespace\MyTag', null)
);
}
/**
* @depends testTagHandlerCorrectRegistration
* @covers \phpDocumentor\Reflection\DocBlock\Tag::registerTagHandler
* @covers \phpDocumentor\Reflection\DocBlock\Tag::createInstance
*
* @return void
*/
public function testNamespacedTagHandlerIncorrectRegistration()
{
$tagPreReg = Tag::createInstance('@T something');
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPreReg
);
$this->assertNotInstanceOf(
'\MyTagHandler',
$tagPreReg
);
$this->assertFalse(
Tag::registerTagHandler('MyNamespace\MyTag', '\MyTagHandler')
);
$tagPostReg = Tag::createInstance(
'@T something',
new DocBlock(
'',
new Context('', array('T' => '\MyNamespace\MyTag'))
)
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPostReg
);
$this->assertNotInstanceOf(
'\MyTagHandler',
$tagPostReg
);
}
/**
* @covers \phpDocumentor\Reflection\DocBlock\Tag::registerTagHandler
*
* @return void
*/
public function testNonExistentTagHandlerRegistration()
{
$currentHandler = __NAMESPACE__ . '\Tag\VarTag';
$tagPreReg = Tag::createInstance('@var mixed');
$this->assertInstanceOf(
$currentHandler,
$tagPreReg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPreReg
);
$this->assertFalse(Tag::registerTagHandler('var', 'Non existent'));
$tagPostReg = Tag::createInstance('@var mixed');
$this->assertInstanceOf(
$currentHandler,
$tagPostReg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPostReg
);
}
/**
* @covers \phpDocumentor\Reflection\DocBlock\Tag::registerTagHandler
*
* @return void
*/
public function testIncompatibleTagHandlerRegistration()
{
$currentHandler = __NAMESPACE__ . '\Tag\VarTag';
$tagPreReg = Tag::createInstance('@var mixed');
$this->assertInstanceOf(
$currentHandler,
$tagPreReg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPreReg
);
$this->assertFalse(
Tag::registerTagHandler('var', __NAMESPACE__ . '\TagTest')
);
$tagPostReg = Tag::createInstance('@var mixed');
$this->assertInstanceOf(
$currentHandler,
$tagPostReg
);
$this->assertInstanceOf(
__NAMESPACE__ . '\Tag',
$tagPostReg
);
}
/**
* Test that the \phpDocumentor\Reflection\DocBlock\Tag\VarTag can
* understand the @var doc block.
*
* @param string $type
* @param string $content
* @param string $exDescription
*
* @covers \phpDocumentor\Reflection\DocBlock\Tag
* @dataProvider provideDataForConstuctor
*
* @return void
*/
public function testConstructorParesInputsIntoCorrectFields(
$type,
$content,
$exDescription
) {
$tag = new Tag($type, $content);
$this->assertEquals($type, $tag->getName());
$this->assertEquals($content, $tag->getContent());
$this->assertEquals($exDescription, $tag->getDescription());
}
/**
* Data provider for testConstructorParesInputsIntoCorrectFields
*
* @return array
*/
public function provideDataForConstuctor()
{
// $type, $content, $exDescription
return array(
array(
'unknown',
'some content',
'some content',
),
array(
'unknown',
'',
'',
)
);
}
}

View File

@ -0,0 +1,195 @@
<?php
/**
* phpDocumentor Collection Test
*
* PHP version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\DocBlock\Type;
use phpDocumentor\Reflection\DocBlock\Context;
/**
* Test class for \phpDocumentor\Reflection\DocBlock\Type\Collection
*
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class CollectionTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::__construct
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::getContext
*
* @return void
*/
public function testConstruct()
{
$collection = new Collection();
$this->assertCount(0, $collection);
$this->assertEquals('', $collection->getContext()->getNamespace());
$this->assertCount(0, $collection->getContext()->getNamespaceAliases());
}
/**
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::__construct
*
* @return void
*/
public function testConstructWithTypes()
{
$collection = new Collection(array('integer', 'string'));
$this->assertCount(2, $collection);
}
/**
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::__construct
*
* @return void
*/
public function testConstructWithNamespace()
{
$collection = new Collection(array(), new Context('\My\Space'));
$this->assertEquals('My\Space', $collection->getContext()->getNamespace());
$collection = new Collection(array(), new Context('My\Space'));
$this->assertEquals('My\Space', $collection->getContext()->getNamespace());
$collection = new Collection(array(), null);
$this->assertEquals('', $collection->getContext()->getNamespace());
}
/**
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::__construct
*
* @return void
*/
public function testConstructWithNamespaceAliases()
{
$fixture = array('a' => 'b');
$collection = new Collection(array(), new Context(null, $fixture));
$this->assertEquals(
array('a' => '\b'),
$collection->getContext()->getNamespaceAliases()
);
}
/**
* @param string $fixture
* @param array $expected
*
* @dataProvider provideTypesToExpand
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::add
*
* @return void
*/
public function testAdd($fixture, $expected)
{
$collection = new Collection(
array(),
new Context('\My\Space', array('Alias' => '\My\Space\Aliasing'))
);
$collection->add($fixture);
$this->assertSame($expected, $collection->getArrayCopy());
}
/**
* @param string $fixture
* @param array $expected
*
* @dataProvider provideTypesToExpandWithoutNamespace
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::add
*
* @return void
*/
public function testAddWithoutNamespace($fixture, $expected)
{
$collection = new Collection(
array(),
new Context(null, array('Alias' => '\My\Space\Aliasing'))
);
$collection->add($fixture);
$this->assertSame($expected, $collection->getArrayCopy());
}
/**
* @covers phpDocumentor\Reflection\DocBlock\Type\Collection::add
* @expectedException InvalidArgumentException
*
* @return void
*/
public function testAddWithInvalidArgument()
{
$collection = new Collection();
$collection->add(array());
}
/**
* Returns the types and their expected values to test the retrieval of
* types.
*
* @param string $method Name of the method consuming this data provider.
* @param string $namespace Name of the namespace to user as basis.
*
* @return string[]
*/
public function provideTypesToExpand($method, $namespace = '\My\Space\\')
{
return array(
array('', array()),
array(' ', array()),
array('int', array('int')),
array('int ', array('int')),
array('string', array('string')),
array('DocBlock', array($namespace.'DocBlock')),
array('DocBlock[]', array($namespace.'DocBlock[]')),
array(' DocBlock ', array($namespace.'DocBlock')),
array('\My\Space\DocBlock', array('\My\Space\DocBlock')),
array('Alias\DocBlock', array('\My\Space\Aliasing\DocBlock')),
array(
'DocBlock|Tag',
array($namespace .'DocBlock', $namespace .'Tag')
),
array(
'DocBlock|null',
array($namespace.'DocBlock', 'null')
),
array(
'\My\Space\DocBlock|Tag',
array('\My\Space\DocBlock', $namespace.'Tag')
),
array(
'DocBlock[]|null',
array($namespace.'DocBlock[]', 'null')
),
array(
'DocBlock[]|int[]',
array($namespace.'DocBlock[]', 'int[]')
),
);
}
/**
* Returns the types and their expected values to test the retrieval of
* types when no namespace is available.
*
* @param string $method Name of the method consuming this data provider.
*
* @return string[]
*/
public function provideTypesToExpandWithoutNamespace($method)
{
return $this->provideTypesToExpand($method, '\\');
}
}

View File

@ -0,0 +1,337 @@
<?php
/**
* phpDocumentor DocBlock Test
*
* PHP Version 5.3
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use phpDocumentor\Reflection\DocBlock\Context;
use phpDocumentor\Reflection\DocBlock\Location;
use phpDocumentor\Reflection\DocBlock\Tag\ReturnTag;
/**
* Test class for phpDocumentor\Reflection\DocBlock
*
* @author Mike van Riel <mike.vanriel@naenius.com>
* @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
class DocBlockTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers \phpDocumentor\Reflection\DocBlock
*
* @return void
*/
public function testConstruct()
{
$fixture = <<<DOCBLOCK
/**
* This is a short description
*
* This is a long description
*
* @see \MyClass
* @return void
*/
DOCBLOCK;
$object = new DocBlock(
$fixture,
new Context('\MyNamespace', array('PHPDoc' => '\phpDocumentor')),
new Location(2)
);
$this->assertEquals(
'This is a short description',
$object->getShortDescription()
);
$this->assertEquals(
'This is a long description',
$object->getLongDescription()->getContents()
);
$this->assertCount(2, $object->getTags());
$this->assertTrue($object->hasTag('see'));
$this->assertTrue($object->hasTag('return'));
$this->assertFalse($object->hasTag('category'));
$this->assertSame('MyNamespace', $object->getContext()->getNamespace());
$this->assertSame(
array('PHPDoc' => '\phpDocumentor'),
$object->getContext()->getNamespaceAliases()
);
$this->assertSame(2, $object->getLocation()->getLineNumber());
}
/**
* @covers \phpDocumentor\Reflection\DocBlock::splitDocBlock
*
* @return void
*/
public function testConstructWithTagsOnly()
{
$fixture = <<<DOCBLOCK
/**
* @see \MyClass
* @return void
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertEquals('', $object->getShortDescription());
$this->assertEquals('', $object->getLongDescription()->getContents());
$this->assertCount(2, $object->getTags());
$this->assertTrue($object->hasTag('see'));
$this->assertTrue($object->hasTag('return'));
$this->assertFalse($object->hasTag('category'));
}
/**
* @covers \phpDocumentor\Reflection\DocBlock::isTemplateStart
*/
public function testIfStartOfTemplateIsDiscovered()
{
$fixture = <<<DOCBLOCK
/**#@+
* @see \MyClass
* @return void
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertEquals('', $object->getShortDescription());
$this->assertEquals('', $object->getLongDescription()->getContents());
$this->assertCount(2, $object->getTags());
$this->assertTrue($object->hasTag('see'));
$this->assertTrue($object->hasTag('return'));
$this->assertFalse($object->hasTag('category'));
$this->assertTrue($object->isTemplateStart());
}
/**
* @covers \phpDocumentor\Reflection\DocBlock::isTemplateEnd
*/
public function testIfEndOfTemplateIsDiscovered()
{
$fixture = <<<DOCBLOCK
/**#@-*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertEquals('', $object->getShortDescription());
$this->assertEquals('', $object->getLongDescription()->getContents());
$this->assertTrue($object->isTemplateEnd());
}
/**
* @covers \phpDocumentor\Reflection\DocBlock::cleanInput
*
* @return void
*/
public function testConstructOneLiner()
{
$fixture = '/** Short description and nothing more. */';
$object = new DocBlock($fixture);
$this->assertEquals(
'Short description and nothing more.',
$object->getShortDescription()
);
$this->assertEquals('', $object->getLongDescription()->getContents());
$this->assertCount(0, $object->getTags());
}
/**
* @covers \phpDocumentor\Reflection\DocBlock::__construct
*
* @return void
*/
public function testConstructFromReflector()
{
$object = new DocBlock(new \ReflectionClass($this));
$this->assertEquals(
'Test class for phpDocumentor\Reflection\DocBlock',
$object->getShortDescription()
);
$this->assertEquals('', $object->getLongDescription()->getContents());
$this->assertCount(4, $object->getTags());
$this->assertTrue($object->hasTag('author'));
$this->assertTrue($object->hasTag('copyright'));
$this->assertTrue($object->hasTag('license'));
$this->assertTrue($object->hasTag('link'));
$this->assertFalse($object->hasTag('category'));
}
/**
* @expectedException \InvalidArgumentException
*
* @return void
*/
public function testExceptionOnInvalidObject()
{
new DocBlock($this);
}
public function testDotSeperation()
{
$fixture = <<<DOCBLOCK
/**
* This is a short description.
* This is a long description.
* This is a continuation of the long description.
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertEquals(
'This is a short description.',
$object->getShortDescription()
);
$this->assertEquals(
"This is a long description.\nThis is a continuation of the long "
."description.",
$object->getLongDescription()->getContents()
);
}
/**
* @covers \phpDocumentor\Reflection\DocBlock::parseTags
* @expectedException \LogicException
*
* @return void
*/
public function testInvalidTagBlock()
{
if (0 == ini_get('allow_url_include')) {
$this->markTestSkipped('"data" URIs for includes are required.');
}
include 'data:text/plain;base64,'. base64_encode(
<<<DOCBLOCK_EXTENSION
<?php
class MyReflectionDocBlock extends \phpDocumentor\Reflection\DocBlock {
protected function splitDocBlock(\$comment) {
return array('', '', 'Invalid tag block');
}
}
DOCBLOCK_EXTENSION
);
new \MyReflectionDocBlock('');
}
public function testTagCaseSensitivity()
{
$fixture = <<<DOCBLOCK
/**
* This is a short description.
*
* This is a long description.
*
* @method null something()
* @Method({"GET", "POST"})
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertEquals(
'This is a short description.',
$object->getShortDescription()
);
$this->assertEquals(
'This is a long description.',
$object->getLongDescription()->getContents()
);
$tags = $object->getTags();
$this->assertCount(2, $tags);
$this->assertTrue($object->hasTag('method'));
$this->assertTrue($object->hasTag('Method'));
$this->assertInstanceOf(
__NAMESPACE__ . '\DocBlock\Tag\MethodTag',
$tags[0]
);
$this->assertInstanceOf(
__NAMESPACE__ . '\DocBlock\Tag',
$tags[1]
);
$this->assertNotInstanceOf(
__NAMESPACE__ . '\DocBlock\Tag\MethodTag',
$tags[1]
);
}
/**
* @depends testConstructFromReflector
* @covers \phpDocumentor\Reflection\DocBlock::getTagsByName
*
* @return void
*/
public function testGetTagsByNameZeroAndOneMatch()
{
$object = new DocBlock(new \ReflectionClass($this));
$this->assertEmpty($object->getTagsByName('category'));
$this->assertCount(1, $object->getTagsByName('author'));
}
/**
* @depends testConstructWithTagsOnly
* @covers \phpDocumentor\Reflection\DocBlock::parseTags
*
* @return void
*/
public function testParseMultilineTag()
{
$fixture = <<<DOCBLOCK
/**
* @return void Content on
* multiple lines.
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertCount(1, $object->getTags());
}
/**
* @depends testConstructWithTagsOnly
* @covers \phpDocumentor\Reflection\DocBlock::parseTags
*
* @return void
*/
public function testParseMultilineTagWithLineBreaks()
{
$fixture = <<<DOCBLOCK
/**
* @return void Content on
* multiple lines.
*
* One more, after the break.
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertCount(1, $tags = $object->getTags());
/** @var ReturnTag $tag */
$tag = reset($tags);
$this->assertEquals("Content on\n multiple lines.\n\n One more, after the break.", $tag->getDescription());
}
/**
* @depends testConstructWithTagsOnly
* @covers \phpDocumentor\Reflection\DocBlock::getTagsByName
*
* @return void
*/
public function testGetTagsByNameMultipleMatch()
{
$fixture = <<<DOCBLOCK
/**
* @param string
* @param int
* @return void
*/
DOCBLOCK;
$object = new DocBlock($fixture);
$this->assertEmpty($object->getTagsByName('category'));
$this->assertCount(1, $object->getTagsByName('return'));
$this->assertCount(2, $object->getTagsByName('param'));
}
}

View File

@ -0,0 +1,5 @@
*.tgz
*.phar
bin
vendor
composer.lock

View File

@ -0,0 +1,9 @@
language: php
php: [5.3, 5.4, 5.5, hhvm, hhvm-nightly]
sudo: false
before_script: travis_retry composer install --no-interaction --prefer-source
script: vendor/bin/phpspec run -fpretty -v

110
core/vendor/phpspec/prophecy/CHANGES.md vendored Normal file
View File

@ -0,0 +1,110 @@
1.4.0 / 2015-03-27
==================
* Fixed errors in return type phpdocs (thanks @sobit)
* Fixed stringifying of hash containing one value (thanks @avant1)
* Improved clarity of method call expectation exception (thanks @dantleech)
* Add ability to specify which argument is returned in willReturnArgument (thanks @coderbyheart)
* Add more information to MethodNotFound exceptions (thanks @ciaranmcnulty)
* Support for mocking classes with methods that return references (thanks @edsonmedina)
* Improved object comparison (thanks @whatthejeff)
* Adopted '^' in composer dependencies (thanks @GrahamCampbell)
* Fixed non-typehinted arguments being treated as optional (thanks @whatthejeff)
* Magic methods are now filtered for keywords (thanks @seagoj)
* More readable errors for failure when expecting single calls (thanks @dantleech)
1.3.1 / 2014-11-17
==================
* Fix the edge case when failed predictions weren't recorded for `getCheckedPredictions()`
1.3.0 / 2014-11-14
==================
* Add a way to get checked predictions with `MethodProphecy::getCheckedPredictions()`
* Fix HHVM compatibility
* Remove dead code (thanks @stof)
* Add support for DirectoryIterators (thanks @shanethehat)
1.2.0 / 2014-07-18
==================
* Added support for doubling magic methods documented in the class phpdoc (thanks @armetiz)
* Fixed a segfault appearing in some cases (thanks @dmoreaulf)
* Fixed the doubling of methods with typehints on non-existent classes (thanks @gquemener)
* Added support for internal classes using keywords as method names (thanks @milan)
* Added IdenticalValueToken and Argument::is (thanks @florianv)
* Removed the usage of scalar typehints in HHVM as HHVM 3 does not support them anymore in PHP code (thanks @whatthejeff)
1.1.2 / 2014-01-24
==================
* Spy automatically promotes spied method call to an expected one
1.1.1 / 2014-01-15
==================
* Added support for HHVM
1.1.0 / 2014-01-01
==================
* Changed the generated class names to use a static counter instead of a random number
* Added a clss patch for ReflectionClass::newInstance to make its argument optional consistently (thanks @docteurklein)
* Fixed mirroring of classes with typehints on non-existent classes (thanks @docteurklein)
* Fixed the support of array callables in CallbackPromise and CallbackPrediction (thanks @ciaranmcnulty)
* Added support for properties in ObjectStateToken (thanks @adrienbrault)
* Added support for mocking classes with a final constructor (thanks @ciaranmcnulty)
* Added ArrayEveryEntryToken and Argument::withEveryEntry() (thanks @adrienbrault)
* Added an exception when trying to prophesize on a final method instead of ignoring silently (thanks @docteurklein)
* Added StringContainToken and Argument::containingString() (thanks @peterjmit)
* Added ``shouldNotHaveBeenCalled`` on the MethodProphecy (thanks @ciaranmcnulty)
* Fixed the comparison of objects in ExactValuetoken (thanks @sstok)
* Deprecated ``shouldNotBeenCalled`` in favor of ``shouldNotHaveBeenCalled``
1.0.4 / 2013-08-10
==================
* Better randomness for generated class names (thanks @sstok)
* Add support for interfaces into TypeToken and Argument::type() (thanks @sstok)
* Add support for old-style (method name === class name) constructors (thanks @l310 for report)
1.0.3 / 2013-07-04
==================
* Support callable typehints (thanks @stof)
* Do not attempt to autoload arrays when generating code (thanks @MarcoDeBortoli)
* New ArrayEntryToken (thanks @kagux)
1.0.2 / 2013-05-19
==================
* Logical `AND` token added (thanks @kagux)
* Logical `NOT` token added (thanks @kagux)
* Add support for setting custom constructor arguments
* Properly stringify hashes
* Record calls that throw exceptions
* Migrate spec suite to PhpSpec 2.0
1.0.1 / 2013-04-30
==================
* Fix broken UnexpectedCallException message
* Trim AggregateException message
1.0.0 / 2013-04-29
==================
* Improve exception messages
1.0.0-BETA2 / 2013-04-03
========================
* Add more debug information to CallTimes and Call prediction exception messages
* Fix MethodNotFoundException wrong namespace (thanks @gunnarlium)
* Fix some typos in the exception messages (thanks @pborreli)
1.0.0-BETA1 / 2013-03-25
========================
* Initial release

View File

@ -0,0 +1,21 @@
Contributing
------------
Prophecy is an open source, community-driven project. If you'd like to contribute,
feel free to do this, but remember to follow this few simple rules:
- Make your feature addition or bug fix,
- Add either specs or examples for any changes you're making (bugfixes or additions)
(please look into `spec/` folder for some examples). This is important so we don't break
it in a future version unintentionally,
- Commit your code, but do not mess with `CHANGES.md`,
Running tests
-------------
Make sure that you don't break anything with your changes by running:
```bash
$> composer install --dev --prefer-dist
$> vendor/bin/phpspec
```

23
core/vendor/phpspec/prophecy/LICENSE vendored Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2013 Konstantin Kudryashov <ever.zet@gmail.com>
Marcello Duarte <marcello.duarte@gmail.com>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

389
core/vendor/phpspec/prophecy/README.md vendored Normal file
View File

@ -0,0 +1,389 @@
# Prophecy
[![Build Status](https://travis-ci.org/phpspec/prophecy.svg?branch=master)](https://travis-ci.org/phpspec/prophecy)
Prophecy is a highly opinionated yet very powerful and flexible PHP object mocking
framework. Though initially it was created to fulfil phpspec2 needs, it is flexible
enough to be used inside any testing framework out there with minimal effort.
## A simple example
```php
<?php
class UserTest extends PHPUnit_Framework_TestCase
{
private $prophet;
public function testPasswordHashing()
{
$hasher = $this->prophet->prophesize('App\Security\Hasher');
$user = new App\Entity\User($hasher->reveal());
$hasher->generateHash($user, 'qwerty')->willReturn('hashed_pass');
$user->setPassword('qwerty');
$this->assertEquals('hashed_pass', $user->getPassword());
}
protected function setup()
{
$this->prophet = new \Prophecy\Prophet;
}
protected function tearDown()
{
$this->prophet->checkPredictions();
}
}
```
## Installation
### Prerequisites
Prophecy requires PHP 5.3.3 or greater.
### Setup through composer
First, add Prophecy to the list of dependencies inside your `composer.json`:
```json
{
"require-dev": {
"phpspec/prophecy": "~1.0"
}
}
```
Then simply install it with composer:
```bash
$> composer install --prefer-dist
```
You can read more about Composer on its [official webpage](http://getcomposer.org).
## How to use it
First of all, in Prophecy every word has a logical meaning, even the name of the library
itself (Prophecy). When you start feeling that, you'll become very fluid with this
tool.
For example, Prophecy has been named that way because it concentrates on describing the future
behavior of objects with very limited knowledge about them. But as with any other prophecy,
those object prophecies can't create themselves - there should be a Prophet:
```php
$prophet = new Prophecy\Prophet;
```
The Prophet creates prophecies by *prophesizing* them:
```php
$prophecy = $prophet->prophesize();
```
The result of the `prophesize()` method call is a new object of class `ObjectProphecy`. Yes,
that's your specific object prophecy, which describes how your object would behave
in the near future. But first, you need to specify which object you're talking about,
right?
```php
$prophecy->willExtend('stdClass');
$prophecy->willImplement('SessionHandlerInterface');
```
There are 2 interesting calls - `willExtend` and `willImplement`. The first one tells
object prophecy that our object should extend specific class, the second one says that
it should implement some interface. Obviously, objects in PHP can implement multiple
interfaces, but extend only one parent class.
### Dummies
Ok, now we have our object prophecy. What can we do with it? First of all, we can get
our object *dummy* by revealing its prophecy:
```php
$dummy = $prophecy->reveal();
```
The `$dummy` variable now holds a special dummy object. Dummy objects are objects that extend
and/or implement preset classes/interfaces by overriding all their public methods. The key
point about dummies is that they do not hold any logic - they just do nothing. Any method
of the dummy will always return `null` and the dummy will never throw any exceptions.
Dummy is your friend if you don't care about the actual behavior of this double and just need
a token object to satisfy a method typehint.
You need to understand one thing - a dummy is not a prophecy. Your object prophecy is still
assigned to `$prophecy` variable and in order to manipulate with your expectations, you
should work with it. `$dummy` is a dummy - a simple php object that tries to fulfil your
prophecy.
### Stubs
Ok, now we know how to create basic prophecies and reveal dummies from them. That's
awesome if we don't care about our _doubles_ (objects that reflect originals)
interactions. If we do, we need to use *stubs* or *mocks*.
A stub is an object double, which doesn't have any expectations about the object behavior,
but when put in specific environment, behaves in specific way. Ok, I know, it's cryptic,
but bear with me for a minute. Simply put, a stub is a dummy, which depending on the called
method signature does different things (has logic). To create stubs in Prophecy:
```php
$prophecy->read('123')->willReturn('value');
```
Oh wow. We've just made an arbitrary call on the object prophecy? Yes, we did. And this
call returned us a new object instance of class `MethodProphecy`. Yep, that's a specific
method with arguments prophecy. Method prophecies give you the ability to create method
promises or predictions. We'll talk about method predictions later in the _Mocks_ section.
#### Promises
Promises are logical blocks, that represent your fictional methods in prophecy terms
and they are handled by the `MethodProphecy::will(PromiseInterface $promise)` method.
As a matter of fact, the call that we made earlier (`willReturn('value')`) is a simple
shortcut to:
```php
$prophecy->read('123')->will(new Prophecy\Promise\ReturnPromise(array('value')));
```
This promise will cause any call to our double's `read()` method with exactly one
argument - `'123'` to always return `'value'`. But that's only for this
promise, there's plenty others you can use:
- `ReturnPromise` or `->willReturn(1)` - returns a value from a method call
- `ReturnArgumentPromise` or `->willReturnArgument($index)` - returns the nth method argument from call
- `ThrowPromise` or `->willThrow` - causes the method to throw specific exception
- `CallbackPromise` or `->will($callback)` - gives you a quick way to define your own custom logic
Keep in mind, that you can always add even more promises by implementing
`Prophecy\Promise\PromiseInterface`.
#### Method prophecies idempotency
Prophecy enforces same method prophecies and, as a consequence, same promises and
predictions for the same method calls with the same arguments. This means:
```php
$methodProphecy1 = $prophecy->read('123');
$methodProphecy2 = $prophecy->read('123');
$methodProphecy3 = $prophecy->read('321');
$methodProphecy1 === $methodProphecy2;
$methodProphecy1 !== $methodProphecy3;
```
That's interesting, right? Now you might ask me how would you define more complex
behaviors where some method call changes behavior of others. In PHPUnit or Mockery
you do that by predicting how many times your method will be called. In Prophecy,
you'll use promises for that:
```php
$user->getName()->willReturn(null);
// For PHP 5.4
$user->setName('everzet')->will(function () {
$this->getName()->willReturn('everzet');
});
// For PHP 5.3
$user->setName('everzet')->will(function ($args, $user) {
$user->getName()->willReturn('everzet');
});
// Or
$user->setName('everzet')->will(function ($args) use ($user) {
$user->getName()->willReturn('everzet');
});
```
And now it doesn't matter how many times or in which order your methods are called.
What matters is their behaviors and how well you faked it.
#### Arguments wildcarding
The previous example is awesome (at least I hope it is for you), but that's not
optimal enough. We hardcoded `'everzet'` in our expectation. Isn't there a better
way? In fact there is, but it involves understanding what this `'everzet'`
actually is.
You see, even if method arguments used during method prophecy creation look
like simple method arguments, in reality they are not. They are argument token
wildcards. As a matter of fact, `->setName('everzet')` looks like a simple call just
because Prophecy automatically transforms it under the hood into:
```php
$user->setName(new Prophecy\Argument\Token\ExactValueToken('everzet'));
```
Those argument tokens are simple PHP classes, that implement
`Prophecy\Argument\Token\TokenInterface` and tell Prophecy how to compare real arguments
with your expectations. And yes, those classnames are damn big. That's why there's a
shortcut class `Prophecy\Argument`, which you can use to create tokens like that:
```php
use Prophecy\Argument;
$user->setName(Argument::exact('everzet'));
```
`ExactValueToken` is not very useful in our case as it forced us to hardcode the username.
That's why Prophecy comes bundled with a bunch of other tokens:
- `IdenticalValueToken` or `Argument::is($value)` - checks that the argument is identical to a specific value
- `ExactValueToken` or `Argument::exact($value)` - checks that the argument matches a specific value
- `TypeToken` or `Argument::type($typeOrClass)` - checks that the argument matches a specific type or
classname
- `ObjectStateToken` or `Argument::which($method, $value)` - checks that the argument method returns
a specific value
- `CallbackToken` or `Argument::that(callback)` - checks that the argument matches a custom callback
- `AnyValueToken` or `Argument::any()` - matches any argument
- `AnyValuesToken` or `Argument::cetera()` - matches any arguments to the rest of the signature
And you can add even more by implementing `TokenInterface` with your own custom classes.
So, let's refactor our initial `{set,get}Name()` logic with argument tokens:
```php
use Prophecy\Argument;
$user->getName()->willReturn(null);
// For PHP 5.4
$user->setName(Argument::type('string'))->will(function ($args) {
$this->getName()->willReturn($args[0]);
});
// For PHP 5.3
$user->setName(Argument::type('string'))->will(function ($args, $user) {
$user->getName()->willReturn($args[0]);
});
// Or
$user->setName(Argument::type('string'))->will(function ($args) use ($user) {
$user->getName()->willReturn($args[0]);
});
```
That's it. Now our `{set,get}Name()` prophecy will work with any string argument provided to it.
We've just described how our stub object should behave, even though the original object could have
no behavior whatsoever.
One last bit about arguments now. You might ask, what happens in case of:
```php
use Prophecy\Argument;
$user->getName()->willReturn(null);
// For PHP 5.4
$user->setName(Argument::type('string'))->will(function ($args) {
$this->getName()->willReturn($args[0]);
});
// For PHP 5.3
$user->setName(Argument::type('string'))->will(function ($args, $user) {
$user->getName()->willReturn($args[0]);
});
// Or
$user->setName(Argument::type('string'))->will(function ($args) use ($user) {
$user->getName()->willReturn($args[0]);
});
$user->setName(Argument::any())->will(function () {
});
```
Nothing. Your stub will continue behaving the way it did before. That's because of how
arguments wildcarding works. Every argument token type has a different score level, which
wildcard then uses to calculate the final arguments match score and use the method prophecy
promise that has the highest score. In this case, `Argument::type()` in case of success
scores `5` and `Argument::any()` scores `3`. So the type token wins, as does the first
`setName()` method prophecy and its promise. The simple rule of thumb - more precise token
always wins.
#### Getting stub objects
Ok, now we know how to define our prophecy method promises, let's get our stub from
it:
```php
$stub = $prophecy->reveal();
```
As you might see, the only difference between how we get dummies and stubs is that with
stubs we describe every object conversation instead of just agreeing with `null` returns
(object being *dummy*). As a matter of fact, after you define your first promise
(method call), Prophecy will force you to define all the communications - it throws
the `UnexpectedCallException` for any call you didn't describe with object prophecy before
calling it on a stub.
### Mocks
Now we know how to define doubles without behavior (dummies) and doubles with behavior, but
no expectations (stubs). What's left is doubles for which we have some expectations. These
are called mocks and in Prophecy they look almost exactly the same as stubs, except that
they define *predictions* instead of *promises* on method prophecies:
```php
$entityManager->flush()->shouldBeCalled();
```
#### Predictions
The `shouldBeCalled()` method here assigns `CallPrediction` to our method prophecy.
Predictions are a delayed behavior check for your prophecies. You see, during the entire lifetime
of your doubles, Prophecy records every single call you're making against it inside your
code. After that, Prophecy can use this collected information to check if it matches defined
predictions. You can assign predictions to method prophecies using the
`MethodProphecy::should(PredictionInterface $prediction)` method. As a matter of fact,
the `shouldBeCalled()` method we used earlier is just a shortcut to:
```php
$entityManager->flush()->should(new Prophecy\Prediction\CallPrediction());
```
It checks if your method of interest (that matches both the method name and the arguments wildcard)
was called 1 or more times. If the prediction failed then it throws an exception. When does this
check happen? Whenever you call `checkPredictions()` on the main Prophet object:
```php
$prophet->checkPredictions();
```
In PHPUnit, you would want to put this call into the `tearDown()` method. If no predictions
are defined, it would do nothing. So it won't harm to call it after every test.
There are plenty more predictions you can play with:
- `CallPrediction` or `shouldBeCalled()` - checks that the method has been called 1 or more times
- `NoCallsPrediction` or `shouldNotBeCalled()` - checks that the method has not been called
- `CallTimesPrediction` or `shouldBeCalledTimes($count)` - checks that the method has been called
`$count` times
- `CallbackPrediction` or `should($callback)` - checks the method against your own custom callback
Of course, you can always create your own custom prediction any time by implementing
`PredictionInterface`.
### Spies
The last bit of awesomeness in Prophecy is out-of-the-box spies support. As I said in the previous
section, Prophecy records every call made during the double's entire lifetime. This means
you don't need to record predictions in order to check them. You can also do it
manually by using the `MethodProphecy::shouldHave(PredictionInterface $prediction)` method:
```php
$em = $prophet->prophesize('Doctrine\ORM\EntityManager');
$controller->createUser($em->reveal());
$em->flush()->shouldHaveBeenCalled();
```
Such manipulation with doubles is called spying. And with Prophecy it just works.

View File

@ -0,0 +1,40 @@
{
"name": "phpspec/prophecy",
"description": "Highly opinionated mocking framework for PHP 5.3+",
"keywords": ["Mock", "Stub", "Dummy", "Double", "Fake", "Spy"],
"homepage": "https://github.com/phpspec/prophecy",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"require": {
"phpdocumentor/reflection-docblock": "~2.0",
"sebastian/comparator": "~1.1",
"doctrine/instantiator": "^1.0.2"
},
"require-dev": {
"phpspec/phpspec": "~2.0"
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
}
}

View File

@ -0,0 +1,143 @@
<?php
namespace spec\Prophecy\Argument;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument\Token\TokenInterface;
class ArgumentsWildcardSpec extends ObjectBehavior
{
/**
* @param \stdClass $object
*/
function it_wraps_non_token_arguments_into_ExactValueToken($object)
{
$this->beConstructedWith(array(42, 'zet', $object));
$class = get_class($object->getWrappedObject());
$hash = spl_object_hash($object->getWrappedObject());
$this->__toString()->shouldReturn("exact(42), exact(\"zet\"), exact($class:$hash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_generates_string_representation_from_all_tokens_imploded($token1, $token2, $token3)
{
$token1->__toString()->willReturn('token_1');
$token2->__toString()->willReturn('token_2');
$token3->__toString()->willReturn('token_3');
$this->beConstructedWith(array($token1, $token2, $token3));
$this->__toString()->shouldReturn('token_1, token_2, token_3');
}
function it_exposes_list_of_tokens(TokenInterface $token)
{
$this->beConstructedWith(array($token));
$this->getTokens()->shouldReturn(array($token));
}
function it_returns_score_of_1_if_there_are_no_tokens_and_arguments()
{
$this->beConstructedWith(array());
$this->scoreArguments(array())->shouldReturn(1);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_should_return_match_score_based_on_all_tokens_score($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(5);
$token2->isLast()->willReturn(false);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj))->shouldReturn(18);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_returns_false_if_there_is_less_arguments_than_tokens($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(5);
$token2->isLast()->willReturn(false);
$token3->scoreArgument(null)->willReturn(false);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2))->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_returns_false_if_there_is_less_tokens_than_arguments($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(5);
$token2->isLast()->willReturn(false);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj, 4))->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_should_return_false_if_one_of_the_tokens_returns_false($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(false);
$token2->isLast()->willReturn(false);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj))->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_should_calculate_score_until_last_token($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(7);
$token2->isLast()->willReturn(true);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj))->shouldReturn(10);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class AnyValueTokenSpec extends ObjectBehavior
{
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function its_string_representation_is_star()
{
$this->__toString()->shouldReturn('*');
}
function it_scores_any_argument_as_3()
{
$this->scoreArgument(42)->shouldReturn(3);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class AnyValuesTokenSpec extends ObjectBehavior
{
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_last()
{
$this->shouldBeLast();
}
function its_string_representation_is_star_with_followup()
{
$this->__toString()->shouldReturn('* [, ...]');
}
function it_scores_any_argument_as_2()
{
$this->scoreArgument(42)->shouldReturn(2);
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class ArrayCountTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(2);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_6_if_argument_array_has_proper_count()
{
$this->scoreArgument(array(1,2))->shouldReturn(6);
}
/**
* @param \Countable $countable
*/
function it_scores_6_if_argument_countable_object_has_proper_count($countable)
{
$countable->count()->willReturn(2);
$this->scoreArgument($countable)->shouldReturn(6);
}
function it_does_not_score_if_argument_is_neither_array_nor_countable_object()
{
$this->scoreArgument('string')->shouldBe(false);
$this->scoreArgument(5)->shouldBe(false);
$this->scoreArgument(new \stdClass)->shouldBe(false);
}
function it_does_not_score_if_argument_array_has_wrong_count()
{
$this->scoreArgument(array(1))->shouldReturn(false);
}
/**
* @param \Countable $countable
*/
function it_does_not_score_if_argument_countable_object_has_wrong_count($countable)
{
$countable->count()->willReturn(3);
$this->scoreArgument($countable)->shouldReturn(false);
}
function it_has_simple_string_representation()
{
$this->__toString()->shouldBe('count(2)');
}
}

View File

@ -0,0 +1,229 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Exception\InvalidArgumentException;
class ArrayEntryTokenSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \Prophecy\Argument\Token\TokenInterface $value
*/
function let($key, $value)
{
$this->beConstructedWith($key, $value);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_holds_key_and_value($key, $value)
{
$this->getKey()->shouldBe($key);
$this->getValue()->shouldBe($value);
}
function its_string_representation_tells_that_its_an_array_containing_the_key_value_pair($key, $value)
{
$key->__toString()->willReturn('key');
$value->__toString()->willReturn('value');
$this->__toString()->shouldBe('[..., key => value, ...]');
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \stdClass $object
*/
function it_wraps_non_token_value_into_ExactValueToken($key, $object)
{
$this->beConstructedWith($key, $object);
$this->getValue()->shouldHaveType('\Prophecy\Argument\Token\ExactValueToken');
}
/**
* @param \stdClass $object
* @param \Prophecy\Argument\Token\TokenInterface $value
*/
function it_wraps_non_token_key_into_ExactValueToken($object, $value)
{
$this->beConstructedWith($object, $value);
$this->getKey()->shouldHaveType('\Prophecy\Argument\Token\ExactValueToken');
}
function it_scores_array_half_of_combined_scores_from_key_and_value_tokens($key, $value)
{
$key->scoreArgument('key')->willReturn(4);
$value->scoreArgument('value')->willReturn(6);
$this->scoreArgument(array('key'=>'value'))->shouldBe(5);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \Iterator $object
*/
function it_scores_traversable_object_half_of_combined_scores_from_key_and_value_tokens($key, $value, $object)
{
$object->current()->will(function () use ($object) {
$object->valid()->willReturn(false);
return 'value';
});
$object->key()->willReturn('key');
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$key->scoreArgument('key')->willReturn(6);
$value->scoreArgument('value')->willReturn(2);
$this->scoreArgument($object)->shouldBe(4);
}
/**
* @param \Prophecy\Argument\Token\AnyValuesToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayAccess $object
*/
function it_throws_exception_during_scoring_of_array_accessible_object_if_key_is_not_ExactValueToken($key, $value, $object)
{
$key->__toString()->willReturn('any_token');
$this->beConstructedWith($key,$value);
$errorMessage = 'You can only use exact value tokens to match key of ArrayAccess object'.PHP_EOL.
'But you used `any_token`.';
$this->shouldThrow(new InvalidArgumentException($errorMessage))->duringScoreArgument($object);
}
/**
* @param \Prophecy\Argument\Token\ExactValueToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayAccess $object
*/
function it_scores_array_accessible_object_half_of_combined_scores_from_key_and_value_tokens($key, $value, $object)
{
$object->offsetExists('key')->willReturn(true);
$object->offsetGet('key')->willReturn('value');
$key->getValue()->willReturn('key');
$key->scoreArgument('key')->willReturn(3);
$value->scoreArgument('value')->willReturn(1);
$this->scoreArgument($object)->shouldBe(2);
}
/**
* @param \Prophecy\Argument\Token\AnyValuesToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayIterator $object
*/
function it_accepts_any_key_token_type_to_score_object_that_is_both_traversable_and_array_accessible($key, $value, $object)
{
$this->beConstructedWith($key, $value);
$object->current()->will(function () use ($object) {
$object->valid()->willReturn(false);
return 'value';
});
$object->key()->willReturn('key');
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$this->shouldNotThrow(new InvalidArgumentException)->duringScoreArgument($object);
}
function it_does_not_score_if_argument_is_neither_array_nor_traversable_nor_array_accessible()
{
$this->scoreArgument('string')->shouldBe(false);
$this->scoreArgument(new \stdClass)->shouldBe(false);
}
function it_does_not_score_empty_array()
{
$this->scoreArgument(array())->shouldBe(false);
}
function it_does_not_score_array_if_key_and_value_tokens_do_not_score_same_entry($key, $value)
{
$argument = array(1 => 'foo', 2 => 'bar');
$key->scoreArgument(1)->willReturn(true);
$key->scoreArgument(2)->willReturn(false);
$value->scoreArgument('foo')->willReturn(false);
$value->scoreArgument('bar')->willReturn(true);
$this->scoreArgument($argument)->shouldBe(false);
}
/**
* @param \Iterator $object
*/
function it_does_not_score_traversable_object_without_entries($object)
{
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(false);
$this->scoreArgument($object)->shouldBe(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \Iterator $object
*/
function it_does_not_score_traversable_object_if_key_and_value_tokens_do_not_score_same_entry($key, $value, $object)
{
$object->current()->willReturn('foo');
$object->current()->will(function () use ($object) {
$object->valid()->willReturn(false);
return 'bar';
});
$object->key()->willReturn(1);
$object->key()->willReturn(2);
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$key->scoreArgument(1)->willReturn(true);
$key->scoreArgument(2)->willReturn(false);
$value->scoreArgument('foo')->willReturn(false);
$value->scoreArgument('bar')->willReturn(true);
$this->scoreArgument($object)->shouldBe(false);
}
/**
* @param \Prophecy\Argument\Token\ExactValueToken $key
* @param \ArrayAccess $object
*/
function it_does_not_score_array_accessible_object_if_it_has_no_offset_with_key_token_value($key, $object)
{
$object->offsetExists('key')->willReturn(false);
$key->getValue()->willReturn('key');
$this->scoreArgument($object)->shouldBe(false);
}
/**
* @param \Prophecy\Argument\Token\ExactValueToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayAccess $object
*/
function it_does_not_score_array_accessible_object_if_key_and_value_tokens_do_not_score_same_entry($key, $value, $object)
{
$object->offsetExists('key')->willReturn(true);
$object->offsetGet('key')->willReturn('value');
$key->getValue()->willReturn('key');
$value->scoreArgument('value')->willReturn(false);
$key->scoreArgument('key')->willReturn(true);
$this->scoreArgument($object)->shouldBe(false);
}
function its_score_is_capped_at_8($key, $value)
{
$key->scoreArgument('key')->willReturn(10);
$value->scoreArgument('value')->willReturn(10);
$this->scoreArgument(array('key'=>'value'))->shouldBe(8);
}
}

View File

@ -0,0 +1,109 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ArrayEveryEntryTokenSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Argument\Token\TokenInterface $value
*/
function let($value)
{
$this->beConstructedWith($value);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_holds_value($value)
{
$this->getValue()->shouldBe($value);
}
function its_string_representation_tells_that_its_an_array_containing_only_value($value)
{
$value->__toString()->willReturn('value');
$this->__toString()->shouldBe('[value, ..., value]');
}
/**
* @param \stdClass $stdClass
*/
function it_wraps_non_token_value_into_ExactValueToken($stdClass)
{
$this->beConstructedWith($stdClass);
$this->getValue()->shouldHaveType('Prophecy\Argument\Token\ExactValueToken');
}
function it_does_not_score_if_argument_is_neither_array_nor_traversable()
{
$this->scoreArgument('string')->shouldBe(false);
$this->scoreArgument(new \stdClass)->shouldBe(false);
}
function it_does_not_score_empty_array()
{
$this->scoreArgument(array())->shouldBe(false);
}
/**
* @param \Iterator $object
*/
function it_does_not_score_traversable_object_without_entries($object)
{
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(false);
$this->scoreArgument($object)->shouldBe(false);
}
function it_scores_avg_of_scores_from_value_tokens($value)
{
$value->scoreArgument('value1')->willReturn(6);
$value->scoreArgument('value2')->willReturn(3);
$this->scoreArgument(array('value1', 'value2'))->shouldBe(4.5);
}
function it_scores_false_if_entry_scores_false($value)
{
$value->scoreArgument('value1')->willReturn(6);
$value->scoreArgument('value2')->willReturn(false);
$this->scoreArgument(array('value1', 'value2'))->shouldBe(false);
}
function it_does_not_score_array_keys($value)
{
$value->scoreArgument('value')->willReturn(6);
$value->scoreArgument('key')->shouldNotBeCalled(0);
$this->scoreArgument(array('key' => 'value'))->shouldBe(6);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \Iterator $object
*/
function it_scores_traversable_object_from_value_token($value, $object)
{
$object->current()->will(function ($args, $object) {
$object->valid()->willReturn(false);
return 'value';
});
$object->key()->willReturn('key');
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$value->scoreArgument('value')->willReturn(2);
$this->scoreArgument($object)->shouldBe(2);
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class CallbackTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('get_class');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_7_if_argument_matches_callback()
{
$this->beConstructedWith(function ($argument) { return 2 === $argument; });
$this->scoreArgument(2)->shouldReturn(7);
}
function it_does_not_scores_if_argument_does_not_match_callback()
{
$this->beConstructedWith(function ($argument) { return 2 === $argument; });
$this->scoreArgument(5)->shouldReturn(false);
}
function its_string_representation_should_tell_that_its_callback()
{
$this->__toString()->shouldReturn('callback()');
}
}

View File

@ -0,0 +1,155 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class ExactValueTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(42);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_holds_value()
{
$this->getValue()->shouldReturn(42);
}
function it_scores_10_if_value_is_equal_to_argument()
{
$this->scoreArgument(42)->shouldReturn(10);
$this->scoreArgument('42')->shouldReturn(10);
}
function it_scores_10_if_value_is_an_object_and_equal_to_argument()
{
$value = new \DateTime();
$value2 = clone $value;
$this->beConstructedWith($value);
$this->scoreArgument($value2)->shouldReturn(10);
}
function it_does_not_scores_if_value_is_not_equal_to_argument()
{
$this->scoreArgument(50)->shouldReturn(false);
$this->scoreArgument(new \stdClass())->shouldReturn(false);
}
function it_does_not_scores_if_value_an_object_and_is_not_equal_to_argument()
{
$value = new ExactValueTokenFixtureB('ABC');
$value2 = new ExactValueTokenFixtureB('CBA');
$this->beConstructedWith($value);
$this->scoreArgument($value2)->shouldReturn(false);
}
function it_does_not_scores_if_value_type_and_is_not_equal_to_argument()
{
$this->beConstructedWith(false);
$this->scoreArgument(0)->shouldReturn(false);
}
function it_generates_proper_string_representation_for_integer()
{
$this->beConstructedWith(42);
$this->__toString()->shouldReturn('exact(42)');
}
function it_generates_proper_string_representation_for_string()
{
$this->beConstructedWith('some string');
$this->__toString()->shouldReturn('exact("some string")');
}
function it_generates_single_line_representation_for_multiline_string()
{
$this->beConstructedWith("some\nstring");
$this->__toString()->shouldReturn('exact("some\\nstring")');
}
function it_generates_proper_string_representation_for_double()
{
$this->beConstructedWith(42.3);
$this->__toString()->shouldReturn('exact(42.3)');
}
function it_generates_proper_string_representation_for_boolean_true()
{
$this->beConstructedWith(true);
$this->__toString()->shouldReturn('exact(true)');
}
function it_generates_proper_string_representation_for_boolean_false()
{
$this->beConstructedWith(false);
$this->__toString()->shouldReturn('exact(false)');
}
function it_generates_proper_string_representation_for_null()
{
$this->beConstructedWith(null);
$this->__toString()->shouldReturn('exact(null)');
}
function it_generates_proper_string_representation_for_empty_array()
{
$this->beConstructedWith(array());
$this->__toString()->shouldReturn('exact([])');
}
function it_generates_proper_string_representation_for_array()
{
$this->beConstructedWith(array('zet', 42));
$this->__toString()->shouldReturn('exact(["zet", 42])');
}
function it_generates_proper_string_representation_for_resource()
{
$resource = fopen(__FILE__, 'r');
$this->beConstructedWith($resource);
$this->__toString()->shouldReturn('exact(stream:'.$resource.')');
}
/**
* @param \stdClass $object
*/
function it_generates_proper_string_representation_for_object($object)
{
$objHash = sprintf('%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
);
$this->beConstructedWith($object);
$this->__toString()->shouldReturn("exact($objHash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");
}
}
class ExactValueTokenFixtureA
{
public $errors;
}
class ExactValueTokenFixtureB extends ExactValueTokenFixtureA
{
public $errors;
public $value = null;
public function __construct($value)
{
$this->value = $value;
}
}

View File

@ -0,0 +1,152 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class IdenticalValueTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(42);
}
function it_is_initializable()
{
$this->shouldHaveType('Prophecy\Argument\Token\IdenticalValueToken');
}
function it_scores_11_if_string_value_is_identical_to_argument()
{
$this->beConstructedWith('foo');
$this->scoreArgument('foo')->shouldReturn(11);
}
function it_scores_11_if_boolean_value_is_identical_to_argument()
{
$this->beConstructedWith(false);
$this->scoreArgument(false)->shouldReturn(11);
}
function it_scores_11_if_integer_value_is_identical_to_argument()
{
$this->beConstructedWith(31);
$this->scoreArgument(31)->shouldReturn(11);
}
function it_scores_11_if_float_value_is_identical_to_argument()
{
$this->beConstructedWith(31.12);
$this->scoreArgument(31.12)->shouldReturn(11);
}
function it_scores_11_if_array_value_is_identical_to_argument()
{
$this->beConstructedWith(array('foo' => 'bar'));
$this->scoreArgument(array('foo' => 'bar'))->shouldReturn(11);
}
function it_scores_11_if_object_value_is_identical_to_argument()
{
$object = new \stdClass();
$this->beConstructedWith($object);
$this->scoreArgument($object)->shouldReturn(11);
}
function it_scores_false_if_value_is_not_identical_to_argument()
{
$this->beConstructedWith(new \stdClass());
$this->scoreArgument('foo')->shouldReturn(false);
}
function it_scores_false_if_object_value_is_not_the_same_instance_than_argument()
{
$this->beConstructedWith(new \stdClass());
$this->scoreArgument(new \stdClass())->shouldReturn(false);
}
function it_scores_false_if_integer_value_is_not_identical_to_boolean_argument()
{
$this->beConstructedWith(1);
$this->scoreArgument(true)->shouldReturn(false);
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_generates_proper_string_representation_for_integer()
{
$this->beConstructedWith(42);
$this->__toString()->shouldReturn('identical(42)');
}
function it_generates_proper_string_representation_for_string()
{
$this->beConstructedWith('some string');
$this->__toString()->shouldReturn('identical("some string")');
}
function it_generates_single_line_representation_for_multiline_string()
{
$this->beConstructedWith("some\nstring");
$this->__toString()->shouldReturn('identical("some\\nstring")');
}
function it_generates_proper_string_representation_for_double()
{
$this->beConstructedWith(42.3);
$this->__toString()->shouldReturn('identical(42.3)');
}
function it_generates_proper_string_representation_for_boolean_true()
{
$this->beConstructedWith(true);
$this->__toString()->shouldReturn('identical(true)');
}
function it_generates_proper_string_representation_for_boolean_false()
{
$this->beConstructedWith(false);
$this->__toString()->shouldReturn('identical(false)');
}
function it_generates_proper_string_representation_for_null()
{
$this->beConstructedWith(null);
$this->__toString()->shouldReturn('identical(null)');
}
function it_generates_proper_string_representation_for_empty_array()
{
$this->beConstructedWith(array());
$this->__toString()->shouldReturn('identical([])');
}
function it_generates_proper_string_representation_for_array()
{
$this->beConstructedWith(array('zet', 42));
$this->__toString()->shouldReturn('identical(["zet", 42])');
}
function it_generates_proper_string_representation_for_resource()
{
$resource = fopen(__FILE__, 'r');
$this->beConstructedWith($resource);
$this->__toString()->shouldReturn('identical(stream:'.$resource.')');
}
function it_generates_proper_string_representation_for_object($object)
{
$objHash = sprintf('%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
);
$this->beConstructedWith($object);
$this->__toString()->shouldReturn("identical($objHash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class LogicalAndTokenSpec extends ObjectBehavior
{
function it_implements_TokenInterface()
{
$this->beConstructedWith(array());
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->beConstructedWith(array());
$this->shouldNotBeLast();
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_generates_string_representation_from_all_tokens_imploded($token1, $token2, $token3)
{
$token1->__toString()->willReturn('token_1');
$token2->__toString()->willReturn('token_2');
$token3->__toString()->willReturn('token_3');
$this->beConstructedWith(array($token1, $token2, $token3));
$this->__toString()->shouldReturn('bool(token_1 AND token_2 AND token_3)');
}
function it_wraps_non_token_arguments_into_ExactValueToken()
{
$this->beConstructedWith(array(15, '1985'));
$this->__toString()->shouldReturn("bool(exact(15) AND exact(\"1985\"))");
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
*/
function it_scores_the_maximum_score_from_all_scores_returned_by_tokens($token1, $token2)
{
$token1->scoreArgument(1)->willReturn(10);
$token2->scoreArgument(1)->willReturn(5);
$this->beConstructedWith(array($token1, $token2));
$this->scoreArgument(1)->shouldReturn(10);
}
function it_does_not_score_if_there_are_no_arguments_or_tokens()
{
$this->beConstructedWith(array());
$this->scoreArgument('any')->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
*/
function it_does_not_score_if_either_of_tokens_does_not_score($token1, $token2)
{
$token1->scoreArgument(1)->willReturn(10);
$token1->scoreArgument(2)->willReturn(false);
$token2->scoreArgument(1)->willReturn(false);
$token2->scoreArgument(2)->willReturn(10);
$this->beConstructedWith(array($token1, $token2));
$this->scoreArgument(1)->shouldReturn(false);
$this->scoreArgument(2)->shouldReturn(false);
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument\Token\TokenInterface;
class LogicalNotTokenSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Argument\Token\TokenInterface $token
*/
function let($token)
{
$this->beConstructedWith($token);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_holds_originating_token($token)
{
$this->getOriginatingToken()->shouldReturn($token);
}
function it_has_simple_string_representation($token)
{
$token->__toString()->willReturn('value');
$this->__toString()->shouldBe('not(value)');
}
function it_wraps_non_token_argument_into_ExactValueToken()
{
$this->beConstructedWith(5);
$token = $this->getOriginatingToken();
$token->shouldhaveType('Prophecy\Argument\Token\ExactValueToken');
$token->getValue()->shouldBe(5);
}
function it_scores_4_if_preset_token_does_not_match_the_argument($token)
{
$token->scoreArgument('argument')->willReturn(false);
$this->scoreArgument('argument')->shouldBe(4);
}
function it_does_not_score_if_preset_token_matches_argument($token)
{
$token->scoreArgument('argument')->willReturn(5);
$this->scoreArgument('argument')->shouldBe(false);
}
function it_is_last_if_preset_token_is_last($token)
{
$token->isLast()->willReturn(true);
$this->shouldBeLast();
}
function it_is_not_last_if_preset_token_is_not_last($token)
{
$token->isLast()->willReturn(false);
$this->shouldNotBeLast();
}
}

View File

@ -0,0 +1,101 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class ObjectStateTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('getName', 'stdClass');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
/**
* @param \ReflectionClass $reflection
*/
function it_scores_8_if_argument_object_has_specific_method_state($reflection)
{
$reflection->getName()->willReturn('stdClass');
$this->scoreArgument($reflection)->shouldReturn(8);
}
/**
* @param \stdClass $class
*/
function it_scores_8_if_argument_object_has_specific_property_state($class)
{
$class->getName = 'stdClass';
$this->scoreArgument($class)->shouldReturn(8);
}
function it_does_not_score_if_argument_method_state_does_not_match()
{
$value = new ObjectStateTokenFixtureB('ABC');
$value2 = new ObjectStateTokenFixtureB('CBA');
$this->beConstructedWith('getSelf', $value);
$this->scoreArgument($value2)->shouldReturn(false);
}
/**
* @param \stdClass $class
*/
function it_does_not_score_if_argument_property_state_does_not_match($class)
{
$class->getName = 'SplFileInfo';
$this->scoreArgument($class)->shouldReturn(false);
}
/**
* @param \spec\Prophecy\Argument\Token\ObjectStateTokenFixtureA $class
*/
function it_does_not_score_if_argument_object_does_not_have_method_or_property($class)
{
$this->scoreArgument($class)->shouldReturn(false);
}
function it_does_not_score_if_argument_is_not_object()
{
$this->scoreArgument(42)->shouldReturn(false);
}
function it_has_simple_string_representation()
{
$this->__toString()->shouldReturn('state(getName(), "stdClass")');
}
}
class ObjectStateTokenFixtureA
{
public $errors;
}
class ObjectStateTokenFixtureB extends ObjectStateTokenFixtureA
{
public $errors;
public $value = null;
public function __construct($value)
{
$this->value = $value;
}
public function getSelf()
{
return $this;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class StringContainsTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('a substring');
}
function it_is_initializable()
{
$this->shouldHaveType('Prophecy\Argument\Token\StringContainsToken');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_holds_value()
{
$this->getValue()->shouldReturn('a substring');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_6_if_the_argument_contains_the_value()
{
$this->scoreArgument('Argument containing a substring')->shouldReturn(6);
}
function it_does_not_score_if_the_argument_does_not_contain_the_value()
{
$this->scoreArgument('Argument will not match')->shouldReturn(false);
}
function its_string_representation_shows_substring()
{
$this->__toString()->shouldReturn('contains("a substring")');
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class TypeTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('integer');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_5_if_argument_matches_simple_type()
{
$this->beConstructedWith('integer');
$this->scoreArgument(42)->shouldReturn(5);
}
function it_does_not_scores_if_argument_does_not_match_simple_type()
{
$this->beConstructedWith('integer');
$this->scoreArgument(42.0)->shouldReturn(false);
}
/**
* @param \ReflectionObject $object
*/
function it_scores_5_if_argument_is_an_instance_of_specified_class($object)
{
$this->beConstructedWith('ReflectionClass');
$this->scoreArgument($object)->shouldReturn(5);
}
function it_has_simple_string_representation()
{
$this->__toString()->shouldReturn('type(integer)');
}
function it_scores_5_if_argument_is_an_instance_of_specified_interface(\Prophecy\Argument\Token\TokenInterface $interface)
{
$this->beConstructedWith('Prophecy\Argument\Token\TokenInterface');
$this->scoreArgument($interface)->shouldReturn(5);
}
}

View File

@ -0,0 +1,101 @@
<?php
namespace spec\Prophecy;
use PhpSpec\ObjectBehavior;
class ArgumentSpec extends ObjectBehavior
{
function it_has_a_shortcut_for_exact_argument_token()
{
$token = $this->exact(42);
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ExactValueToken');
$token->getValue()->shouldReturn(42);
}
function it_has_a_shortcut_for_any_argument_token()
{
$token = $this->any();
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\AnyValueToken');
}
function it_has_a_shortcut_for_multiple_arguments_token()
{
$token = $this->cetera();
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\AnyValuesToken');
}
function it_has_a_shortcut_for_type_token()
{
$token = $this->type('integer');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\TypeToken');
}
function it_has_a_shortcut_for_callback_token()
{
$token = $this->that('get_class');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\CallbackToken');
}
function it_has_a_shortcut_for_object_state_token()
{
$token = $this->which('getName', 'everzet');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ObjectStateToken');
}
function it_has_a_shortcut_for_logical_and_token()
{
$token = $this->allOf('integer', 5);
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\LogicalAndToken');
}
function it_has_a_shortcut_for_array_count_token()
{
$token = $this->size(5);
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayCountToken');
}
function it_has_a_shortcut_for_array_entry_token()
{
$token = $this->withEntry('key', 'value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEntryToken');
}
function it_has_a_shortcut_for_array_every_entry_token()
{
$token = $this->withEveryEntry('value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEveryEntryToken');
}
function it_has_a_shortcut_for_identical_value_token()
{
$token = $this->is('value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\IdenticalValueToken');
}
function it_has_a_shortcut_for_array_entry_token_matching_any_key()
{
$token = $this->containing('value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEntryToken');
$token->getKey()->shouldHaveType('Prophecy\Argument\Token\AnyValueToken');
}
function it_has_a_shortcut_for_array_entry_token_matching_any_value()
{
$token = $this->withKey('key');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEntryToken');
$token->getValue()->shouldHaveType('Prophecy\Argument\Token\AnyValueToken');
}
function it_has_a_shortcut_for_logical_not_token()
{
$token = $this->not('kagux');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\LogicalNotToken');
}
function it_has_a_shortcut_for_string_contains_token()
{
$token = $this->containingString('string');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\StringContainsToken');
}
}

View File

@ -0,0 +1,188 @@
<?php
namespace spec\Prophecy\Call;
use PhpSpec\ObjectBehavior;
use Prophecy\Prophecy\ObjectProphecy;
use Prophecy\Argument\ArgumentsWildcard;
class CallCenterSpec extends ObjectBehavior
{
function let(ObjectProphecy $objectProphecy)
{
}
function it_records_calls_made_through_makeCall_method(ObjectProphecy $objectProphecy, ArgumentsWildcard $wildcard)
{
$wildcard->scoreArguments(array(5, 2, 3))->willReturn(10);
$objectProphecy->getMethodProphecies()->willReturn(array());
$this->makeCall($objectProphecy, 'setValues', array(5, 2, 3));
$calls = $this->findCalls('setValues', $wildcard);
$calls->shouldHaveCount(1);
$calls[0]->shouldBeAnInstanceOf('Prophecy\Call\Call');
$calls[0]->getMethodName()->shouldReturn('setValues');
$calls[0]->getArguments()->shouldReturn(array(5, 2, 3));
$calls[0]->getReturnValue()->shouldReturn(null);
}
function it_returns_null_for_any_call_through_makeCall_if_no_method_prophecies_added(
$objectProphecy
)
{
$objectProphecy->getMethodProphecies()->willReturn(array());
$this->makeCall($objectProphecy, 'setValues', array(5, 2, 3))->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method1
* @param \Prophecy\Prophecy\MethodProphecy $method2
* @param \Prophecy\Prophecy\MethodProphecy $method3
* @param \Prophecy\Argument\ArgumentsWildcard $arguments1
* @param \Prophecy\Argument\ArgumentsWildcard $arguments2
* @param \Prophecy\Argument\ArgumentsWildcard $arguments3
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_executes_promise_of_method_prophecy_that_matches_signature_passed_to_makeCall(
$objectProphecy, $method1, $method2, $method3, $arguments1, $arguments2, $arguments3,
$promise
)
{
$method1->getMethodName()->willReturn('getName');
$method1->getArgumentsWildcard()->willReturn($arguments1);
$arguments1->scoreArguments(array('world', 'everything'))->willReturn(false);
$method2->getMethodName()->willReturn('setTitle');
$method2->getArgumentsWildcard()->willReturn($arguments2);
$arguments2->scoreArguments(array('world', 'everything'))->willReturn(false);
$method3->getMethodName()->willReturn('getName');
$method3->getArgumentsWildcard()->willReturn($arguments3);
$method3->getPromise()->willReturn($promise);
$arguments3->scoreArguments(array('world', 'everything'))->willReturn(200);
$objectProphecy->getMethodProphecies()->willReturn(array(
'method1' => array($method1),
'method2' => array($method2, $method3)
));
$objectProphecy->getMethodProphecies('getName')->willReturn(array($method1, $method3));
$objectProphecy->reveal()->willReturn(new \stdClass());
$promise->execute(array('world', 'everything'), $objectProphecy->getWrappedObject(), $method3)->willReturn(42);
$this->makeCall($objectProphecy, 'getName', array('world', 'everything'))->shouldReturn(42);
$calls = $this->findCalls('getName', $arguments3);
$calls->shouldHaveCount(1);
$calls[0]->getReturnValue()->shouldReturn(42);
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method1
* @param \Prophecy\Prophecy\MethodProphecy $method2
* @param \Prophecy\Prophecy\MethodProphecy $method3
* @param \Prophecy\Argument\ArgumentsWildcard $arguments1
* @param \Prophecy\Argument\ArgumentsWildcard $arguments2
* @param \Prophecy\Argument\ArgumentsWildcard $arguments3
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_executes_promise_of_method_prophecy_that_matches_with_highest_score_to_makeCall(
$objectProphecy, $method1, $method2, $method3, $arguments1, $arguments2, $arguments3,
$promise
)
{
$method1->getMethodName()->willReturn('getName');
$method1->getArgumentsWildcard()->willReturn($arguments1);
$arguments1->scoreArguments(array('world', 'everything'))->willReturn(50);
$method2->getMethodName()->willReturn('getName');
$method2->getArgumentsWildcard()->willReturn($arguments2);
$method2->getPromise()->willReturn($promise);
$arguments2->scoreArguments(array('world', 'everything'))->willReturn(300);
$method3->getMethodName()->willReturn('getName');
$method3->getArgumentsWildcard()->willReturn($arguments3);
$arguments3->scoreArguments(array('world', 'everything'))->willReturn(200);
$objectProphecy->getMethodProphecies()->willReturn(array(
'method1' => array($method1),
'method2' => array($method2, $method3)
));
$objectProphecy->getMethodProphecies('getName')->willReturn(array(
$method1, $method2, $method3
));
$objectProphecy->reveal()->willReturn(new \stdClass());
$promise->execute(array('world', 'everything'), $objectProphecy->getWrappedObject(), $method2)
->willReturn('second');
$this->makeCall($objectProphecy, 'getName', array('world', 'everything'))
->shouldReturn('second');
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_throws_exception_if_call_does_not_match_any_of_defined_method_prophecies(
$objectProphecy, $method, $arguments
)
{
$method->getMethodName()->willReturn('getName');
$method->getArgumentsWildcard()->willReturn($arguments);
$arguments->scoreArguments(array('world', 'everything'))->willReturn(false);
$arguments->__toString()->willReturn('arg1, arg2');
$objectProphecy->getMethodProphecies()->willReturn(array('method1' => array($method)));
$objectProphecy->getMethodProphecies('getName')->willReturn(array($method));
$this->shouldThrow('Prophecy\Exception\Call\UnexpectedCallException')
->duringMakeCall($objectProphecy, 'getName', array('world', 'everything'));
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_returns_null_if_method_prophecy_that_matches_makeCall_arguments_has_no_promise(
$objectProphecy, $method, $arguments
)
{
$method->getMethodName()->willReturn('getName');
$method->getArgumentsWildcard()->willReturn($arguments);
$method->getPromise()->willReturn(null);
$arguments->scoreArguments(array('world', 'everything'))->willReturn(100);
$objectProphecy->getMethodProphecies()->willReturn(array($method));
$objectProphecy->getMethodProphecies('getName')->willReturn(array($method));
$this->makeCall($objectProphecy, 'getName', array('world', 'everything'))
->shouldReturn(null);
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $wildcard
*/
function it_finds_recorded_calls_by_a_method_name_and_arguments_wildcard(
$objectProphecy, $wildcard
)
{
$objectProphecy->getMethodProphecies()->willReturn(array());
$this->makeCall($objectProphecy, 'getName', array('world'));
$this->makeCall($objectProphecy, 'getName', array('everything'));
$this->makeCall($objectProphecy, 'setName', array(42));
$wildcard->scoreArguments(array('world'))->willReturn(false);
$wildcard->scoreArguments(array('everything'))->willReturn(10);
$calls = $this->findCalls('getName', $wildcard);
$calls->shouldHaveCount(1);
$calls[0]->getMethodName()->shouldReturn('getName');
$calls[0]->getArguments()->shouldReturn(array('everything'));
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace spec\Prophecy\Call;
use PhpSpec\ObjectBehavior;
class CallSpec extends ObjectBehavior
{
/**
* @param \Exception $exception
*/
function let($exception)
{
$this->beConstructedWith('setValues', array(5, 2), 42, $exception, 'some_file.php', 23);
}
function it_exposes_method_name_through_getter()
{
$this->getMethodName()->shouldReturn('setValues');
}
function it_exposes_arguments_through_getter()
{
$this->getArguments()->shouldReturn(array(5, 2));
}
function it_exposes_return_value_through_getter()
{
$this->getReturnValue()->shouldReturn(42);
}
function it_exposes_exception_through_getter($exception)
{
$this->getException()->shouldReturn($exception);
}
function it_exposes_file_and_line_through_getter()
{
$this->getFile()->shouldReturn('some_file.php');
$this->getLine()->shouldReturn(23);
}
function it_returns_shortpath_to_callPlace()
{
$this->getCallPlace()->shouldReturn('some_file.php:23');
}
function it_returns_unknown_as_callPlace_if_no_file_or_line_provided()
{
$this->beConstructedWith('setValues', array(), 0, null, null, null);
$this->getCallPlace()->shouldReturn('unknown');
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class DisableConstructorPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_100()
{
$this->getPriority()->shouldReturn(100);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_anything($node)
{
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg2
*/
function it_makes_all_constructor_arguments_optional($class, $method, $arg1, $arg2)
{
$class->hasMethod('__construct')->willReturn(true);
$class->getMethod('__construct')->willReturn($method);
$method->getArguments()->willReturn(array($arg1, $arg2));
$arg1->setDefault(null)->shouldBeCalled();
$arg2->setDefault(null)->shouldBeCalled();
$method->setCode(Argument::type('string'))->shouldBeCalled();
$this->apply($class);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_creates_new_constructor_if_object_has_none($class)
{
$class->hasMethod('__construct')->willReturn(false);
$class->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))
->shouldBeCalled();
$this->apply($class);
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class HhvmExceptionPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_minus_50()
{
$this->getPriority()->shouldReturn(-50);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\MethodNode $getterMethod
*/
function it_uses_parent_code_for_setTraceOptions($node, $method, $getterMethod)
{
$node->hasMethod('setTraceOptions')->willReturn(true);
$node->getMethod('setTraceOptions')->willReturn($method);
$node->hasMethod('getTraceOptions')->willReturn(true);
$node->getMethod('getTraceOptions')->willReturn($getterMethod);
$method->useParentCode()->shouldBeCalled();
$getterMethod->useParentCode()->shouldBeCalled();
$this->apply($node);
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Doubler\Generator\Node\MethodNode;
class KeywordPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_49()
{
$this->getPriority()->shouldReturn(49);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method3
*/
function it_will_remove_echo_and_eval_methods($node, $method1, $method2, $method3)
{
$node->removeMethod('eval')->shouldBeCalled();
$node->removeMethod('echo')->shouldBeCalled();
$method1->getName()->willReturn('echo');
$method2->getName()->willReturn('eval');
$method3->getName()->willReturn('notKeyword');
$node->getMethods()->willReturn(array(
'echo' => $method1,
'eval' => $method2,
'notKeyword' => $method3,
));
$this->apply($node);
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Doubler\Generator\Node\MethodNode;
class MagicCallPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_anything($node)
{
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_discovers_api_using_phpdoc($node)
{
$node->getParentClass()->willReturn('spec\Prophecy\Doubler\ClassPatch\MagicalApi');
$node->addMethod(new MethodNode('undefinedMethod'))->shouldBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_ignores_existing_methods($node)
{
$node->getParentClass()->willReturn('spec\Prophecy\Doubler\ClassPatch\MagicalApiExtended');
$node->addMethod(new MethodNode('undefinedMethod'))->shouldBeCalled();
$node->addMethod(new MethodNode('definedMethod'))->shouldNotBeCalled();
$this->apply($node);
}
function it_has_50_priority()
{
$this->getPriority()->shouldReturn(50);
}
}
/**
* @method void undefinedMethod()
*/
class MagicalApi
{
/**
* @return void
*/
public function definedMethod()
{
}
}
/**
* @method void undefinedMethod()
* @method void definedMethod()
*/
class MagicalApiExtended extends MagicalApi
{
}

View File

@ -0,0 +1,83 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ProphecySubjectPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function it_has_priority_of_0()
{
$this->getPriority()->shouldReturn(0);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_any_class($node)
{
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_forces_class_to_implement_ProphecySubjectInterface($node)
{
$node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface')->shouldBeCalled();
$node->addProperty('objectProphecy', 'private')->willReturn(null);
$node->getMethods()->willReturn(array());
$node->hasMethod(Argument::any())->willReturn(false);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $constructor
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method3
*/
function it_forces_all_class_methods_except_constructor_to_proxy_calls_into_prophecy_makeCall(
$node, $constructor, $method1, $method2, $method3
)
{
$node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface')->willReturn(null);
$node->addProperty('objectProphecy', 'private')->willReturn(null);
$node->hasMethod(Argument::any())->willReturn(false);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$constructor->getName()->willReturn('__construct');
$method1->getName()->willReturn('method1');
$method2->getName()->willReturn('method2');
$method3->getName()->willReturn('method3');
$node->getMethods()->willReturn(array(
'method1' => $method1,
'method2' => $method2,
'method3' => $method3,
));
$constructor->setCode(Argument::any())->shouldNotBeCalled();
$method1->setCode('return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());')
->shouldBeCalled();
$method2->setCode('return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());')
->shouldBeCalled();
$method3->setCode('return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());')
->shouldBeCalled();
$this->apply($node);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ReflectionClassNewInstancePatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_50()
{
$this->getPriority()->shouldReturn(50);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $reflectionClassNode
* @param \Prophecy\Doubler\Generator\Node\ClassNode $anotherClassNode
*/
function it_supports_ReflectionClass_only($reflectionClassNode, $anotherClassNode)
{
$reflectionClassNode->getParentClass()->willReturn('ReflectionClass');
$anotherClassNode->getParentClass()->willReturn('stdClass');
$this->supports($reflectionClassNode)->shouldReturn(true);
$this->supports($anotherClassNode)->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg2
*/
function it_makes_all_newInstance_arguments_optional($class, $method, $arg1, $arg2)
{
$class->getMethod('newInstance')->willReturn($method);
$method->getArguments()->willReturn(array($arg1));
$arg1->setDefault(null)->shouldBeCalled();
$this->apply($class);
}
}

View File

@ -0,0 +1,91 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class SplFileInfoPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_50()
{
$this->getPriority()->shouldReturn(50);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_does_not_support_nodes_without_parent_class($node)
{
$node->getParentClass()->willReturn('stdClass');
$this->supports($node)->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_nodes_with_SplFileInfo_as_parent_class($node)
{
$node->getParentClass()->willReturn('SplFileInfo');
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_nodes_with_derivative_of_SplFileInfo_as_parent_class($node)
{
$node->getParentClass()->willReturn('SplFileInfo');
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_adds_a_method_to_node_if_not_exists($node)
{
$node->hasMethod('__construct')->willReturn(false);
$node->addMethod(Argument::any())->shouldBeCalled();
$node->getParentClass()->shouldBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function it_updates_existing_method_if_found($node, $method)
{
$node->hasMethod('__construct')->willReturn(true);
$node->getMethod('__construct')->willReturn($method);
$node->getParentClass()->shouldBeCalled();
$method->useParentCode()->shouldBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function it_should_not_supply_a_file_for_a_directory_iterator($node, $method)
{
$node->hasMethod('__construct')->willReturn(true);
$node->getMethod('__construct')->willReturn($method);
$node->getParentClass()->willReturn('DirectoryIterator');
$method->setCode(Argument::that(function($value) {
return strpos($value, '.php') === false;
}))->shouldBeCalled();
$this->apply($node);
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class TraversablePatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_class_that_implements_only_Traversable($node)
{
$node->getInterfaces()->willReturn(array('Traversable'));
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_does_not_support_class_that_implements_Iterator($node)
{
$node->getInterfaces()->willReturn(array('Traversable', 'Iterator'));
$this->supports($node)->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_does_not_support_class_that_implements_IteratorAggregate($node)
{
$node->getInterfaces()->willReturn(array('Traversable', 'IteratorAggregate'));
$this->supports($node)->shouldReturn(false);
}
function it_has_100_priority()
{
$this->getPriority()->shouldReturn(100);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_forces_node_to_implement_IteratorAggregate($node)
{
$node->addInterface('Iterator')->shouldBeCalled();
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$this->apply($node);
}
}

View File

@ -0,0 +1,122 @@
<?php
namespace spec\Prophecy\Doubler;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class DoublerSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\ClassMirror $mirror
* @param \Prophecy\Doubler\Generator\ClassCreator $creator
* @param \Prophecy\Doubler\NameGenerator $namer
*/
function let($mirror, $creator, $namer)
{
$this->beConstructedWith($mirror, $creator, $namer);
}
function it_does_not_have_patches_by_default()
{
$this->getClassPatches()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $patch
*/
function its_registerClassPatch_adds_a_patch_to_the_doubler($patch)
{
$this->registerClassPatch($patch);
$this->getClassPatches()->shouldReturn(array($patch));
}
/**
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt1
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt2
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt3
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt4
*/
function its_getClassPatches_sorts_patches_by_priority($alt1, $alt2, $alt3, $alt4)
{
$alt1->getPriority()->willReturn(2);
$alt2->getPriority()->willReturn(50);
$alt3->getPriority()->willReturn(10);
$alt4->getPriority()->willReturn(0);
$this->registerClassPatch($alt1);
$this->registerClassPatch($alt2);
$this->registerClassPatch($alt3);
$this->registerClassPatch($alt4);
$this->getClassPatches()->shouldReturn(array($alt2, $alt3, $alt1, $alt4));
}
/**
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt1
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt2
* @param \ReflectionClass $class
* @param \ReflectionClass $interface1
* @param \ReflectionClass $interface2
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function its_double_mirrors_alterates_and_instantiates_provided_class(
$mirror, $creator, $namer, $alt1, $alt2, $class, $interface1, $interface2, $node
)
{
$mirror->reflect($class, array($interface1, $interface2))->willReturn($node);
$alt1->supports($node)->willReturn(true);
$alt2->supports($node)->willReturn(false);
$alt1->getPriority()->willReturn(1);
$alt2->getPriority()->willReturn(2);
$namer->name($class, array($interface1, $interface2))->willReturn('SplStack');
$class->getName()->willReturn('stdClass');
$interface1->getName()->willReturn('ArrayAccess');
$interface2->getName()->willReturn('Iterator');
$alt1->apply($node)->shouldBeCalled();
$alt2->apply($node)->shouldNotBeCalled();
$creator->create('SplStack', $node)->shouldBeCalled();
$this->registerClassPatch($alt1);
$this->registerClassPatch($alt2);
$this->double($class, array($interface1, $interface2))
->shouldReturnAnInstanceOf('SplStack');
}
/**
* @param \ReflectionClass $class
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_double_instantiates_a_class_with_constructor_argument($mirror, $class, $node, $namer)
{
$class->getName()->willReturn('ReflectionClass');
$mirror->reflect($class, array())->willReturn($node);
$namer->name($class, array())->willReturn('ReflectionClass');
$double = $this->double($class, array(), array('stdClass'));
$double->shouldBeAnInstanceOf('ReflectionClass');
$double->getName()->shouldReturn('stdClass');
}
/**
* @param \ReflectionClass $class
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_can_instantiate_class_with_final_constructor($mirror, $class, $node, $namer)
{
$class->getName()->willReturn('spec\Prophecy\Doubler\WithFinalConstructor');
$mirror->reflect($class, array())->willReturn($node);
$namer->name($class, array())->willReturn('spec\Prophecy\Doubler\WithFinalConstructor');
$double = $this->double($class, array());
$double->shouldBeAnInstanceOf('spec\Prophecy\Doubler\WithFinalConstructor');
}
}
class WithFinalConstructor
{
final public function __construct() {}
}

View File

@ -0,0 +1,186 @@
<?php
namespace spec\Prophecy\Doubler\Generator;
use PhpSpec\ObjectBehavior;
class ClassCodeGeneratorSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method3
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument11
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument12
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument21
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument31
*/
function it_generates_proper_php_code_for_specific_ClassNode(
$class, $method1, $method2, $method3, $argument11, $argument12, $argument21, $argument31
)
{
$class->getParentClass()->willReturn('RuntimeException');
$class->getInterfaces()->willReturn(array(
'Prophecy\Doubler\Generator\MirroredInterface', 'ArrayAccess', 'ArrayIterator'
));
$class->getProperties()->willReturn(array('name' => 'public', 'email' => 'private'));
$class->getMethods()->willReturn(array($method1, $method2, $method3));
$method1->getName()->willReturn('getName');
$method1->getVisibility()->willReturn('public');
$method1->returnsReference()->willReturn(false);
$method1->isStatic()->willReturn(true);
$method1->getArguments()->willReturn(array($argument11, $argument12));
$method1->getCode()->willReturn('return $this->name;');
$method2->getName()->willReturn('getEmail');
$method2->getVisibility()->willReturn('protected');
$method2->returnsReference()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method2->getArguments()->willReturn(array($argument21));
$method2->getCode()->willReturn('return $this->email;');
$method3->getName()->willReturn('getRefValue');
$method3->getVisibility()->willReturn('public');
$method3->returnsReference()->willReturn(true);
$method3->isStatic()->willReturn(false);
$method3->getArguments()->willReturn(array($argument31));
$method3->getCode()->willReturn('return $this->refValue;');
$argument11->getName()->willReturn('fullname');
$argument11->getTypeHint()->willReturn('array');
$argument11->isOptional()->willReturn(true);
$argument11->getDefault()->willReturn(null);
$argument11->isPassedByReference()->willReturn(false);
$argument12->getName()->willReturn('class');
$argument12->getTypeHint()->willReturn('ReflectionClass');
$argument12->isOptional()->willReturn(false);
$argument12->isPassedByReference()->willReturn(false);
$argument21->getName()->willReturn('default');
$argument21->getTypeHint()->willReturn(null);
$argument21->isOptional()->willReturn(true);
$argument21->getDefault()->willReturn('ever.zet@gmail.com');
$argument21->isPassedByReference()->willReturn(false);
$argument31->getName()->willReturn('refValue');
$argument31->getTypeHint()->willReturn(null);
$argument31->isOptional()->willReturn(false);
$argument31->getDefault()->willReturn();
$argument31->isPassedByReference()->willReturn(false);
$code = $this->generate('CustomClass', $class);
$expected = <<<'PHP'
namespace {
class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generator\MirroredInterface, \ArrayAccess, \ArrayIterator {
public $name;
private $email;
public static function getName(array $fullname = NULL, \ReflectionClass $class) {
return $this->name;
}
protected function getEmail( $default = 'ever.zet@gmail.com') {
return $this->email;
}
public function &getRefValue( $refValue) {
return $this->refValue;
}
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument
*/
function it_overrides_properly_methods_with_args_passed_by_reference(
$class, $method, $argument
)
{
$class->getParentClass()->willReturn('RuntimeException');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array($method));
$method->getName()->willReturn('getName');
$method->getVisibility()->willReturn('public');
$method->isStatic()->willReturn(false);
$method->getArguments()->willReturn(array($argument));
$method->returnsReference()->willReturn(false);
$method->getCode()->willReturn('return $this->name;');
$argument->getName()->willReturn('fullname');
$argument->getTypeHint()->willReturn('array');
$argument->isOptional()->willReturn(true);
$argument->getDefault()->willReturn(null);
$argument->isPassedByReference()->willReturn(true);
$code = $this->generate('CustomClass', $class);
$expected =<<<'PHP'
namespace {
class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generator\MirroredInterface {
public function getName(array &$fullname = NULL) {
return $this->name;
}
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_generates_empty_class_for_empty_ClassNode($class)
{
$class->getParentClass()->willReturn('stdClass');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array());
$code = $this->generate('CustomClass', $class);
$expected =<<<'PHP'
namespace {
class CustomClass extends \stdClass implements \Prophecy\Doubler\Generator\MirroredInterface {
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_wraps_class_in_namespace_if_it_is_namespaced($class)
{
$class->getParentClass()->willReturn('stdClass');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array());
$code = $this->generate('My\Awesome\CustomClass', $class);
$expected =<<<'PHP'
namespace My\Awesome {
class CustomClass extends \stdClass implements \Prophecy\Doubler\Generator\MirroredInterface {
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace spec\Prophecy\Doubler\Generator;
use PhpSpec\ObjectBehavior;
class ClassCreatorSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\ClassCodeGenerator $generator
*/
function let($generator)
{
$this->beConstructedWith($generator);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_evaluates_code_generated_by_ClassCodeGenerator($generator, $class)
{
$generator->generate('stdClass', $class)->shouldBeCalled()->willReturn(
'return 42;'
);
$this->create('stdClass', $class)->shouldReturn(42);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_throws_an_exception_if_class_does_not_exist_after_evaluation($generator, $class)
{
$generator->generate('CustomClass', $class)->shouldBeCalled()->willReturn(
'return 42;'
);
$class->getParentClass()->willReturn('stdClass');
$class->getInterfaces()->willReturn(array('Interface1', 'Interface2'));
$this->shouldThrow('Prophecy\Exception\Doubler\ClassCreatorException')
->duringCreate('CustomClass', $class);
}
}

View File

@ -0,0 +1,554 @@
<?php
namespace spec\Prophecy\Doubler\Generator;
use PhpSpec\ObjectBehavior;
use I\Simply;
use ReflectionClass;
use ReflectionMethod;
use ReflectionParameter;
class ClassMirrorSpec extends ObjectBehavior
{
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method1
* @param ReflectionMethod $method2
* @param ReflectionMethod $method3
*/
function it_reflects_a_class_by_mirroring_all_its_public_methods(
$class, $method1, $method2, $method3
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array(
$method1, $method2, $method3
));
$method1->getName()->willReturn('getName');
$method2->getName()->willReturn('isPublic');
$method3->getName()->willReturn('isAbstract');
$method1->isFinal()->willReturn(false);
$method2->isFinal()->willReturn(false);
$method3->isFinal()->willReturn(false);
$method1->isProtected()->willReturn(false);
$method2->isProtected()->willReturn(false);
$method3->isProtected()->willReturn(false);
$method1->isStatic()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method3->isStatic()->willReturn(false);
$method1->returnsReference()->willReturn(false);
$method2->returnsReference()->willReturn(false);
$method3->returnsReference()->willReturn(false);
$method1->getParameters()->willReturn(array());
$method2->getParameters()->willReturn(array());
$method3->getParameters()->willReturn(array());
$classNode = $this->reflect($class, array());
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('Custom\ClassName');
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(3);
$classNode->hasMethod('getName')->shouldReturn(true);
$classNode->hasMethod('isPublic')->shouldReturn(true);
$classNode->hasMethod('isAbstract')->shouldReturn(true);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $parameter
*/
function it_changes_argument_names_if_they_are_varying($class, $method, $parameter)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$method->getParameters()->willReturn(array($parameter));
$method->getName()->willReturn('methodName');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(false);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
$parameter->getName()->willReturn('...');
$parameter->isDefaultValueAvailable()->willReturn(true);
$parameter->getDefaultValue()->willReturn(null);
$parameter->isPassedByReference()->willReturn(false);
$parameter->getClass()->willReturn($class);
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argumentNodes = $methodNodes['methodName']->getArguments();
$argumentNode = $argumentNodes[0];
$argumentNode->getName()->shouldReturn('__dot_dot_dot__');
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_reflects_protected_abstract_methods($class, $method)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array($method));
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array());
$method->isProtected()->willReturn(true);
$method->isStatic()->willReturn(false);
$method->getParameters()->willReturn(array());
$method->getName()->willReturn('innerDetail');
$method->returnsReference()->willReturn(false);
$classNode = $this->reflect($class, array());
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('Custom\ClassName');
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(1);
$methodNodes['innerDetail']->getVisibility()->shouldReturn('protected');
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_reflects_public_static_methods($class, $method)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array($method));
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array());
$method->isProtected()->willReturn(true);
$method->isStatic()->willReturn(true);
$method->getParameters()->willReturn(array());
$method->getName()->willReturn('innerDetail');
$method->returnsReference()->willReturn(false);
$classNode = $this->reflect($class, array());
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('Custom\ClassName');
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(1);
$methodNodes['innerDetail']->getVisibility()->shouldReturn('protected');
$methodNodes['innerDetail']->isStatic()->shouldReturn(true);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $param1
* @param ReflectionParameter $param2
* @param ReflectionClass $typeHint
* @param ReflectionParameter $param3
*/
function it_properly_reads_methods_arguments_with_types(
$class, $method, $param1, $param2, $typeHint, $param3
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('methodWithArgs');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(true);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
$method->getParameters()->willReturn(array($param1, $param2, $param3));
$param1->getName()->willReturn('arg_1');
$param1->isArray()->willReturn(true);
$param1->getClass()->willReturn(null);
$param1->isDefaultValueAvailable()->willReturn(true);
$param1->isPassedByReference()->willReturn(false);
$param1->allowsNull()->willReturn(false);
$param1->getDefaultValue()->willReturn(array());
$param2->getName()->willReturn('arg2');
$param2->isArray()->willReturn(false);
$param2->getClass()->willReturn($typeHint);
$param2->isDefaultValueAvailable()->willReturn(false);
$param2->isOptional()->willReturn(false);
$param2->isPassedByReference()->willReturn(false);
$param2->allowsNull()->willReturn(false);
$typeHint->getName()->willReturn('ArrayAccess');
$param3->getName()->willReturn('arg_3');
$param3->isArray()->willReturn(false);
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$param3->isCallable()->willReturn(true);
}
$param3->getClass()->willReturn(null);
$param3->isOptional()->willReturn(false);
$param3->isDefaultValueAvailable()->willReturn(false);
$param3->isPassedByReference()->willReturn(false);
$param3->allowsNull()->willReturn(true);
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argNodes = $methodNodes['methodWithArgs']->getArguments();
$argNodes[0]->getName()->shouldReturn('arg_1');
$argNodes[0]->getTypeHint()->shouldReturn('array');
$argNodes[0]->isOptional()->shouldReturn(true);
$argNodes[0]->getDefault()->shouldReturn(array());
$argNodes[1]->getName()->shouldReturn('arg2');
$argNodes[1]->getTypeHint()->shouldReturn('ArrayAccess');
$argNodes[1]->isOptional()->shouldReturn(false);
$argNodes[2]->getName()->shouldReturn('arg_3');
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$argNodes[2]->getTypeHint()->shouldReturn('callable');
$argNodes[2]->isOptional()->shouldReturn(true);
$argNodes[2]->getDefault()->shouldReturn(null);
} else {
$argNodes[2]->isOptional()->shouldReturn(false);
}
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $param1
*/
function it_marks_required_args_without_types_as_not_optional(
$class, $method, $param1
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('methodWithArgs');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(false);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
$method->getParameters()->willReturn(array($param1));
$param1->getName()->willReturn('arg_1');
$param1->isArray()->willReturn(false);
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$param1->isCallable()->willReturn(false);
}
$param1->getClass()->willReturn(null);
$param1->isDefaultValueAvailable()->willReturn(false);
$param1->isOptional()->willReturn(false);
$param1->isPassedByReference()->willReturn(false);
$param1->allowsNull()->willReturn(true);
if (defined('HHVM_VERSION')) {
$param1->getTypehintText()->willReturn(null);
}
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argNodes = $methodNodes['methodWithArgs']->getArguments();
$argNodes[0]->isOptional()->shouldReturn(false);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $param1
* @param ReflectionParameter $param2
* @param ReflectionClass $typeHint
*/
function it_marks_passed_by_reference_args_as_passed_by_reference(
$class, $method, $param1, $param2, $typeHint
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('methodWithArgs');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(false);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
$method->getParameters()->willReturn(array($param1, $param2));
$param1->getName()->willReturn('arg_1');
$param1->isArray()->willReturn(false);
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$param1->isCallable()->willReturn(false);
}
$param1->getClass()->willReturn(null);
$param1->isDefaultValueAvailable()->willReturn(false);
$param1->isOptional()->willReturn(true);
$param1->isPassedByReference()->willReturn(true);
$param1->allowsNull()->willReturn(false);
if (defined('HHVM_VERSION')) {
$param1->getTypehintText()->willReturn(null);
}
$param2->getName()->willReturn('arg2');
$param2->isArray()->willReturn(false);
$param2->getClass()->willReturn($typeHint);
$param2->isDefaultValueAvailable()->willReturn(false);
$param2->isOptional()->willReturn(false);
$param2->isPassedByReference()->willReturn(false);
$param2->allowsNull()->willReturn(false);
$typeHint->getName()->willReturn('ArrayAccess');
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argNodes = $methodNodes['methodWithArgs']->getArguments();
$argNodes[0]->isPassedByReference()->shouldReturn(true);
$argNodes[1]->isPassedByReference()->shouldReturn(false);
}
/**
* @param ReflectionClass $class
*/
function it_throws_an_exception_if_class_is_final($class)
{
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(true);
$class->getName()->willReturn('Custom\ClassName');
$this->shouldThrow('Prophecy\Exception\Doubler\ClassMirrorException')
->duringReflect($class, array());
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_ignores_final_methods($class, $method)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->isFinal()->willReturn(true);
$method->getName()->willReturn('finalImplementation');
$classNode = $this->reflect($class, array());
$classNode->getMethods()->shouldHaveCount(0);
}
/**
* @param ReflectionClass $interface
*/
function it_throws_an_exception_if_interface_provided_instead_of_class($interface)
{
$interface->isInterface()->willReturn(true);
$interface->getName()->willReturn('Custom\ClassName');
$this->shouldThrow('Prophecy\Exception\InvalidArgumentException')
->duringReflect($interface, array());
}
/**
* @param ReflectionClass $interface1
* @param ReflectionClass $interface2
* @param ReflectionMethod $method1
* @param ReflectionMethod $method2
* @param ReflectionMethod $method3
*/
function it_reflects_all_interfaces_methods(
$interface1, $interface2, $method1, $method2, $method3
)
{
$interface1->getName()->willReturn('MyInterface1');
$interface2->getName()->willReturn('MyInterface2');
$interface1->isInterface()->willReturn(true);
$interface2->isInterface()->willReturn(true);
$interface1->getMethods()->willReturn(array($method1));
$interface2->getMethods()->willReturn(array($method2, $method3));
$method1->getName()->willReturn('getName');
$method2->getName()->willReturn('isPublic');
$method3->getName()->willReturn('isAbstract');
$method1->isProtected()->willReturn(false);
$method2->isProtected()->willReturn(false);
$method3->isProtected()->willReturn(false);
$method1->returnsReference()->willReturn(false);
$method2->returnsReference()->willReturn(false);
$method3->returnsReference()->willReturn(false);
$method1->isStatic()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method3->isStatic()->willReturn(false);
$method1->getParameters()->willReturn(array());
$method2->getParameters()->willReturn(array());
$method3->getParameters()->willReturn(array());
$classNode = $this->reflect(null, array($interface1, $interface2));
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('stdClass');
$classNode->getInterfaces()->shouldReturn(array(
'Prophecy\Doubler\Generator\ReflectionInterface', 'MyInterface2', 'MyInterface1',
));
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(3);
$classNode->hasMethod('getName')->shouldReturn(true);
$classNode->hasMethod('isPublic')->shouldReturn(true);
$classNode->hasMethod('isAbstract')->shouldReturn(true);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method1
* @param ReflectionMethod $method2
* @param ReflectionMethod $method3
*/
function it_ignores_virtually_private_methods($class, $method1, $method2, $method3)
{
$class->getName()->willReturn('SomeClass');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method1, $method2, $method3));
$method1->getName()->willReturn('_getName');
$method2->getName()->willReturn('__toString');
$method3->getName()->willReturn('isAbstract');
$method1->isFinal()->willReturn(false);
$method2->isFinal()->willReturn(false);
$method3->isFinal()->willReturn(false);
$method1->isProtected()->willReturn(false);
$method2->isProtected()->willReturn(false);
$method3->isProtected()->willReturn(false);
$method1->isStatic()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method3->isStatic()->willReturn(false);
$method1->returnsReference()->willReturn(false);
$method2->returnsReference()->willReturn(false);
$method3->returnsReference()->willReturn(false);
$method1->getParameters()->willReturn(array());
$method2->getParameters()->willReturn(array());
$method3->getParameters()->willReturn(array());
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(2);
$classNode->hasMethod('isAbstract')->shouldReturn(true);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_does_not_throw_exception_for_virtually_private_finals($class, $method)
{
$class->getName()->willReturn('SomeClass');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('__toString');
$method->isFinal()->willReturn(true);
$this->shouldNotThrow()->duringReflect($class, array());
}
/**
* @param ReflectionClass $class
*/
function it_throws_an_exception_if_class_provided_in_interfaces_list($class)
{
$class->getName()->willReturn('MyClass');
$class->isInterface()->willReturn(false);
$this->shouldThrow('InvalidArgumentException')
->duringReflect(null, array($class));
}
function it_throws_an_exception_if_not_reflection_provided_as_interface()
{
$this->shouldThrow('InvalidArgumentException')
->duringReflect(null, array(null));
}
function it_doesnt_fail_to_typehint_nonexistent_FQCN()
{
$classNode = $this->reflect(new ReflectionClass('spec\Prophecy\Doubler\Generator\OptionalDepsClass'), array());
$method = $classNode->getMethod('iHaveAStrangeTypeHintedArg');
$arguments = $method->getArguments();
$arguments[0]->getTypeHint()->shouldBe('I\Simply\Am\Nonexistent');
}
function it_doesnt_fail_to_typehint_nonexistent_RQCN()
{
$classNode = $this->reflect(new ReflectionClass('spec\Prophecy\Doubler\Generator\OptionalDepsClass'), array());
$method = $classNode->getMethod('iHaveAnEvenStrangerTypeHintedArg');
$arguments = $method->getArguments();
$arguments[0]->getTypeHint()->shouldBe('I\Simply\Am\Not');
}
function it_doesnt_use_scalar_typehints()
{
$classNode = $this->reflect(new ReflectionClass('ReflectionMethod'), array());
$method = $classNode->getMethod('export');
$arguments = $method->getArguments();
$arguments[0]->getTypeHint()->shouldReturn(null);
$arguments[1]->getTypeHint()->shouldReturn(null);
$arguments[2]->getTypeHint()->shouldReturn(null);
}
}
class OptionalDepsClass
{
public function iHaveAStrangeTypeHintedArg(\I\Simply\Am\Nonexistent $class)
{
}
public function iHaveAnEvenStrangerTypeHintedArg(Simply\Am\Not $class)
{
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace spec\Prophecy\Doubler\Generator\Node;
use PhpSpec\ObjectBehavior;
class ArgumentNodeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('name');
}
function it_is_not_be_passed_by_reference_by_default()
{
$this->shouldNotBePassedByReference();
}
function it_is_passed_by_reference_if_marked()
{
$this->setAsPassedByReference();
$this->shouldBePassedByReference();
}
function it_has_name_with_which_it_was_been_constructed()
{
$this->getName()->shouldReturn('name');
}
function it_has_no_typehint_by_default()
{
$this->getTypeHint()->shouldReturn(null);
}
function its_typeHint_is_mutable()
{
$this->setTypeHint('array');
$this->getTypeHint()->shouldReturn('array');
}
function it_does_not_have_default_value_by_default()
{
$this->getDefault()->shouldReturn(null);
}
function it_is_not_optional_by_default()
{
$this->isOptional()->shouldReturn(false);
}
function its_default_is_mutable()
{
$this->setDefault(array());
$this->getDefault()->shouldReturn(array());
}
function it_is_marked_as_optional_when_default_is_set()
{
$this->setDefault(null);
$this->isOptional()->shouldReturn(true);
}
}

View File

@ -0,0 +1,154 @@
<?php
namespace spec\Prophecy\Doubler\Generator\Node;
use PhpSpec\ObjectBehavior;
class ClassNodeSpec extends ObjectBehavior
{
function its_parentClass_is_a_stdClass_by_default()
{
$this->getParentClass()->shouldReturn('stdClass');
}
function its_parentClass_is_mutable()
{
$this->setParentClass('Exception');
$this->getParentClass()->shouldReturn('Exception');
}
function its_parentClass_is_set_to_stdClass_if_user_set_null()
{
$this->setParentClass(null);
$this->getParentClass()->shouldReturn('stdClass');
}
function it_does_not_implement_any_interface_by_default()
{
$this->getInterfaces()->shouldHaveCount(0);
}
function its_addInterface_adds_item_to_the_list_of_implemented_interfaces()
{
$this->addInterface('MyInterface');
$this->getInterfaces()->shouldHaveCount(1);
}
function its_hasInterface_returns_true_if_class_implements_interface()
{
$this->addInterface('MyInterface');
$this->hasInterface('MyInterface')->shouldReturn(true);
}
function its_hasInterface_returns_false_if_class_does_not_implements_interface()
{
$this->hasInterface('MyInterface')->shouldReturn(false);
}
function it_supports_implementation_of_multiple_interfaces()
{
$this->addInterface('MyInterface');
$this->addInterface('MySecondInterface');
$this->getInterfaces()->shouldHaveCount(2);
}
function it_ignores_same_interfaces_added_twice()
{
$this->addInterface('MyInterface');
$this->addInterface('MyInterface');
$this->getInterfaces()->shouldHaveCount(1);
$this->getInterfaces()->shouldReturn(array('MyInterface'));
}
function it_does_not_have_methods_by_default()
{
$this->getMethods()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
*/
function it_can_has_methods($method1, $method2)
{
$method1->getName()->willReturn('__construct');
$method2->getName()->willReturn('getName');
$this->addMethod($method1);
$this->addMethod($method2);
$this->getMethods()->shouldReturn(array(
'__construct' => $method1,
'getName' => $method2
));
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function its_hasMethod_returns_true_if_method_exists($method)
{
$method->getName()->willReturn('getName');
$this->addMethod($method);
$this->hasMethod('getName')->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function its_getMethod_returns_method_by_name($method)
{
$method->getName()->willReturn('getName');
$this->addMethod($method);
$this->getMethod('getName')->shouldReturn($method);
}
function its_hasMethod_returns_false_if_method_does_not_exists()
{
$this->hasMethod('getName')->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function its_hasMethod_returns_false_if_method_has_been_removed($method)
{
$method->getName()->willReturn('getName');
$this->addMethod($method);
$this->removeMethod('getName');
$this->hasMethod('getName')->shouldReturn(false);
}
function it_does_not_have_properties_by_default()
{
$this->getProperties()->shouldHaveCount(0);
}
function it_is_able_to_have_properties()
{
$this->addProperty('title');
$this->addProperty('text', 'private');
$this->getProperties()->shouldReturn(array(
'title' => 'public',
'text' => 'private'
));
}
function its_addProperty_does_not_accept_unsupported_visibility()
{
$this->shouldThrow('InvalidArgumentException')->duringAddProperty('title', 'town');
}
function its_addProperty_lowercases_visibility_before_setting()
{
$this->addProperty('text', 'PRIVATE');
$this->getProperties()->shouldReturn(array('text' => 'private'));
}
}

View File

@ -0,0 +1,123 @@
<?php
namespace spec\Prophecy\Doubler\Generator\Node;
use PhpSpec\ObjectBehavior;
class MethodNodeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('getTitle');
}
function it_has_a_name()
{
$this->getName()->shouldReturn('getTitle');
}
function it_has_public_visibility_by_default()
{
$this->getVisibility()->shouldReturn('public');
}
function its_visibility_is_mutable()
{
$this->setVisibility('private');
$this->getVisibility()->shouldReturn('private');
}
function it_is_not_static_by_default()
{
$this->shouldNotBeStatic();
}
function it_does_not_return_a_reference_by_default()
{
$this->returnsReference()->shouldReturn(false);
}
function it_should_be_settable_as_returning_a_reference_through_setter()
{
$this->setReturnsReference();
$this->returnsReference()->shouldReturn(true);
}
function it_should_be_settable_as_static_through_setter()
{
$this->setStatic();
$this->shouldBeStatic();
}
function it_accepts_only_supported_visibilities()
{
$this->shouldThrow('InvalidArgumentException')->duringSetVisibility('stealth');
}
function it_lowercases_visibility_before_setting_it()
{
$this->setVisibility('Public');
$this->getVisibility()->shouldReturn('public');
}
/**
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument2
*/
function its_useParentCode_causes_method_to_call_parent($argument1, $argument2)
{
$argument1->getName()->willReturn('objectName');
$argument2->getName()->willReturn('default');
$this->addArgument($argument1);
$this->addArgument($argument2);
$this->useParentCode();
$this->getCode()->shouldReturn(
'return parent::getTitle($objectName, $default);'
);
}
function its_code_is_mutable()
{
$this->setCode('echo "code";');
$this->getCode()->shouldReturn('echo "code";');
}
function its_reference_returning_methods_will_generate_exceptions()
{
$this->setCode('echo "code";');
$this->setReturnsReference();
$this->getCode()->shouldReturn("throw new \Prophecy\Exception\Doubler\ReturnByReferenceException('Returning by reference not supported', get_class(\$this), 'getTitle');");
}
function its_setCode_provided_with_null_cleans_method_body()
{
$this->setCode(null);
$this->getCode()->shouldReturn('');
}
function it_is_constructable_with_code()
{
$this->beConstructedWith('getTitle', 'die();');
$this->getCode()->shouldReturn('die();');
}
function it_does_not_have_arguments_by_default()
{
$this->getArguments()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument2
*/
function it_supports_adding_arguments($argument1, $argument2)
{
$this->addArgument($argument1);
$this->addArgument($argument2);
$this->getArguments()->shouldReturn(array($argument1, $argument2));
}
}

View File

@ -0,0 +1,96 @@
<?php
namespace spec\Prophecy\Doubler;
use PhpSpec\ObjectBehavior;
class LazyDoubleSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Doubler $doubler
*/
function let($doubler)
{
$this->beConstructedWith($doubler);
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function it_returns_anonymous_double_instance_by_default($doubler, $double)
{
$doubler->double(null, array())->willReturn($double);
$this->getInstance()->shouldReturn($double);
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
* @param \ReflectionClass $class
*/
function it_returns_class_double_instance_if_set($doubler, $double, $class)
{
$doubler->double($class, array())->willReturn($double);
$this->setParentClass($class);
$this->getInstance()->shouldReturn($double);
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double1
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double2
*/
function it_returns_same_double_instance_if_called_2_times(
$doubler, $double1, $double2
)
{
$doubler->double(null, array())->willReturn($double1);
$doubler->double(null, array())->willReturn($double2);
$this->getInstance()->shouldReturn($double2);
$this->getInstance()->shouldReturn($double2);
}
function its_setParentClass_throws_ClassNotFoundException_if_class_not_found()
{
$this->shouldThrow('Prophecy\Exception\Doubler\ClassNotFoundException')
->duringSetParentClass('SomeUnexistingClass');
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function its_setParentClass_throws_exception_if_prophecy_is_already_created(
$doubler, $double
)
{
$doubler->double(null, array())->willReturn($double);
$this->getInstance();
$this->shouldThrow('Prophecy\Exception\Doubler\DoubleException')
->duringSetParentClass('stdClass');
}
function its_addInterface_throws_InterfaceNotFoundException_if_no_interface_found()
{
$this->shouldThrow('Prophecy\Exception\Doubler\InterfaceNotFoundException')
->duringAddInterface('SomeUnexistingInterface');
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function its_addInterface_throws_exception_if_prophecy_is_already_created(
$doubler, $double
)
{
$doubler->double(null, array())->willReturn($double);
$this->getInstance();
$this->shouldThrow('Prophecy\Exception\Doubler\DoubleException')
->duringAddInterface('ArrayAccess');
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace spec\Prophecy\Doubler;
use PhpSpec\ObjectBehavior;
class NameGeneratorSpec extends ObjectBehavior
{
/**
* @param \ReflectionClass $class
*/
function its_name_generates_name_based_on_simple_class_reflection($class)
{
$class->getName()->willReturn('stdClass');
$this->name($class, array())->shouldStartWith('Double\stdClass\\');
}
/**
* @param \ReflectionClass $class
*/
function its_name_generates_name_based_on_namespaced_class_reflection($class)
{
$class->getName()->willReturn('Some\Custom\Class');
$this->name($class, array())->shouldStartWith('Double\Some\Custom\Class\P');
}
/**
* @param \ReflectionClass $interface1
* @param \ReflectionClass $interface2
*/
function its_name_generates_name_based_on_interface_shortnames($interface1, $interface2)
{
$interface1->getShortName()->willReturn('HandlerInterface');
$interface2->getShortName()->willReturn('LoaderInterface');
$this->name(null, array($interface1, $interface2))->shouldStartWith(
'Double\HandlerInterface\LoaderInterface\P'
);
}
function it_generates_proper_name_for_no_class_and_interfaces_list()
{
$this->name(null, array())->shouldStartWith('Double\stdClass\P');
}
/**
* @param \ReflectionClass $class
* @param \ReflectionClass $interface1
* @param \ReflectionClass $interface2
*/
function its_name_generates_name_based_only_on_class_if_its_available(
$class, $interface1, $interface2
)
{
$class->getName()->willReturn('Some\Custom\Class');
$interface1->getShortName()->willReturn('HandlerInterface');
$interface2->getShortName()->willReturn('LoaderInterface');
$this->name($class, array($interface1, $interface2))->shouldStartWith(
'Double\Some\Custom\Class\P'
);
}
public function getMatchers()
{
return array(
'startWith' => function ($subject, $string) {
return 0 === strpos($subject, $string);
},
);
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace spec\Prophecy\Exception\Call;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy\Prophecy;
class UnexpectedCallExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
*/
function let($objectProphecy)
{
$this->beConstructedWith('msg', $objectProphecy, 'getName', array('arg1', 'arg2'));
}
function it_is_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Prophecy\ObjectProphecyException');
}
function it_exposes_method_name_through_getter()
{
$this->getMethodName()->shouldReturn('getName');
}
function it_exposes_arguments_through_getter()
{
$this->getArguments()->shouldReturn(array('arg1', 'arg2'));
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class ClassCreatorExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function let($node)
{
$this->beConstructedWith('', $node);
}
function it_is_a_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Exception');
$this->shouldBeAnInstanceOf('Prophecy\Exception\Doubler\DoublerException');
}
function it_contains_a_reflected_node($node)
{
$this->getClassNode()->shouldReturn($node);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
class ClassMirrorExceptionSpec extends ObjectBehavior
{
/**
* @param \ReflectionClass $class
*/
function let($class)
{
$this->beConstructedWith('', $class);
}
function it_is_a_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Exception');
$this->shouldBeAnInstanceOf('Prophecy\Exception\Doubler\DoublerException');
}
function it_contains_a_reflected_class_link($class)
{
$this->getReflectedClass()->shouldReturn($class);
}
}

Some files were not shown because too many files have changed in this diff Show More