"packages": [
{
"name": "brain/hierarchy",
- "version": "2.3.0",
+ "version": "2.3.1",
"source": {
"type": "git",
"url": "https://github.com/Brain-WP/Hierarchy.git",
- "reference": "adb52da233e586051a577ef5eabe2c537df785d5"
+ "reference": "239f9bbe49ff6ad1199bbcad308d2c7977bee25a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Brain-WP/Hierarchy/zipball/adb52da233e586051a577ef5eabe2c537df785d5",
- "reference": "adb52da233e586051a577ef5eabe2c537df785d5",
+ "url": "https://api.github.com/repos/Brain-WP/Hierarchy/zipball/239f9bbe49ff6ad1199bbcad308d2c7977bee25a",
+ "reference": "239f9bbe49ff6ad1199bbcad308d2c7977bee25a",
"shasum": ""
},
"require": {
"keywords": [
"wordpress"
],
- "time": "2016-09-15 13:33:53"
+ "time": "2017-12-28 17:16:07"
},
{
"name": "composer/installers",
- "version": "v1.4.0",
+ "version": "v1.5.0",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
- "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b"
+ "reference": "049797d727261bf27f2690430d935067710049c2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/installers/zipball/9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b",
- "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b",
+ "url": "https://api.github.com/repos/composer/installers/zipball/049797d727261bf27f2690430d935067710049c2",
+ "reference": "049797d727261bf27f2690430d935067710049c2",
"shasum": ""
},
"require": {
},
"require-dev": {
"composer/composer": "1.0.*@dev",
- "phpunit/phpunit": "4.1.*"
+ "phpunit/phpunit": "^4.8.36"
},
"type": "composer-plugin",
"extra": {
"lavalite",
"lithium",
"magento",
+ "majima",
"mako",
"mediawiki",
"modulework",
+ "modx",
"moodle",
"osclass",
"phpbb",
"piwik",
"ppi",
"puppet",
+ "pxcms",
"reindex",
"roundcube",
"shopware",
"zend",
"zikula"
],
- "time": "2017-08-09 07:53:48"
+ "time": "2017-12-29 09:13:20"
},
{
"name": "doctrine/inflector",
- "version": "v1.2.0",
+ "version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462"
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a",
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^6.2"
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2.x-dev"
+ "dev-master": "1.3.x-dev"
}
},
"autoload": {
"singularize",
"string"
],
- "time": "2017-07-22 12:18:28"
+ "time": "2018-01-09 20:05:19"
},
{
"name": "hassankhan/config",
},
{
"name": "illuminate/config",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/config.git",
- "reference": "8fe700aa596bc623d347e4578041fbda7a44c3d9"
+ "reference": "e8158dff3189deed846c84c66c60fa68c21ee579"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/config/zipball/8fe700aa596bc623d347e4578041fbda7a44c3d9",
- "reference": "8fe700aa596bc623d347e4578041fbda7a44c3d9",
+ "url": "https://api.github.com/repos/illuminate/config/zipball/e8158dff3189deed846c84c66c60fa68c21ee579",
+ "reference": "e8158dff3189deed846c84c66c60fa68c21ee579",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Config package.",
"homepage": "https://laravel.com",
- "time": "2017-02-04 20:27:32"
+ "time": "2017-11-07 20:23:51"
},
{
"name": "illuminate/container",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
- "reference": "c5b8a02a34a52c307f16922334c355c5eef725a6"
+ "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/container/zipball/c5b8a02a34a52c307f16922334c355c5eef725a6",
- "reference": "c5b8a02a34a52c307f16922334c355c5eef725a6",
+ "url": "https://api.github.com/repos/illuminate/container/zipball/4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
+ "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "php": "^7.1.3",
+ "psr/container": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Container package.",
"homepage": "https://laravel.com",
- "time": "2017-05-24 14:15:53"
+ "time": "2018-01-21 02:13:38"
},
{
"name": "illuminate/contracts",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0"
+ "reference": "6a11fbccbc7da16a85fcd1d4b08e51b5658de0d4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/contracts/zipball/31f0193eb14aa3ee07841dc254081425616e79f0",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0",
+ "url": "https://api.github.com/repos/illuminate/contracts/zipball/6a11fbccbc7da16a85fcd1d4b08e51b5658de0d4",
+ "reference": "6a11fbccbc7da16a85fcd1d4b08e51b5658de0d4",
"shasum": ""
},
"require": {
- "php": ">=5.6.4"
+ "php": "^7.1.3",
+ "psr/container": "~1.0",
+ "psr/simple-cache": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com",
- "time": "2017-04-19 20:17:43"
+ "time": "2018-05-08 13:22:33"
},
{
"name": "illuminate/events",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/events.git",
- "reference": "ebdca3b0305e9fc954afb9e422c4559482cd11e6"
+ "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/events/zipball/ebdca3b0305e9fc954afb9e422c4559482cd11e6",
- "reference": "ebdca3b0305e9fc954afb9e422c4559482cd11e6",
+ "url": "https://api.github.com/repos/illuminate/events/zipball/b6e73ed40478cef2ef98d5ddb27f333291606cea",
+ "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea",
"shasum": ""
},
"require": {
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4"
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Events package.",
"homepage": "https://laravel.com",
- "time": "2017-05-02 12:57:00"
+ "time": "2018-02-26 19:00:55"
},
{
"name": "illuminate/filesystem",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/filesystem.git",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda"
+ "reference": "a4ca4a9c2f969ec227748ab334693144995ba0ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/filesystem/zipball/e0ee832f625fbfadb816a972655b1a66af1a5bda",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda",
+ "url": "https://api.github.com/repos/illuminate/filesystem/zipball/a4ca4a9c2f969ec227748ab334693144995ba0ce",
+ "reference": "a4ca4a9c2f969ec227748ab334693144995ba0ce",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4",
- "symfony/finder": "~3.2"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/finder": "~4.0"
},
"suggest": {
"league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).",
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).",
- "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0)."
+ "league/flysystem-cached-adapter": "Required to use the Flysystem cache (~1.0).",
+ "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).",
+ "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (~1.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Filesystem package.",
"homepage": "https://laravel.com",
- "time": "2017-05-18 14:37:58"
+ "time": "2018-05-02 16:10:37"
},
{
"name": "illuminate/support",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d"
+ "reference": "6e84d4140310246ace38fdb0909da5b2fb22eadf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/support/zipball/a42393b56d0ec75f55e760f2a47bcf85a17a278d",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d",
+ "url": "https://api.github.com/repos/illuminate/support/zipball/6e84d4140310246ace38fdb0909da5b2fb22eadf",
+ "reference": "6e84d4140310246ace38fdb0909da5b2fb22eadf",
"shasum": ""
},
"require": {
- "doctrine/inflector": "~1.0",
+ "doctrine/inflector": "~1.1",
"ext-mbstring": "*",
- "illuminate/contracts": "5.4.*",
- "paragonie/random_compat": "~1.4|~2.0",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "nesbot/carbon": "^1.24.1",
+ "php": "^7.1.3"
},
- "replace": {
- "tightenco/collect": "self.version"
+ "conflict": {
+ "tightenco/collect": "<5.5.33"
},
"suggest": {
- "illuminate/filesystem": "Required to use the composer class (5.2.*).",
- "symfony/process": "Required to use the composer class (~3.2).",
- "symfony/var-dumper": "Required to use the dd function (~3.2)."
+ "illuminate/filesystem": "Required to use the composer class (5.6.*).",
+ "symfony/process": "Required to use the composer class (~4.0).",
+ "symfony/var-dumper": "Required to use the dd function (~4.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
- "time": "2017-06-15 12:35:32"
+ "time": "2018-05-07 14:12:37"
},
{
"name": "illuminate/view",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/view.git",
- "reference": "423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75"
+ "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/view/zipball/423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75",
- "reference": "423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75",
+ "url": "https://api.github.com/repos/illuminate/view/zipball/54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
+ "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
"shasum": ""
},
"require": {
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/events": "5.4.*",
- "illuminate/filesystem": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4",
- "symfony/debug": "~3.2"
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/events": "5.6.*",
+ "illuminate/filesystem": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/debug": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate View package.",
"homepage": "https://laravel.com",
- "time": "2017-06-07 13:32:57"
+ "time": "2018-04-03 12:56:35"
},
{
"name": "log1x/blade-svg-sage",
"homepage": "https://github.com/log1x/blade-svg-sage",
"time": "2018-02-06 19:18:31"
},
+ {
+ "name": "nesbot/carbon",
+ "version": "1.27.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/briannesbitt/Carbon.git",
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9",
+ "symfony/translation": "~2.6 || ~3.0 || ~4.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "~2",
+ "phpunit/phpunit": "^4.8.35 || ^5.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "http://nesbot.com"
+ }
+ ],
+ "description": "A simple API extension for DateTime.",
+ "homepage": "http://carbon.nesbot.com",
+ "keywords": [
+ "date",
+ "datetime",
+ "time"
+ ],
+ "time": "2018-04-23 09:02:57"
+ },
{
"name": "nothingworks/blade-svg",
"version": "v0.2.2",
"time": "2017-08-13 20:55:40"
},
{
- "name": "paragonie/random_compat",
- "version": "v2.0.10",
+ "name": "psr/container",
+ "version": "1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/paragonie/random_compat.git",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
- "php": ">=5.2.0"
- },
- "require-dev": {
- "phpunit/phpunit": "4.*|5.*"
- },
- "suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ "php": ">=5.3.0"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
"autoload": {
- "files": [
- "lib/random.php"
- ]
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
}
],
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
"keywords": [
- "csprng",
- "pseudorandom",
- "random"
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
],
- "time": "2017-03-13 16:27:32"
+ "time": "2017-02-14 16:28:37"
},
{
"name": "psr/log",
],
"time": "2016-10-10 12:19:37"
},
+ {
+ "name": "psr/simple-cache",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "time": "2017-10-23 01:57:42"
+ },
{
"name": "roots/sage-lib",
- "version": "9.0.0-beta.4",
+ "version": "9.0.1",
"source": {
"type": "git",
"url": "https://github.com/roots/sage-lib.git",
- "reference": "71ed6e54e831fd1ced5bae028f0515d277e8c1c1"
+ "reference": "36573cd93b8109633c953e3f05b9f7d654bad885"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/roots/sage-lib/zipball/71ed6e54e831fd1ced5bae028f0515d277e8c1c1",
- "reference": "71ed6e54e831fd1ced5bae028f0515d277e8c1c1",
+ "url": "https://api.github.com/repos/roots/sage-lib/zipball/36573cd93b8109633c953e3f05b9f7d654bad885",
+ "reference": "36573cd93b8109633c953e3f05b9f7d654bad885",
"shasum": ""
},
"require": {
"composer/installers": "~1.0",
- "illuminate/config": "~5.4",
- "illuminate/view": "~5.4",
+ "illuminate/config": "~5.6",
+ "illuminate/view": "~5.6",
"php": ">=7"
},
"require-dev": {
"keywords": [
"wordpress"
],
- "time": "2017-08-11 23:38:23"
+ "time": "2018-04-25 17:24:31"
},
{
"name": "soberwp/controller",
},
{
"name": "symfony/debug",
- "version": "v3.3.6",
+ "version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13"
+ "reference": "e1d57cdb357e5b10f5fdacbb0b86689c0a435e6e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/e1d57cdb357e5b10f5fdacbb0b86689c0a435e6e",
+ "reference": "e1d57cdb357e5b10f5fdacbb0b86689c0a435e6e",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
+ "php": "^7.1.3",
"psr/log": "~1.0"
},
"conflict": {
- "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ "symfony/http-kernel": "<3.4"
},
"require-dev": {
- "symfony/http-kernel": "~2.8|~3.0"
+ "symfony/http-kernel": "~3.4|~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2017-07-28 15:27:31"
+ "time": "2018-04-30 16:59:37"
},
{
"name": "symfony/finder",
- "version": "v3.3.6",
+ "version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4"
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2017-06-01 21:01:25"
+ "time": "2018-04-04 05:10:37"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "3296adf6a6454a050679cde90f95350ad604b171"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171",
+ "reference": "3296adf6a6454a050679cde90f95350ad604b171",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2018-04-26 10:06:28"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v4.0.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "ad3abf08eb3450491d8d76513100ef58194cd13e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/ad3abf08eb3450491d8d76513100ef58194cd13e",
+ "reference": "ad3abf08eb3450491d8d76513100ef58194cd13e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/config": "<3.4",
+ "symfony/dependency-injection": "<3.4",
+ "symfony/yaml": "<3.4"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/finder": "~2.8|~3.0|~4.0",
+ "symfony/intl": "~3.4|~4.0",
+ "symfony/yaml": "~3.4|~4.0"
+ },
+ "suggest": {
+ "psr/log-implementation": "To use logging capability in translator",
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Translation Component",
+ "homepage": "https://symfony.com",
+ "time": "2018-04-30 01:23:47"
},
{
"name": "symfony/yaml",
- "version": "v3.3.6",
+ "version": "v3.4.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed"
+ "reference": "033cfa61ef06ee0847e056e530201842b6e926c3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed",
- "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/033cfa61ef06ee0847e056e530201842b6e926c3",
+ "reference": "033cfa61ef06ee0847e056e530201842b6e926c3",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "conflict": {
+ "symfony/console": "<3.4"
},
"require-dev": {
- "symfony/console": "~2.8|~3.0"
+ "symfony/console": "~3.4|~4.0"
},
"suggest": {
"symfony/console": "For validating YAML files using the lint command"
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "3.4-dev"
}
},
"autoload": {
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2017-07-23 12:43:26"
+ "time": "2018-04-08 08:21:29"
},
{
"name": "wikimedia/relpath",
"packages-dev": [
{
"name": "illuminate/console",
- "version": "v5.4.27",
+ "version": "v5.6.21",
"source": {
"type": "git",
"url": "https://github.com/illuminate/console.git",
- "reference": "bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e"
+ "reference": "80fda6b3fddc07e81351260fa21e92496fc13b7e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/console/zipball/bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e",
- "reference": "bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e",
+ "url": "https://api.github.com/repos/illuminate/console/zipball/80fda6b3fddc07e81351260fa21e92496fc13b7e",
+ "reference": "80fda6b3fddc07e81351260fa21e92496fc13b7e",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "nesbot/carbon": "~1.20",
- "php": ">=5.6.4",
- "symfony/console": "~3.2"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/console": "~4.0"
},
"suggest": {
+ "dragonmantank/cron-expression": "Required to use scheduling component (~2.0).",
"guzzlehttp/guzzle": "Required to use the ping methods on schedules (~6.0).",
- "mtdowling/cron-expression": "Required to use scheduling component (~1.0).",
- "symfony/process": "Required to use scheduling component (~3.2)."
+ "symfony/process": "Required to use scheduling component (~4.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Console package.",
"homepage": "https://laravel.com",
- "time": "2017-06-10 13:11:18"
- },
- {
- "name": "nesbot/carbon",
- "version": "1.22.1",
- "source": {
- "type": "git",
- "url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc",
- "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0",
- "symfony/translation": "~2.6 || ~3.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "~2",
- "phpunit/phpunit": "~4.0 || ~5.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.23-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Carbon\\": "src/Carbon/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Brian Nesbitt",
- "email": "brian@nesbot.com",
- "homepage": "http://nesbot.com"
- }
- ],
- "description": "A simple API extension for DateTime.",
- "homepage": "http://carbon.nesbot.com",
- "keywords": [
- "date",
- "datetime",
- "time"
- ],
- "time": "2017-01-16 07:55:07"
+ "time": "2018-05-02 14:47:56"
},
{
"name": "roots/sage-installer",
- "version": "1.3.1",
+ "version": "1.3.6",
"source": {
"type": "git",
"url": "https://github.com/roots/sage-installer.git",
- "reference": "dca019cfa6f1f2cb2e155dfc6574829b80c689b7"
+ "reference": "e811ab937a36b321ea88ec6000ab3d5019b8f2b1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/roots/sage-installer/zipball/dca019cfa6f1f2cb2e155dfc6574829b80c689b7",
- "reference": "dca019cfa6f1f2cb2e155dfc6574829b80c689b7",
+ "url": "https://api.github.com/repos/roots/sage-installer/zipball/e811ab937a36b321ea88ec6000ab3d5019b8f2b1",
+ "reference": "e811ab937a36b321ea88ec6000ab3d5019b8f2b1",
"shasum": ""
},
"require": {
- "illuminate/console": "~5.4",
- "illuminate/filesystem": "~5.4",
+ "illuminate/console": "~5.6",
+ "illuminate/filesystem": "~5.6",
"symfony/process": "~3.3"
},
"require-dev": {
"homepage": "https://github.com/qwp6t"
}
],
- "description": "Sage installer.",
+ "description": "Sage starter theme installer",
"keywords": [
- "FontAwesome",
"bootstrap",
"foundation",
"sage",
"theme",
"wordpress"
],
- "time": "2017-08-12 00:16:45"
+ "time": "2018-04-25 17:45:56"
},
{
"name": "squizlabs/php_codesniffer",
},
{
"name": "symfony/console",
- "version": "v3.3.6",
+ "version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "b0878233cb5c4391347e5495089c7af11b8e6201"
+ "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/b0878233cb5c4391347e5495089c7af11b8e6201",
- "reference": "b0878233cb5c4391347e5495089c7af11b8e6201",
+ "url": "https://api.github.com/repos/symfony/console/zipball/3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
+ "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
- "symfony/debug": "~2.8|~3.0",
+ "php": "^7.1.3",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "symfony/dependency-injection": "<3.3"
+ "symfony/dependency-injection": "<3.4",
+ "symfony/process": "<3.3"
},
"require-dev": {
"psr/log": "~1.0",
- "symfony/config": "~3.3",
- "symfony/dependency-injection": "~3.3",
- "symfony/event-dispatcher": "~2.8|~3.0",
- "symfony/filesystem": "~2.8|~3.0",
- "symfony/http-kernel": "~2.8|~3.0",
- "symfony/process": "~2.8|~3.0"
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/event-dispatcher": "~3.4|~4.0",
+ "symfony/lock": "~3.4|~4.0",
+ "symfony/process": "~3.4|~4.0"
},
"suggest": {
- "psr/log": "For using the console logger",
+ "psr/log-implementation": "For using the console logger",
"symfony/event-dispatcher": "",
- "symfony/filesystem": "",
+ "symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2017-07-29 21:27:59"
- },
- {
- "name": "symfony/polyfill-mbstring",
- "version": "v1.5.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
- "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.5-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for the Mbstring extension",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "mbstring",
- "polyfill",
- "portable",
- "shim"
- ],
- "time": "2017-06-14 15:44:48"
+ "time": "2018-04-30 01:23:47"
},
{
"name": "symfony/process",
- "version": "v3.3.6",
+ "version": "v3.4.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a"
+ "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a",
+ "url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b",
+ "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "3.4-dev"
}
},
"autoload": {
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2017-07-13 13:05:09"
- },
- {
- "name": "symfony/translation",
- "version": "v3.3.6",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/translation.git",
- "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
- "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
- "shasum": ""
- },
- "require": {
- "php": ">=5.5.9",
- "symfony/polyfill-mbstring": "~1.0"
- },
- "conflict": {
- "symfony/config": "<2.8",
- "symfony/yaml": "<3.3"
- },
- "require-dev": {
- "psr/log": "~1.0",
- "symfony/config": "~2.8|~3.0",
- "symfony/intl": "^2.8.18|^3.2.5",
- "symfony/yaml": "~3.3"
- },
- "suggest": {
- "psr/log": "To use logging capability in translator",
- "symfony/config": "",
- "symfony/yaml": ""
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.3-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Translation\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Translation Component",
- "homepage": "https://symfony.com",
- "time": "2017-06-24 16:45:30"
+ "time": "2018-04-03 05:22:50"
}
],
"aliases": [],
li:not(:last-of-type)
constrain(margin-right, 1.25vw)
- img
+ svg
display: inline-block
width: 50px
height: auto
+ *
+ transition: all 0.1s ease-out
+
+ &:hover
+ *
+ fill: $colors.light-blue
&-signup
a
font-size: 11px
padding: r(40px)
padding-bottom: 0
+
+ a
+ color: #fff
<div class="footer-col footer-social">
<h3><?php _e('Follow Us', 'physioassist') ?></h3>
<ul class="footer-social-icons">
- <li><a href="#"><img src="@asset('images/icons/facebook.svg')" alt="Facebook"></a></li>
- <li><a href="#"><img src="@asset('images/icons/twitter.svg')" alt="Twitter"></a></li>
- <li><a href="#"><img src="@asset('images/icons/linkedin.svg')" alt="LinkedIn"></a></li>
+ <li><a href="#">@svg('icons/facebook')</a></li>
+ <li><a href="#">@svg('icons/twitter')</a></li>
+ <li><a href="#">@svg('icons/linkedin')</a></li>
</ul>
</div>
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit42eb17074963c60ab53fe9b8f4e9f075::getLoader();
+return ComposerAutoloaderInit37569206a6c3ede43e64eb047cb7f858::getLoader();
private function postType(\WP_Query $query)
{
$type = $query->get('post_type');
- is_array($type) and $type = reset($post_type);
+ is_array($type) and $type = reset($type);
$object = get_post_type_object($type);
(is_object($object) && $object->has_archive) or $type = '';
$baseDir = dirname($vendorDir);
return array(
- '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
- '72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+ '72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'4d945db823e5f6ca6dd83ad1f5fbcc43' => $vendorDir . '/wikimedia/relpath/src/RelPath/RelPath.php',
'6513700b70192b7dfd0e5e9fc8082cf3' => $vendorDir . '/wikimedia/relpath/src/Wikimedia/RelPath.php',
'7840a5c52edd823fb593e3c5547a8fbf' => $vendorDir . '/nothingworks/blade-svg/src/helpers.php',
'Sober\\Controller\\' => array($vendorDir . '/soberwp/controller/src'),
'Roots\\Sage\\Installer\\' => array($vendorDir . '/roots/sage-installer/src'),
'Roots\\Sage\\' => array($vendorDir . '/roots/sage-lib'),
+ 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
+ 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Noodlehaus\\' => array($vendorDir . '/hassankhan/config/src'),
'Illuminate\\View\\' => array($vendorDir . '/illuminate/view'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/support'),
'Illuminate\\Config\\' => array($vendorDir . '/illuminate/config'),
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'),
'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
- 'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
'Brain\\Hierarchy\\' => array($vendorDir . '/brain/hierarchy/src'),
'BladeSvg\\' => array($vendorDir . '/nothingworks/blade-svg/src'),
'App\\' => array($baseDir . '/app'),
+ '' => array($vendorDir . '/nesbot/carbon/src'),
);
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit42eb17074963c60ab53fe9b8f4e9f075
+class ComposerAutoloaderInit37569206a6c3ede43e64eb047cb7f858
{
private static $loader;
return self::$loader;
}
- spl_autoload_register(array('ComposerAutoloaderInit42eb17074963c60ab53fe9b8f4e9f075', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit37569206a6c3ede43e64eb047cb7f858', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInit42eb17074963c60ab53fe9b8f4e9f075', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit37569206a6c3ede43e64eb047cb7f858', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
- call_user_func(\Composer\Autoload\ComposerStaticInit42eb17074963c60ab53fe9b8f4e9f075::getInitializer($loader));
+ call_user_func(\Composer\Autoload\ComposerStaticInit37569206a6c3ede43e64eb047cb7f858::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->register(true);
if ($useStaticLoader) {
- $includeFiles = Composer\Autoload\ComposerStaticInit42eb17074963c60ab53fe9b8f4e9f075::$files;
+ $includeFiles = Composer\Autoload\ComposerStaticInit37569206a6c3ede43e64eb047cb7f858::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
- composerRequire42eb17074963c60ab53fe9b8f4e9f075($fileIdentifier, $file);
+ composerRequire37569206a6c3ede43e64eb047cb7f858($fileIdentifier, $file);
}
return $loader;
}
}
-function composerRequire42eb17074963c60ab53fe9b8f4e9f075($fileIdentifier, $file)
+function composerRequire37569206a6c3ede43e64eb047cb7f858($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
namespace Composer\Autoload;
-class ComposerStaticInit42eb17074963c60ab53fe9b8f4e9f075
+class ComposerStaticInit37569206a6c3ede43e64eb047cb7f858
{
public static $files = array (
- '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
- '72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+ '72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'4d945db823e5f6ca6dd83ad1f5fbcc43' => __DIR__ . '/..' . '/wikimedia/relpath/src/RelPath/RelPath.php',
'6513700b70192b7dfd0e5e9fc8082cf3' => __DIR__ . '/..' . '/wikimedia/relpath/src/Wikimedia/RelPath.php',
'7840a5c52edd823fb593e3c5547a8fbf' => __DIR__ . '/..' . '/nothingworks/blade-svg/src/helpers.php',
),
'P' =>
array (
+ 'Psr\\SimpleCache\\' => 16,
'Psr\\Log\\' => 8,
+ 'Psr\\Container\\' => 14,
),
'N' =>
array (
'C' =>
array (
'Composer\\Installers\\' => 20,
- 'Carbon\\' => 7,
),
'B' =>
array (
array (
0 => __DIR__ . '/..' . '/roots/sage-lib',
),
+ 'Psr\\SimpleCache\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/simple-cache/src',
+ ),
'Psr\\Log\\' =>
array (
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
),
+ 'Psr\\Container\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/container/src',
+ ),
'Noodlehaus\\' =>
array (
0 => __DIR__ . '/..' . '/hassankhan/config/src',
array (
0 => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers',
),
- 'Carbon\\' =>
- array (
- 0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
- ),
'Brain\\Hierarchy\\' =>
array (
0 => __DIR__ . '/..' . '/brain/hierarchy/src',
),
);
+ public static $fallbackDirsPsr4 = array (
+ 0 => __DIR__ . '/..' . '/nesbot/carbon/src',
+ );
+
public static $classMap = array (
'Generic_Sniffs_Arrays_DisallowLongArraySyntaxSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php',
'Generic_Sniffs_Arrays_DisallowShortArraySyntaxSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php',
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInit42eb17074963c60ab53fe9b8f4e9f075::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInit42eb17074963c60ab53fe9b8f4e9f075::$prefixDirsPsr4;
- $loader->classMap = ComposerStaticInit42eb17074963c60ab53fe9b8f4e9f075::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInit37569206a6c3ede43e64eb047cb7f858::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit37569206a6c3ede43e64eb047cb7f858::$prefixDirsPsr4;
+ $loader->fallbackDirsPsr4 = ComposerStaticInit37569206a6c3ede43e64eb047cb7f858::$fallbackDirsPsr4;
+ $loader->classMap = ComposerStaticInit37569206a6c3ede43e64eb047cb7f858::$classMap;
}, null, ClassLoader::class);
}
[
{
"name": "composer/installers",
- "version": "v1.4.0",
- "version_normalized": "1.4.0.0",
+ "version": "v1.5.0",
+ "version_normalized": "1.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
- "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b"
+ "reference": "049797d727261bf27f2690430d935067710049c2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/installers/zipball/9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b",
- "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b",
+ "url": "https://api.github.com/repos/composer/installers/zipball/049797d727261bf27f2690430d935067710049c2",
+ "reference": "049797d727261bf27f2690430d935067710049c2",
"shasum": ""
},
"require": {
},
"require-dev": {
"composer/composer": "1.0.*@dev",
- "phpunit/phpunit": "4.1.*"
+ "phpunit/phpunit": "^4.8.36"
},
- "time": "2017-08-09 07:53:48",
+ "time": "2017-12-29 09:13:20",
"type": "composer-plugin",
"extra": {
"class": "Composer\\Installers\\Plugin",
"lavalite",
"lithium",
"magento",
+ "majima",
"mako",
"mediawiki",
"modulework",
+ "modx",
"moodle",
"osclass",
"phpbb",
"piwik",
"ppi",
"puppet",
+ "pxcms",
"reindex",
"roundcube",
"shopware",
]
},
{
- "name": "paragonie/random_compat",
- "version": "v2.0.10",
- "version_normalized": "2.0.10.0",
+ "name": "brain/hierarchy",
+ "version": "2.3.1",
+ "version_normalized": "2.3.1.0",
"source": {
"type": "git",
- "url": "https://github.com/paragonie/random_compat.git",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
+ "url": "https://github.com/Brain-WP/Hierarchy.git",
+ "reference": "239f9bbe49ff6ad1199bbcad308d2c7977bee25a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
+ "url": "https://api.github.com/repos/Brain-WP/Hierarchy/zipball/239f9bbe49ff6ad1199bbcad308d2c7977bee25a",
+ "reference": "239f9bbe49ff6ad1199bbcad308d2c7977bee25a",
"shasum": ""
},
"require": {
- "php": ">=5.2.0"
+ "php": ">=5.5"
},
"require-dev": {
- "phpunit/phpunit": "4.*|5.*"
+ "antecedent/patchwork": "~1.3.0",
+ "brain/monkey": "~1.2",
+ "gmazzap/andrew": "~1.0",
+ "mockery/mockery": "0.9.3",
+ "phpunit/phpunit": "~4.8",
+ "symfony/finder": "~2.7.0"
},
"suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ "symfony/finder": "Allows loading of templates using Symfony finder component."
},
- "time": "2017-03-13 16:27:32",
+ "time": "2017-12-28 17:16:07",
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev",
+ "dev-dev": "2.0.x-dev"
+ }
+ },
"installation-source": "dist",
"autoload": {
- "files": [
- "lib/random.php"
- ]
+ "psr-4": {
+ "Brain\\Hierarchy\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
+ "name": "Giuseppe Mazzapica",
+ "email": "giuseppe.mazzapica@gmail.com"
}
],
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "description": "No-dependencies package that embodies WordPress template hierarchy",
"keywords": [
- "csprng",
- "pseudorandom",
- "random"
+ "wordpress"
]
},
{
- "name": "illuminate/contracts",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "name": "symfony/yaml",
+ "version": "v3.4.9",
+ "version_normalized": "3.4.9.0",
"source": {
"type": "git",
- "url": "https://github.com/illuminate/contracts.git",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0"
+ "url": "https://github.com/symfony/yaml.git",
+ "reference": "033cfa61ef06ee0847e056e530201842b6e926c3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/contracts/zipball/31f0193eb14aa3ee07841dc254081425616e79f0",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/033cfa61ef06ee0847e056e530201842b6e926c3",
+ "reference": "033cfa61ef06ee0847e056e530201842b6e926c3",
"shasum": ""
},
"require": {
- "php": ">=5.6.4"
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "conflict": {
+ "symfony/console": "<3.4"
+ },
+ "require-dev": {
+ "symfony/console": "~3.4|~4.0"
+ },
+ "suggest": {
+ "symfony/console": "For validating YAML files using the lint command"
},
- "time": "2017-04-19 20:17:43",
+ "time": "2018-04-08 08:21:29",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "3.4-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Illuminate\\Contracts\\": ""
- }
+ "Symfony\\Component\\Yaml\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "The Illuminate Contracts package.",
- "homepage": "https://laravel.com"
+ "description": "Symfony Yaml Component",
+ "homepage": "https://symfony.com"
},
{
- "name": "doctrine/inflector",
- "version": "v1.2.0",
- "version_normalized": "1.2.0.0",
+ "name": "hassankhan/config",
+ "version": "0.10.0",
+ "version_normalized": "0.10.0.0",
"source": {
"type": "git",
- "url": "https://github.com/doctrine/inflector.git",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462"
+ "url": "https://github.com/hassankhan/config.git",
+ "reference": "06ac500348af033f1a2e44dc357ca86282626d4a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462",
+ "url": "https://api.github.com/repos/hassankhan/config/zipball/06ac500348af033f1a2e44dc357ca86282626d4a",
+ "reference": "06ac500348af033f1a2e44dc357ca86282626d4a",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": ">=5.3.0"
},
"require-dev": {
- "phpunit/phpunit": "^6.2"
+ "phpunit/phpunit": "~4.0",
+ "scrutinizer/ocular": "~1.1",
+ "squizlabs/php_codesniffer": "~2.2"
},
- "time": "2017-07-22 12:18:28",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.2.x-dev"
- }
+ "suggest": {
+ "symfony/yaml": "~2.5"
},
+ "time": "2016-02-11 16:21:17",
+ "type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector"
+ "Noodlehaus\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Roman Borschel",
- "email": "roman@code-factory.org"
- },
- {
- "name": "Benjamin Eberlei",
- "email": "kontakt@beberlei.de"
- },
- {
- "name": "Guilherme Blanco",
- "email": "guilhermeblanco@gmail.com"
- },
- {
- "name": "Jonathan Wage",
- "email": "jonwage@gmail.com"
- },
- {
- "name": "Johannes Schmitt",
- "email": "schmittjoh@gmail.com"
+ "name": "Hassan Khan",
+ "homepage": "http://hassankhan.me/",
+ "role": "Developer"
}
],
- "description": "Common String Manipulations with regard to casing and singular/plural rules.",
- "homepage": "http://www.doctrine-project.org",
+ "description": "Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files",
+ "homepage": "http://hassankhan.me/config/",
"keywords": [
- "inflection",
- "pluralize",
- "singularize",
- "string"
+ "config",
+ "configuration",
+ "ini",
+ "json",
+ "microphp",
+ "unframework",
+ "xml",
+ "yaml",
+ "yml"
]
},
{
- "name": "illuminate/support",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "name": "soberwp/controller",
+ "version": "9.0.0-beta.4",
+ "version_normalized": "9.0.0.0-beta4",
"source": {
"type": "git",
- "url": "https://github.com/illuminate/support.git",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d"
+ "url": "https://github.com/soberwp/controller.git",
+ "reference": "2b6c8450f4a3100b16bfc482c825d89422b6adc6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/support/zipball/a42393b56d0ec75f55e760f2a47bcf85a17a278d",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d",
+ "url": "https://api.github.com/repos/soberwp/controller/zipball/2b6c8450f4a3100b16bfc482c825d89422b6adc6",
+ "reference": "2b6c8450f4a3100b16bfc482c825d89422b6adc6",
"shasum": ""
},
"require": {
- "doctrine/inflector": "~1.0",
- "ext-mbstring": "*",
- "illuminate/contracts": "5.4.*",
- "paragonie/random_compat": "~1.4|~2.0",
- "php": ">=5.6.4"
- },
- "replace": {
- "tightenco/collect": "self.version"
- },
- "suggest": {
- "illuminate/filesystem": "Required to use the composer class (5.2.*).",
- "symfony/process": "Required to use the composer class (~3.2).",
- "symfony/var-dumper": "Required to use the dd function (~3.2)."
+ "brain/hierarchy": "^2.3",
+ "composer/installers": "~1.0",
+ "hassankhan/config": "^0.10.0",
+ "php": ">=5.6.0",
+ "symfony/yaml": "^3.2"
},
- "time": "2017-06-15 12:35:32",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "5.4-dev"
- }
+ "require-dev": {
+ "squizlabs/php_codesniffer": "2.*"
},
+ "time": "2017-08-22 17:35:30",
+ "type": "package",
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Illuminate\\Support\\": ""
+ "Sober\\Controller\\": "src/",
+ "Sober\\Controller\\Module\\": "src/Module/"
},
"files": [
- "helpers.php"
+ "controller.php"
]
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
+ "name": "Darren Jacoby",
+ "email": "darren@jacoby.co.za",
+ "homepage": "https://github.com/darrenjacoby"
}
],
- "description": "The Illuminate Support package.",
- "homepage": "https://laravel.com"
+ "description": "WordPress package to enable a basic controller when using Blade with Sage 9",
+ "homepage": "https://github.com/soberwp",
+ "keywords": [
+ "wordpress"
+ ]
},
{
- "name": "illuminate/container",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.8.0",
+ "version_normalized": "1.8.0.0",
"source": {
"type": "git",
- "url": "https://github.com/illuminate/container.git",
- "reference": "c5b8a02a34a52c307f16922334c355c5eef725a6"
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "3296adf6a6454a050679cde90f95350ad604b171"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/container/zipball/c5b8a02a34a52c307f16922334c355c5eef725a6",
- "reference": "c5b8a02a34a52c307f16922334c355c5eef725a6",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171",
+ "reference": "3296adf6a6454a050679cde90f95350ad604b171",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "php": ">=5.6.4"
+ "php": ">=5.3.3"
},
- "time": "2017-05-24 14:15:53",
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "time": "2018-04-26 10:06:28",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "1.8-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Illuminate\\Container\\": ""
- }
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "The Illuminate Container package.",
- "homepage": "https://laravel.com"
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ]
},
{
- "name": "illuminate/events",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "name": "symfony/translation",
+ "version": "v4.0.9",
+ "version_normalized": "4.0.9.0",
"source": {
"type": "git",
- "url": "https://github.com/illuminate/events.git",
- "reference": "ebdca3b0305e9fc954afb9e422c4559482cd11e6"
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "ad3abf08eb3450491d8d76513100ef58194cd13e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/events/zipball/ebdca3b0305e9fc954afb9e422c4559482cd11e6",
- "reference": "ebdca3b0305e9fc954afb9e422c4559482cd11e6",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/ad3abf08eb3450491d8d76513100ef58194cd13e",
+ "reference": "ad3abf08eb3450491d8d76513100ef58194cd13e",
"shasum": ""
},
"require": {
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4"
+ "php": "^7.1.3",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/config": "<3.4",
+ "symfony/dependency-injection": "<3.4",
+ "symfony/yaml": "<3.4"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/finder": "~2.8|~3.0|~4.0",
+ "symfony/intl": "~3.4|~4.0",
+ "symfony/yaml": "~3.4|~4.0"
+ },
+ "suggest": {
+ "psr/log-implementation": "To use logging capability in translator",
+ "symfony/config": "",
+ "symfony/yaml": ""
},
- "time": "2017-05-02 12:57:00",
+ "time": "2018-04-30 01:23:47",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "4.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Illuminate\\Events\\": ""
- }
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "The Illuminate Events package.",
- "homepage": "https://laravel.com"
+ "description": "Symfony Translation Component",
+ "homepage": "https://symfony.com"
},
{
- "name": "psr/log",
- "version": "1.0.2",
- "version_normalized": "1.0.2.0",
+ "name": "nesbot/carbon",
+ "version": "1.27.0",
+ "version_normalized": "1.27.0.0",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/log.git",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ "url": "https://github.com/briannesbitt/Carbon.git",
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": ">=5.3.9",
+ "symfony/translation": "~2.6 || ~3.0 || ~4.0"
},
- "time": "2016-10-10 12:19:37",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "~2",
+ "phpunit/phpunit": "^4.8.35 || ^5.7"
},
+ "time": "2018-04-23 09:02:57",
+ "type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Psr\\Log\\": "Psr/Log/"
+ "": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "http://nesbot.com"
}
],
- "description": "Common interface for logging libraries",
- "homepage": "https://github.com/php-fig/log",
+ "description": "A simple API extension for DateTime.",
+ "homepage": "http://carbon.nesbot.com",
"keywords": [
- "log",
- "psr",
- "psr-3"
+ "date",
+ "datetime",
+ "time"
]
},
{
- "name": "symfony/debug",
- "version": "v3.3.6",
- "version_normalized": "3.3.6.0",
+ "name": "psr/simple-cache",
+ "version": "1.0.1",
+ "version_normalized": "1.0.1.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/debug.git",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13"
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
- "psr/log": "~1.0"
- },
- "conflict": {
- "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
- },
- "require-dev": {
- "symfony/http-kernel": "~2.8|~3.0"
+ "php": ">=5.3.0"
},
- "time": "2017-07-28 15:27:31",
+ "time": "2017-10-23 01:57:42",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Debug\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Psr\\SimpleCache\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
}
],
- "description": "Symfony Debug Component",
- "homepage": "https://symfony.com"
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ]
},
{
- "name": "symfony/finder",
- "version": "v3.3.6",
- "version_normalized": "3.3.6.0",
+ "name": "psr/container",
+ "version": "1.0.0",
+ "version_normalized": "1.0.0.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/finder.git",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4"
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": ">=5.3.0"
},
- "time": "2017-06-01 21:01:25",
+ "time": "2017-02-14 16:28:37",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Finder\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Psr\\Container\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
}
],
- "description": "Symfony Finder Component",
- "homepage": "https://symfony.com"
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ]
},
{
- "name": "illuminate/filesystem",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "name": "illuminate/contracts",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
"source": {
"type": "git",
- "url": "https://github.com/illuminate/filesystem.git",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda"
+ "url": "https://github.com/illuminate/contracts.git",
+ "reference": "6a11fbccbc7da16a85fcd1d4b08e51b5658de0d4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/filesystem/zipball/e0ee832f625fbfadb816a972655b1a66af1a5bda",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda",
+ "url": "https://api.github.com/repos/illuminate/contracts/zipball/6a11fbccbc7da16a85fcd1d4b08e51b5658de0d4",
+ "reference": "6a11fbccbc7da16a85fcd1d4b08e51b5658de0d4",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4",
- "symfony/finder": "~3.2"
+ "php": "^7.1.3",
+ "psr/container": "~1.0",
+ "psr/simple-cache": "~1.0"
},
- "suggest": {
- "league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).",
- "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).",
- "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0)."
- },
- "time": "2017-05-18 14:37:58",
+ "time": "2018-05-08 13:22:33",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Illuminate\\Filesystem\\": ""
+ "Illuminate\\Contracts\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"email": "taylor@laravel.com"
}
],
- "description": "The Illuminate Filesystem package.",
+ "description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com"
},
{
- "name": "illuminate/view",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "name": "doctrine/inflector",
+ "version": "v1.3.0",
+ "version_normalized": "1.3.0.0",
"source": {
"type": "git",
- "url": "https://github.com/illuminate/view.git",
- "reference": "423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75"
+ "url": "https://github.com/doctrine/inflector.git",
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/view/zipball/423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75",
- "reference": "423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a",
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a",
"shasum": ""
},
"require": {
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/events": "5.4.*",
- "illuminate/filesystem": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4",
- "symfony/debug": "~3.2"
- },
- "time": "2017-06-07 13:32:57",
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.2"
+ },
+ "time": "2018-01-09 20:05:19",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "1.3.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Illuminate\\View\\": ""
+ "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Common String Manipulations with regard to casing and singular/plural rules.",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "inflection",
+ "pluralize",
+ "singularize",
+ "string"
+ ]
+ },
+ {
+ "name": "illuminate/support",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/illuminate/support.git",
+ "reference": "6e84d4140310246ace38fdb0909da5b2fb22eadf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/illuminate/support/zipball/6e84d4140310246ace38fdb0909da5b2fb22eadf",
+ "reference": "6e84d4140310246ace38fdb0909da5b2fb22eadf",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/inflector": "~1.1",
+ "ext-mbstring": "*",
+ "illuminate/contracts": "5.6.*",
+ "nesbot/carbon": "^1.24.1",
+ "php": "^7.1.3"
+ },
+ "conflict": {
+ "tightenco/collect": "<5.5.33"
+ },
+ "suggest": {
+ "illuminate/filesystem": "Required to use the composer class (5.6.*).",
+ "symfony/process": "Required to use the composer class (~4.0).",
+ "symfony/var-dumper": "Required to use the dd function (~4.0)."
+ },
+ "time": "2018-05-07 14:12:37",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.6-dev"
}
},
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Illuminate\\Support\\": ""
+ },
+ "files": [
+ "helpers.php"
+ ]
+ },
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
"email": "taylor@laravel.com"
}
],
- "description": "The Illuminate View package.",
+ "description": "The Illuminate Support package.",
"homepage": "https://laravel.com"
},
{
"name": "illuminate/config",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/config.git",
- "reference": "8fe700aa596bc623d347e4578041fbda7a44c3d9"
+ "reference": "e8158dff3189deed846c84c66c60fa68c21ee579"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/config/zipball/8fe700aa596bc623d347e4578041fbda7a44c3d9",
- "reference": "8fe700aa596bc623d347e4578041fbda7a44c3d9",
+ "url": "https://api.github.com/repos/illuminate/config/zipball/e8158dff3189deed846c84c66c60fa68c21ee579",
+ "reference": "e8158dff3189deed846c84c66c60fa68c21ee579",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3"
},
- "time": "2017-02-04 20:27:32",
+ "time": "2017-11-07 20:23:51",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"installation-source": "dist",
"homepage": "https://laravel.com"
},
{
- "name": "roots/sage-lib",
- "version": "9.0.0-beta.4",
- "version_normalized": "9.0.0.0-beta4",
+ "name": "psr/log",
+ "version": "1.0.2",
+ "version_normalized": "1.0.2.0",
"source": {
"type": "git",
- "url": "https://github.com/roots/sage-lib.git",
- "reference": "71ed6e54e831fd1ced5bae028f0515d277e8c1c1"
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/roots/sage-lib/zipball/71ed6e54e831fd1ced5bae028f0515d277e8c1c1",
- "reference": "71ed6e54e831fd1ced5bae028f0515d277e8c1c1",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
"require": {
- "composer/installers": "~1.0",
- "illuminate/config": "~5.4",
- "illuminate/view": "~5.4",
- "php": ">=7"
- },
- "require-dev": {
- "squizlabs/php_codesniffer": "~3.0"
+ "php": ">=5.3.0"
},
- "time": "2017-08-11 23:38:23",
+ "time": "2016-10-10 12:19:37",
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Roots\\Sage\\": ""
+ "Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Ben Word",
- "email": "ben@benword.com",
- "homepage": "https://github.com/retlehs"
- },
- {
- "name": "QWp6t",
- "email": "hi@qwp6t.me",
- "homepage": "https://github.com/qwp6t"
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
}
],
- "description": "Library files for Sage Starter Theme",
- "homepage": "https://roots.io/sage/",
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
"keywords": [
- "wordpress"
+ "log",
+ "psr",
+ "psr-3"
]
},
{
- "name": "symfony/yaml",
- "version": "v3.3.6",
- "version_normalized": "3.3.6.0",
+ "name": "symfony/debug",
+ "version": "v4.0.9",
+ "version_normalized": "4.0.9.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/yaml.git",
- "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed"
+ "url": "https://github.com/symfony/debug.git",
+ "reference": "e1d57cdb357e5b10f5fdacbb0b86689c0a435e6e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed",
- "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/e1d57cdb357e5b10f5fdacbb0b86689c0a435e6e",
+ "reference": "e1d57cdb357e5b10f5fdacbb0b86689c0a435e6e",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^7.1.3",
+ "psr/log": "~1.0"
},
- "require-dev": {
- "symfony/console": "~2.8|~3.0"
+ "conflict": {
+ "symfony/http-kernel": "<3.4"
},
- "suggest": {
- "symfony/console": "For validating YAML files using the lint command"
+ "require-dev": {
+ "symfony/http-kernel": "~3.4|~4.0"
},
- "time": "2017-07-23 12:43:26",
+ "time": "2018-04-30 16:59:37",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Yaml\\": ""
+ "Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
"/Tests/"
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony Yaml Component",
+ "description": "Symfony Debug Component",
"homepage": "https://symfony.com"
},
{
- "name": "hassankhan/config",
- "version": "0.10.0",
- "version_normalized": "0.10.0.0",
+ "name": "symfony/finder",
+ "version": "v4.0.9",
+ "version_normalized": "4.0.9.0",
"source": {
"type": "git",
- "url": "https://github.com/hassankhan/config.git",
- "reference": "06ac500348af033f1a2e44dc357ca86282626d4a"
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/hassankhan/config/zipball/06ac500348af033f1a2e44dc357ca86282626d4a",
- "reference": "06ac500348af033f1a2e44dc357ca86282626d4a",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.0",
- "scrutinizer/ocular": "~1.1",
- "squizlabs/php_codesniffer": "~2.2"
- },
- "suggest": {
- "symfony/yaml": "~2.5"
+ "php": "^7.1.3"
},
- "time": "2016-02-11 16:21:17",
+ "time": "2018-04-04 05:10:37",
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Noodlehaus\\": "src"
- }
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Hassan Khan",
- "homepage": "http://hassankhan.me/",
- "role": "Developer"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files",
- "homepage": "http://hassankhan.me/config/",
- "keywords": [
- "config",
- "configuration",
- "ini",
- "json",
- "microphp",
- "unframework",
- "xml",
- "yaml",
- "yml"
- ]
+ "description": "Symfony Finder Component",
+ "homepage": "https://symfony.com"
},
{
- "name": "brain/hierarchy",
- "version": "2.3.0",
- "version_normalized": "2.3.0.0",
+ "name": "illuminate/filesystem",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
"source": {
"type": "git",
- "url": "https://github.com/Brain-WP/Hierarchy.git",
- "reference": "adb52da233e586051a577ef5eabe2c537df785d5"
+ "url": "https://github.com/illuminate/filesystem.git",
+ "reference": "a4ca4a9c2f969ec227748ab334693144995ba0ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Brain-WP/Hierarchy/zipball/adb52da233e586051a577ef5eabe2c537df785d5",
- "reference": "adb52da233e586051a577ef5eabe2c537df785d5",
+ "url": "https://api.github.com/repos/illuminate/filesystem/zipball/a4ca4a9c2f969ec227748ab334693144995ba0ce",
+ "reference": "a4ca4a9c2f969ec227748ab334693144995ba0ce",
"shasum": ""
},
"require": {
- "php": ">=5.5"
- },
- "require-dev": {
- "antecedent/patchwork": "~1.3.0",
- "brain/monkey": "~1.2",
- "gmazzap/andrew": "~1.0",
- "mockery/mockery": "0.9.3",
- "phpunit/phpunit": "~4.8",
- "symfony/finder": "~2.7.0"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/finder": "~4.0"
},
"suggest": {
- "symfony/finder": "Allows loading of templates using Symfony finder component."
+ "league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).",
+ "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).",
+ "league/flysystem-cached-adapter": "Required to use the Flysystem cache (~1.0).",
+ "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).",
+ "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (~1.0)."
},
- "time": "2016-09-15 13:33:53",
+ "time": "2018-05-02 16:10:37",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2.x-dev",
- "dev-dev": "2.0.x-dev"
+ "dev-master": "5.6-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Brain\\Hierarchy\\": "src/"
+ "Illuminate\\Filesystem\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Giuseppe Mazzapica",
- "email": "giuseppe.mazzapica@gmail.com"
- }
- ],
- "description": "No-dependencies package that embodies WordPress template hierarchy",
- "keywords": [
- "wordpress"
- ]
- },
- {
- "name": "soberwp/controller",
- "version": "9.0.0-beta.4",
- "version_normalized": "9.0.0.0-beta4",
- "source": {
- "type": "git",
- "url": "https://github.com/soberwp/controller.git",
- "reference": "2b6c8450f4a3100b16bfc482c825d89422b6adc6"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/soberwp/controller/zipball/2b6c8450f4a3100b16bfc482c825d89422b6adc6",
- "reference": "2b6c8450f4a3100b16bfc482c825d89422b6adc6",
- "shasum": ""
- },
- "require": {
- "brain/hierarchy": "^2.3",
- "composer/installers": "~1.0",
- "hassankhan/config": "^0.10.0",
- "php": ">=5.6.0",
- "symfony/yaml": "^3.2"
- },
- "require-dev": {
- "squizlabs/php_codesniffer": "2.*"
- },
- "time": "2017-08-22 17:35:30",
- "type": "package",
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Sober\\Controller\\": "src/",
- "Sober\\Controller\\Module\\": "src/Module/"
- },
- "files": [
- "controller.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Darren Jacoby",
- "email": "darren@jacoby.co.za",
- "homepage": "https://github.com/darrenjacoby"
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
}
],
- "description": "WordPress package to enable a basic controller when using Blade with Sage 9",
- "homepage": "https://github.com/soberwp",
- "keywords": [
- "wordpress"
- ]
+ "description": "The Illuminate Filesystem package.",
+ "homepage": "https://laravel.com"
},
{
- "name": "symfony/polyfill-mbstring",
- "version": "v1.5.0",
- "version_normalized": "1.5.0.0",
+ "name": "illuminate/container",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803"
+ "url": "https://github.com/illuminate/container.git",
+ "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
- "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
+ "url": "https://api.github.com/repos/illuminate/container/zipball/4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
+ "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
+ "illuminate/contracts": "5.6.*",
+ "php": "^7.1.3",
+ "psr/container": "~1.0"
},
- "time": "2017-06-14 15:44:48",
+ "time": "2018-01-21 02:13:38",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.5-dev"
+ "dev-master": "5.6-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
+ "Illuminate\\Container\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
}
],
- "description": "Symfony polyfill for the Mbstring extension",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "mbstring",
- "polyfill",
- "portable",
- "shim"
- ]
+ "description": "The Illuminate Container package.",
+ "homepage": "https://laravel.com"
},
{
- "name": "symfony/translation",
- "version": "v3.3.6",
- "version_normalized": "3.3.6.0",
+ "name": "illuminate/events",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/translation.git",
- "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3"
+ "url": "https://github.com/illuminate/events.git",
+ "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
- "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
+ "url": "https://api.github.com/repos/illuminate/events/zipball/b6e73ed40478cef2ef98d5ddb27f333291606cea",
+ "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
- "symfony/polyfill-mbstring": "~1.0"
- },
- "conflict": {
- "symfony/config": "<2.8",
- "symfony/yaml": "<3.3"
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3"
},
- "require-dev": {
- "psr/log": "~1.0",
- "symfony/config": "~2.8|~3.0",
- "symfony/intl": "^2.8.18|^3.2.5",
- "symfony/yaml": "~3.3"
- },
- "suggest": {
- "psr/log": "To use logging capability in translator",
- "symfony/config": "",
- "symfony/yaml": ""
- },
- "time": "2017-06-24 16:45:30",
+ "time": "2018-02-26 19:00:55",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "5.6-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Translation\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Illuminate\\Events\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
}
],
- "description": "Symfony Translation Component",
- "homepage": "https://symfony.com"
+ "description": "The Illuminate Events package.",
+ "homepage": "https://laravel.com"
},
{
- "name": "nesbot/carbon",
- "version": "1.22.1",
- "version_normalized": "1.22.1.0",
+ "name": "illuminate/view",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
"source": {
"type": "git",
- "url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc"
+ "url": "https://github.com/illuminate/view.git",
+ "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc",
- "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc",
+ "url": "https://api.github.com/repos/illuminate/view/zipball/54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
+ "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
"shasum": ""
},
"require": {
- "php": ">=5.3.0",
- "symfony/translation": "~2.6 || ~3.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "~2",
- "phpunit/phpunit": "~4.0 || ~5.0"
- },
- "time": "2017-01-16 07:55:07",
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/events": "5.6.*",
+ "illuminate/filesystem": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/debug": "~4.0"
+ },
+ "time": "2018-04-03 12:56:35",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.23-dev"
+ "dev-master": "5.6-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Carbon\\": "src/Carbon/"
+ "Illuminate\\View\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Brian Nesbitt",
- "email": "brian@nesbot.com",
- "homepage": "http://nesbot.com"
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
}
],
- "description": "A simple API extension for DateTime.",
- "homepage": "http://carbon.nesbot.com",
- "keywords": [
- "date",
- "datetime",
- "time"
- ]
+ "description": "The Illuminate View package.",
+ "homepage": "https://laravel.com"
},
{
- "name": "symfony/process",
- "version": "v3.3.6",
- "version_normalized": "3.3.6.0",
+ "name": "roots/sage-lib",
+ "version": "9.0.1",
+ "version_normalized": "9.0.1.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/process.git",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a"
+ "url": "https://github.com/roots/sage-lib.git",
+ "reference": "36573cd93b8109633c953e3f05b9f7d654bad885"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a",
+ "url": "https://api.github.com/repos/roots/sage-lib/zipball/36573cd93b8109633c953e3f05b9f7d654bad885",
+ "reference": "36573cd93b8109633c953e3f05b9f7d654bad885",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "composer/installers": "~1.0",
+ "illuminate/config": "~5.6",
+ "illuminate/view": "~5.6",
+ "php": ">=7"
},
- "time": "2017-07-13 13:05:09",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.3-dev"
- }
+ "require-dev": {
+ "squizlabs/php_codesniffer": "~3.0"
},
+ "time": "2018-04-25 17:24:31",
+ "type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Process\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Roots\\Sage\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Ben Word",
+ "email": "ben@benword.com",
+ "homepage": "https://github.com/retlehs"
},
{
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "QWp6t",
+ "email": "hi@qwp6t.me",
+ "homepage": "https://github.com/qwp6t"
}
],
- "description": "Symfony Process Component",
- "homepage": "https://symfony.com"
+ "description": "Library files for Sage Starter Theme",
+ "homepage": "https://roots.io/sage/",
+ "keywords": [
+ "wordpress"
+ ]
},
{
- "name": "symfony/console",
- "version": "v3.3.6",
- "version_normalized": "3.3.6.0",
+ "name": "wikimedia/relpath",
+ "version": "2.1.1",
+ "version_normalized": "2.1.1.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/console.git",
- "reference": "b0878233cb5c4391347e5495089c7af11b8e6201"
+ "url": "https://github.com/wikimedia/RelPath.git",
+ "reference": "35e701ff16abf461bb8676a9d9177f86fa0b2c94"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/b0878233cb5c4391347e5495089c7af11b8e6201",
- "reference": "b0878233cb5c4391347e5495089c7af11b8e6201",
+ "url": "https://api.github.com/repos/wikimedia/RelPath/zipball/35e701ff16abf461bb8676a9d9177f86fa0b2c94",
+ "reference": "35e701ff16abf461bb8676a9d9177f86fa0b2c94",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
- "symfony/debug": "~2.8|~3.0",
- "symfony/polyfill-mbstring": "~1.0"
- },
- "conflict": {
- "symfony/dependency-injection": "<3.3"
+ "php": ">=5.5.9"
},
"require-dev": {
- "psr/log": "~1.0",
- "symfony/config": "~3.3",
- "symfony/dependency-injection": "~3.3",
- "symfony/event-dispatcher": "~2.8|~3.0",
- "symfony/filesystem": "~2.8|~3.0",
- "symfony/http-kernel": "~2.8|~3.0",
- "symfony/process": "~2.8|~3.0"
- },
- "suggest": {
- "psr/log": "For using the console logger",
- "symfony/event-dispatcher": "",
- "symfony/filesystem": "",
- "symfony/process": ""
+ "jakub-onderka/php-parallel-lint": "^0.9.0.0",
+ "mediawiki/mediawiki-codesniffer": "15.0.0",
+ "phpunit/phpunit": "^4.8.9.0"
},
- "time": "2017-07-29 21:27:59",
+ "time": "2018-01-18 21:23:40",
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.3-dev"
- }
- },
"installation-source": "dist",
"autoload": {
- "psr-4": {
- "Symfony\\Component\\Console\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
+ "files": [
+ "src/RelPath/RelPath.php",
+ "src/Wikimedia/RelPath.php"
]
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "Ori Livneh",
+ "email": "ori@wikimedia.org"
}
],
- "description": "Symfony Console Component",
- "homepage": "https://symfony.com"
+ "description": "Compute a relative filepath between two paths.",
+ "homepage": "https://www.mediawiki.org/wiki/RelPath"
},
{
- "name": "illuminate/console",
- "version": "v5.4.27",
- "version_normalized": "5.4.27.0",
+ "name": "nothingworks/blade-svg",
+ "version": "v0.2.2",
+ "version_normalized": "0.2.2.0",
"source": {
"type": "git",
- "url": "https://github.com/illuminate/console.git",
- "reference": "bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e"
+ "url": "https://github.com/adamwathan/blade-svg.git",
+ "reference": "fad56a6e5fb970e55b9745e547106ca09273fe24"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/console/zipball/bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e",
- "reference": "bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e",
+ "url": "https://api.github.com/repos/adamwathan/blade-svg/zipball/fad56a6e5fb970e55b9745e547106ca09273fe24",
+ "reference": "fad56a6e5fb970e55b9745e547106ca09273fe24",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "nesbot/carbon": "~1.20",
- "php": ">=5.6.4",
- "symfony/console": "~3.2"
+ "illuminate/filesystem": "^5.3",
+ "illuminate/support": "^5.3"
},
- "suggest": {
- "guzzlehttp/guzzle": "Required to use the ping methods on schedules (~6.0).",
- "mtdowling/cron-expression": "Required to use scheduling component (~1.0).",
- "symfony/process": "Required to use scheduling component (~3.2)."
+ "require-dev": {
+ "mockery/mockery": "^0.9.5",
+ "phpunit/phpunit": "^5.5"
},
- "time": "2017-06-10 13:11:18",
+ "time": "2017-08-13 20:55:40",
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "5.4-dev"
+ "laravel": {
+ "providers": [
+ "BladeSvg\\BladeSvgServiceProvider"
+ ]
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Illuminate\\Console\\": ""
- }
+ "BladeSvg\\": "src/"
+ },
+ "files": [
+ "src/helpers.php"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Taylor Otwell",
- "email": "taylor@laravel.com"
+ "name": "Adam Wathan",
+ "email": "adam.wathan@gmail.com"
}
- ],
- "description": "The Illuminate Console package.",
- "homepage": "https://laravel.com"
+ ]
},
{
- "name": "roots/sage-installer",
- "version": "1.3.1",
- "version_normalized": "1.3.1.0",
+ "name": "log1x/blade-svg-sage",
+ "version": "v1.0.6",
+ "version_normalized": "1.0.6.0",
"source": {
"type": "git",
- "url": "https://github.com/roots/sage-installer.git",
- "reference": "dca019cfa6f1f2cb2e155dfc6574829b80c689b7"
+ "url": "https://github.com/Log1x/blade-svg-sage.git",
+ "reference": "c41f1180d1eab3ea1040eb8bb2d02082bccc9c20"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/roots/sage-installer/zipball/dca019cfa6f1f2cb2e155dfc6574829b80c689b7",
- "reference": "dca019cfa6f1f2cb2e155dfc6574829b80c689b7",
+ "url": "https://api.github.com/repos/Log1x/blade-svg-sage/zipball/c41f1180d1eab3ea1040eb8bb2d02082bccc9c20",
+ "reference": "c41f1180d1eab3ea1040eb8bb2d02082bccc9c20",
"shasum": ""
},
"require": {
- "illuminate/console": "~5.4",
- "illuminate/filesystem": "~5.4",
- "symfony/process": "~3.3"
- },
- "require-dev": {
- "squizlabs/php_codesniffer": "~3.0"
+ "nothingworks/blade-svg": "^0.2.1",
+ "wikimedia/relpath": "^2.1"
},
- "time": "2017-08-12 00:16:45",
- "bin": [
- "bin/sage"
- ],
- "type": "library",
+ "time": "2018-02-06 19:18:31",
+ "type": "package",
"installation-source": "dist",
"autoload": {
- "psr-4": {
- "Roots\\Sage\\Installer\\": "src/"
- }
+ "files": [
+ "src/helpers.php",
+ "src/blade-svg-sage.php"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Ben Word",
- "email": "ben@benword.com",
- "homepage": "https://github.com/retlehs"
- },
- {
- "name": "QWp6t",
- "email": "hi@qwp6t.me",
- "homepage": "https://github.com/qwp6t"
+ "name": "Brandon Nifong",
+ "email": "brandon@tendency.me"
}
],
- "description": "Sage installer.",
- "keywords": [
- "FontAwesome",
- "bootstrap",
- "foundation",
- "sage",
- "tachyons",
- "theme",
- "wordpress"
- ]
+ "homepage": "https://github.com/log1x/blade-svg-sage"
},
{
"name": "squizlabs/php_codesniffer",
]
},
{
- "name": "wikimedia/relpath",
- "version": "2.1.1",
- "version_normalized": "2.1.1.0",
+ "name": "symfony/process",
+ "version": "v3.4.9",
+ "version_normalized": "3.4.9.0",
"source": {
"type": "git",
- "url": "https://github.com/wikimedia/RelPath.git",
- "reference": "35e701ff16abf461bb8676a9d9177f86fa0b2c94"
+ "url": "https://github.com/symfony/process.git",
+ "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/wikimedia/RelPath/zipball/35e701ff16abf461bb8676a9d9177f86fa0b2c94",
- "reference": "35e701ff16abf461bb8676a9d9177f86fa0b2c94",
+ "url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b",
+ "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
- },
- "require-dev": {
- "jakub-onderka/php-parallel-lint": "^0.9.0.0",
- "mediawiki/mediawiki-codesniffer": "15.0.0",
- "phpunit/phpunit": "^4.8.9.0"
+ "php": "^5.5.9|>=7.0.8"
},
- "time": "2018-01-18 21:23:40",
+ "time": "2018-04-03 05:22:50",
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
"installation-source": "dist",
"autoload": {
- "files": [
- "src/RelPath/RelPath.php",
- "src/Wikimedia/RelPath.php"
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Ori Livneh",
- "email": "ori@wikimedia.org"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Compute a relative filepath between two paths.",
- "homepage": "https://www.mediawiki.org/wiki/RelPath"
+ "description": "Symfony Process Component",
+ "homepage": "https://symfony.com"
},
{
- "name": "nothingworks/blade-svg",
- "version": "v0.2.2",
- "version_normalized": "0.2.2.0",
+ "name": "symfony/console",
+ "version": "v4.0.9",
+ "version_normalized": "4.0.9.0",
"source": {
"type": "git",
- "url": "https://github.com/adamwathan/blade-svg.git",
- "reference": "fad56a6e5fb970e55b9745e547106ca09273fe24"
+ "url": "https://github.com/symfony/console.git",
+ "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/adamwathan/blade-svg/zipball/fad56a6e5fb970e55b9745e547106ca09273fe24",
- "reference": "fad56a6e5fb970e55b9745e547106ca09273fe24",
+ "url": "https://api.github.com/repos/symfony/console/zipball/3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
+ "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
"shasum": ""
},
"require": {
- "illuminate/filesystem": "^5.3",
- "illuminate/support": "^5.3"
+ "php": "^7.1.3",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<3.4",
+ "symfony/process": "<3.3"
},
"require-dev": {
- "mockery/mockery": "^0.9.5",
- "phpunit/phpunit": "^5.5"
+ "psr/log": "~1.0",
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/event-dispatcher": "~3.4|~4.0",
+ "symfony/lock": "~3.4|~4.0",
+ "symfony/process": "~3.4|~4.0"
},
- "time": "2017-08-13 20:55:40",
+ "suggest": {
+ "psr/log-implementation": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/lock": "",
+ "symfony/process": ""
+ },
+ "time": "2018-04-30 01:23:47",
"type": "library",
"extra": {
- "laravel": {
- "providers": [
- "BladeSvg\\BladeSvgServiceProvider"
- ]
+ "branch-alias": {
+ "dev-master": "4.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "BladeSvg\\": "src/"
+ "Symfony\\Component\\Console\\": ""
},
- "files": [
- "src/helpers.php"
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
],
"authors": [
{
- "name": "Adam Wathan",
- "email": "adam.wathan@gmail.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
- ]
+ ],
+ "description": "Symfony Console Component",
+ "homepage": "https://symfony.com"
},
{
- "name": "log1x/blade-svg-sage",
- "version": "v1.0.6",
- "version_normalized": "1.0.6.0",
+ "name": "illuminate/console",
+ "version": "v5.6.21",
+ "version_normalized": "5.6.21.0",
"source": {
"type": "git",
- "url": "https://github.com/Log1x/blade-svg-sage.git",
- "reference": "c41f1180d1eab3ea1040eb8bb2d02082bccc9c20"
+ "url": "https://github.com/illuminate/console.git",
+ "reference": "80fda6b3fddc07e81351260fa21e92496fc13b7e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Log1x/blade-svg-sage/zipball/c41f1180d1eab3ea1040eb8bb2d02082bccc9c20",
- "reference": "c41f1180d1eab3ea1040eb8bb2d02082bccc9c20",
+ "url": "https://api.github.com/repos/illuminate/console/zipball/80fda6b3fddc07e81351260fa21e92496fc13b7e",
+ "reference": "80fda6b3fddc07e81351260fa21e92496fc13b7e",
"shasum": ""
},
"require": {
- "nothingworks/blade-svg": "^0.2.1",
- "wikimedia/relpath": "^2.1"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/console": "~4.0"
+ },
+ "suggest": {
+ "dragonmantank/cron-expression": "Required to use scheduling component (~2.0).",
+ "guzzlehttp/guzzle": "Required to use the ping methods on schedules (~6.0).",
+ "symfony/process": "Required to use scheduling component (~4.0)."
+ },
+ "time": "2018-05-02 14:47:56",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.6-dev"
+ }
},
- "time": "2018-02-06 19:18:31",
- "type": "package",
"installation-source": "dist",
"autoload": {
- "files": [
- "src/helpers.php",
- "src/blade-svg-sage.php"
- ]
+ "psr-4": {
+ "Illuminate\\Console\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Brandon Nifong",
- "email": "brandon@tendency.me"
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
}
],
- "homepage": "https://github.com/log1x/blade-svg-sage"
+ "description": "The Illuminate Console package.",
+ "homepage": "https://laravel.com"
+ },
+ {
+ "name": "roots/sage-installer",
+ "version": "1.3.6",
+ "version_normalized": "1.3.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/roots/sage-installer.git",
+ "reference": "e811ab937a36b321ea88ec6000ab3d5019b8f2b1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/roots/sage-installer/zipball/e811ab937a36b321ea88ec6000ab3d5019b8f2b1",
+ "reference": "e811ab937a36b321ea88ec6000ab3d5019b8f2b1",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/console": "~5.6",
+ "illuminate/filesystem": "~5.6",
+ "symfony/process": "~3.3"
+ },
+ "require-dev": {
+ "squizlabs/php_codesniffer": "~3.0"
+ },
+ "time": "2018-04-25 17:45:56",
+ "bin": [
+ "bin/sage"
+ ],
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Roots\\Sage\\Installer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ben Word",
+ "email": "ben@benword.com",
+ "homepage": "https://github.com/retlehs"
+ },
+ {
+ "name": "QWp6t",
+ "email": "hi@qwp6t.me",
+ "homepage": "https://github.com/qwp6t"
+ }
+ ],
+ "description": "Sage starter theme installer",
+ "keywords": [
+ "bootstrap",
+ "foundation",
+ "sage",
+ "tachyons",
+ "theme",
+ "wordpress"
+ ]
}
]
- 5.6
- 7.0
- 7.1
+ - 7.2
- hhvm
- nightly
## [Unreleased]
+## v1.5.0 - 2017-12-29
+### Added
+* Added WordPress dropin support.
+* Added new types supported for Eliasis.
+* Added support for Phoenix CMS.
+* Added MODX installer.
+* Added Majima instaler.
+* Added SiteDirect installer.
+* Added support optional prefix in OctoberCMS installers.
+* Added PHP 7.2 support.
+
+### Changed
+* Changed remove packages, see [#348](https://github.com/composer/installers/pull/348).
+
+### Fixed
+* Fixed code style, removed unused imports.
+
## v1.4.0 - 2017-08-09
### Added
* Installer for eZ Platform.
| Dolibarr | `dolibarr-module`
| Drupal | <b>`drupal-core`<br>`drupal-module`<br>`drupal-theme`</b><br>`drupal-library`<br>`drupal-profile`<br>`drupal-drush`
| Elgg | `elgg-plugin`
-| Eliasis | `eliasis-module`
+| Eliasis | `eliasis-component`<br>`eliasis-module`<br>`eliasis-plugin`<br>`eliasis-template`
| ExpressionEngine 3 | `ee3-addon`<br>`ee3-theme`
| eZ Platform | `ezplatform-assets`<br>`ezplatform-meta-assets`
| FuelPHP v1.x | `fuel-module`<br>`fuel-package`<br/>`fuel-theme`
| Lavalite | `lavalite-theme`<br>`lavalite-package`
| Lithium | **`lithium-library`<br>`lithium-source`**
| Magento | `magento-library`<br>`magento-skin`<br>`magento-theme`
+| majima | `majima-plugin`
| Mako | `mako-package`
| Mautic | `mautic-plugin`<br>`mautic-theme`
| Maya | `maya-module`
+| MODX | `modx-extra`
| MODX Evo | `modxevo-snippet`<br>`modxevo-plugin`<br>`modxevo-module`<br>`modxevo-template`<br>`modxevo-lib`
| MediaWiki | `mediawiki-extension`
| October | **`october-module`<br>`october-plugin`<br>`october-theme`**
| Roundcube | `roundcube-plugin`
| shopware | `shopware-backend-plugin`<br/>`shopware-core-plugin`<br/>`shopware-frontend-plugin`<br/>`shopware-theme`<br/>`shopware-plugin`<br/>`shopware-frontend-theme`
| SilverStripe | `silverstripe-module`<br>`silverstripe-theme`
+| SiteDirect | `sitedirect-module`<br>`sitedirect-plugin`
| SMF | `smf-module`<br>`smf-theme`
| SyDES | `sydes-module`<br>`sydes-theme`
| symfony1 | **`symfony1-plugin`**
| Vanilla | `vanilla-plugin`<br>`vanilla-theme`
| Vgmcp | `vgmcp-bundle`<br>`vgmcp-theme`
| Wolf CMS | `wolfcms-plugin`
-| WordPress | <b>`wordpress-plugin`<br>`wordpress-theme`</b><br>`wordpress-muplugin`
+| WordPress | <b>`wordpress-plugin`<br>`wordpress-theme`</b><br>`wordpress-muplugin`<br>`wordpress-dropin`
| YAWIK | `yawik-module`
| Zend | `zend-library`<br>`zend-extra`<br>`zend-module`
| Zikula | `zikula-module`<br>`zikula-theme`
"Lavalite",
"Lithium",
"Magento",
+ "majima",
"Mako",
"Mautic",
"Maya",
+ "MODX",
"MODX Evo",
"MediaWiki",
"OXID",
"MODULEWork",
"Moodle",
"Piwik",
+ "pxcms",
"phpBB",
"Plentymarkets",
"PPI",
},
"require-dev": {
"composer/composer": "1.0.*@dev",
- "phpunit/phpunit": "4.1.*"
+ "phpunit/phpunit": "^4.8.36"
},
"scripts": {
"test": "phpunit"
namespace Composer\Installers;
use Composer\DependencyResolver\Pool;
-use Composer\Package\PackageInterface;
class CakePHPInstaller extends BaseInstaller
{
class EliasisInstaller extends BaseInstaller
{
protected $locations = array(
- 'module' => 'modules/{$name}/'
+ 'component' => 'components/{$name}/',
+ 'module' => 'modules/{$name}/',
+ 'plugin' => 'plugins/{$name}/',
+ 'template' => 'templates/{$name}/',
);
}
'lavalite' => 'LavaLiteInstaller',
'lithium' => 'LithiumInstaller',
'magento' => 'MagentoInstaller',
+ 'majima' => 'MajimaInstaller',
'mako' => 'MakoInstaller',
'maya' => 'MayaInstaller',
'mautic' => 'MauticInstaller',
'mediawiki' => 'MediaWikiInstaller',
'microweber' => 'MicroweberInstaller',
'modulework' => 'MODULEWorkInstaller',
+ 'modx' => 'ModxInstaller',
'modxevo' => 'MODXEvoInstaller',
'moodle' => 'MoodleInstaller',
'october' => 'OctoberInstaller',
'ontowiki' => 'OntoWikiInstaller',
'oxid' => 'OxidInstaller',
'osclass' => 'OsclassInstaller',
+ 'pxcms' => 'PxcmsInstaller',
'phpbb' => 'PhpBBInstaller',
'pimcore' => 'PimcoreInstaller',
'piwik' => 'PiwikInstaller',
'reindex' => 'ReIndexInstaller',
'roundcube' => 'RoundcubeInstaller',
'shopware' => 'ShopwareInstaller',
+ 'sitedirect' => 'SiteDirectInstaller',
'silverstripe' => 'SilverStripeInstaller',
'smf' => 'SMFInstaller',
'sydes' => 'SyDESInstaller',
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
{
- if (!$repo->hasPackage($package)) {
- throw new \InvalidArgumentException('Package is not installed: '.$package);
- }
-
- $repo->removePackage($package);
-
- $installPath = $this->getInstallPath($package);
- $this->io->write(sprintf('Deleting %s - %s', $installPath, $this->filesystem->removeDirectory($installPath) ? '<comment>deleted</comment>' : '<error>not deleted</error>'));
+ parent::uninstall($repo, $package);
+ $installPath = $this->getPackageBasePath($package);
+ $this->io->write(sprintf('Deleting %s - %s', $installPath, !file_exists($installPath) ? '<comment>deleted</comment>' : '<error>not deleted</error>'));
}
/**
--- /dev/null
+<?php
+namespace Composer\Installers;
+
+/**
+ * Plugin/theme installer for majima
+ * @author David Neustadt
+ */
+class MajimaInstaller extends BaseInstaller
+{
+ protected $locations = array(
+ 'plugin' => 'plugins/{$name}/',
+ );
+
+ /**
+ * Transforms the names
+ * @param array $vars
+ * @return array
+ */
+ public function inflectPackageVars($vars)
+ {
+ return $this->correctPluginName($vars);
+ }
+
+ /**
+ * Change hyphenated names to camelcase
+ * @param array $vars
+ * @return array
+ */
+ private function correctPluginName($vars)
+ {
+ $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) {
+ return strtoupper($matches[0][1]);
+ }, $vars['name']);
+ $vars['name'] = ucfirst($camelCasedName);
+ return $vars;
+ }
+}
--- /dev/null
+<?php
+namespace Composer\Installers;
+
+/**
+ * An installer to handle MODX specifics when installing packages.
+ */
+class ModxInstaller extends BaseInstaller
+{
+ protected $locations = array(
+ 'extra' => 'core/packages/{$name}/'
+ );
+}
protected function inflectPluginVars($vars)
{
- $vars['name'] = preg_replace('/-plugin$/', '', $vars['name']);
+ $vars['name'] = preg_replace('/^oc-|-plugin$/', '', $vars['name']);
return $vars;
}
protected function inflectThemeVars($vars)
{
- $vars['name'] = preg_replace('/-theme$/', '', $vars['name']);
+ $vars['name'] = preg_replace('/^oc-|-theme$/', '', $vars['name']);
return $vars;
}
-}
\ No newline at end of file
+}
--- /dev/null
+<?php
+namespace Composer\Installers;
+
+class PxcmsInstaller extends BaseInstaller
+{
+ protected $locations = array(
+ 'module' => 'app/Modules/{$name}/',
+ 'theme' => 'themes/{$name}/',
+ );
+
+ /**
+ * Format package name.
+ *
+ * @param array $vars
+ *
+ * @return array
+ */
+ public function inflectPackageVars($vars)
+ {
+ if ($vars['type'] === 'pxcms-module') {
+ return $this->inflectModuleVars($vars);
+ }
+
+ if ($vars['type'] === 'pxcms-theme') {
+ return $this->inflectThemeVars($vars);
+ }
+
+ return $vars;
+ }
+
+ /**
+ * For package type pxcms-module, cut off a trailing '-plugin' if present.
+ *
+ * return string
+ */
+ protected function inflectModuleVars($vars)
+ {
+ $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy)
+ $vars['name'] = str_replace('module-', '', $vars['name']); // strip out module-
+ $vars['name'] = preg_replace('/-module$/', '', $vars['name']); // strip out -module
+ $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s
+ $vars['name'] = ucwords($vars['name']); // make module name camelcased
+
+ return $vars;
+ }
+
+
+ /**
+ * For package type pxcms-module, cut off a trailing '-plugin' if present.
+ *
+ * return string
+ */
+ protected function inflectThemeVars($vars)
+ {
+ $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy)
+ $vars['name'] = str_replace('theme-', '', $vars['name']); // strip out theme-
+ $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); // strip out -theme
+ $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s
+ $vars['name'] = ucwords($vars['name']); // make module name camelcased
+
+ return $vars;
+ }
+}
{
if ($vars['type'] === 'shopware-theme') {
return $this->correctThemeName($vars);
- } else {
- return $this->correctPluginName($vars);
}
+
+ return $this->correctPluginName($vars);
}
/**
&& version_compare($package->getVersion(), '2.999.999') < 0
) {
return $this->templatePath($this->locations['module'], array('name' => 'sapphire'));
- } else {
- return parent::getInstallPath($package, $frameworkType);
}
+ return parent::getInstallPath($package, $frameworkType);
}
}
--- /dev/null
+<?php
+
+namespace Composer\Installers;
+
+class SiteDirectInstaller extends BaseInstaller
+{
+ protected $locations = array(
+ 'module' => 'modules/{$vendor}/{$name}/',
+ 'plugin' => 'plugins/{$vendor}/{$name}/'
+ );
+
+ public function inflectPackageVars($vars)
+ {
+ return $this->parseVars($vars);
+ }
+
+ protected function parseVars($vars)
+ {
+ $vars['vendor'] = strtolower($vars['vendor']) == 'sitedirect' ? 'SiteDirect' : $vars['vendor'];
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
+
+ return $vars;
+ }
+}
'plugin' => 'wp-content/plugins/{$name}/',
'theme' => 'wp-content/themes/{$name}/',
'muplugin' => 'wp-content/mu-plugins/{$name}/',
+ 'dropin' => 'wp-content/{$name}/',
);
}
use Composer\Installers\AsgardInstaller;
use Composer\Package\Package;
use Composer\Composer;
+use PHPUnit\Framework\TestCase;
-class AsgardInstallerTest extends \PHPUnit_Framework_TestCase
+class AsgardInstallerTest extends TestCase
{
/**
* @var AsgardInstaller
namespace Composer\Installers\Test;
use Composer\Installers\BitrixInstaller;
-use Composer\Package\PackageInterface;
use Composer\Package\Package;
use Composer\Composer;
),
);
}
-}
\ No newline at end of file
+}
use Composer\Repository\InstalledArrayRepository;
use Composer\Package\Package;
use Composer\Package\RootPackage;
-use Composer\Package\Link;
use Composer\Package\Version\VersionParser;
use Composer\Composer;
use Composer\Config;
use Composer\Installers\DokuWikiInstaller;
use Composer\Package\Package;
use Composer\Composer;
+use PHPUnit\Framework\TestCase as BaseTestCase;
-class DokuWikiInstallerTest extends \PHPUnit_Framework_TestCase
+class DokuWikiInstallerTest extends BaseTestCase
{
/**
* @var DokuWikiInstaller
array('ee2-theme', true),
array('ee2-addon', true),
array('elgg-plugin', true),
+ array('eliasis-component', true),
array('eliasis-module', true),
+ array('eliasis-plugin', true),
+ array('eliasis-template', true),
array('ezplatform-assets', true),
array('ezplatform-meta-assets', true),
array('fuel-module', true),
array('lavalite-package', true),
array('lithium-library', true),
array('magento-library', true),
+ array('majima-plugin', true),
array('mako-package', true),
+ array('modx-extra', true),
array('modxevo-snippet', true),
array('modxevo-plugin', true),
array('modxevo-module', true),
array('october-module', true),
array('october-plugin', true),
array('piwik-plugin', true),
+ array('pxcms-module', true),
+ array('pxcms-theme', true),
array('phpbb-extension', true),
array('pimcore-plugin', true),
array('plentymarkets-plugin', true),
array('drupal-profile', 'profiles/my_module/', 'shama/my_module'),
array('drupal-drush', 'drush/my_module/', 'shama/my_module'),
array('elgg-plugin', 'mod/sample_plugin/', 'test/sample_plugin'),
+ array('eliasis-component', 'components/my_component/', 'shama/my_component'),
array('eliasis-module', 'modules/my_module/', 'shama/my_module'),
+ array('eliasis-plugin', 'plugins/my_plugin/', 'shama/my_plugin'),
+ array('eliasis-template', 'templates/my_template/', 'shama/my_template'),
array('ee3-addon', 'system/user/addons/ee_theme/', 'author/ee_theme'),
array('ee3-theme', 'themes/user/ee_package/', 'author/ee_package'),
array('ee2-addon', 'system/expressionengine/third_party/ee_theme/', 'author/ee_theme'),
array('lavalite-package', 'packages/my_group/my_package/', 'my_group/my_package'),
array('lithium-library', 'libraries/li3_test/', 'user/li3_test'),
array('magento-library', 'lib/foo/', 'test/foo'),
+ array('majima-plugin', 'plugins/MyPlugin/', 'shama/my-plugin'),
+ array('modx-extra', 'core/packages/extra/', 'vendor/extra'),
array('modxevo-snippet', 'assets/snippets/my_snippet/', 'shama/my_snippet'),
array('modxevo-plugin', 'assets/plugins/my_plugin/', 'shama/my_plugin'),
array('modxevo-module', 'assets/modules/my_module/', 'shama/my_module'),
array('piwik-plugin', 'plugins/VisitSummary/', 'shama/visit-summary'),
array('prestashop-module', 'modules/a-module/', 'vendor/a-module'),
array('prestashop-theme', 'themes/a-theme/', 'vendor/a-theme'),
+ array('pxcms-module', 'app/Modules/Foo/', 'vendor/module-foo'),
+ array('pxcms-module', 'app/Modules/Foo/', 'vendor/pxcms-foo'),
+ array('pxcms-theme', 'themes/Foo/', 'vendor/theme-foo'),
+ array('pxcms-theme', 'themes/Foo/', 'vendor/pxcms-foo'),
array('phpbb-extension', 'ext/test/foo/', 'test/foo'),
array('phpbb-style', 'styles/foo/', 'test/foo'),
array('phpbb-language', 'language/foo/', 'test/foo'),
$package = new Package('foo', '1.0.0', '1.0.0');
$installer = $this->getMock('Composer\Installers\Installer', array('getInstallPath'), array($this->io, $this->composer));
- $installer->expects($this->once())->method('getInstallPath')->with($package)->will($this->returnValue(sys_get_temp_dir().'/foo'));
+ $installer->expects($this->atLeastOnce())->method('getInstallPath')->with($package)->will($this->returnValue(sys_get_temp_dir().'/foo'));
$repo = $this->getMock('Composer\Repository\InstalledRepositoryInterface');
$repo->expects($this->once())->method('hasPackage')->with($package)->will($this->returnValue(true));
use Composer\Installers\MayaInstaller;
use Composer\Package\Package;
use Composer\Composer;
+use PHPUnit\Framework\TestCase as BaseTestCase;
-class MayaInstallerTest extends \PHPUnit_Framework_TestCase
+class MayaInstallerTest extends BaseTestCase
{
/**
* @var MayaInstaller
use Composer\Installers\MediaWikiInstaller;
use Composer\Package\Package;
use Composer\Composer;
+use PHPUnit\Framework\TestCase as BaseTestCase;
-class MediaWikiInstallerTest extends \PHPUnit_Framework_TestCase
+class MediaWikiInstallerTest extends BaseTestCase
{
/**
* @var MediaWikiInstaller
use Composer\Installers\OctoberInstaller;
use Composer\Package\Package;
use Composer\Composer;
+use PHPUnit\Framework\TestCase as BaseTestCase;
-class OctoberInstallerTest extends \PHPUnit_Framework_TestCase
+class OctoberInstallerTest extends BaseTestCase
{
/**
* @var OctoberInstaller
),
);
}
-}
\ No newline at end of file
+}
namespace Composer\Installers\Test;
use Composer\Installers\OntoWikiInstaller;
-use Composer\Package\Package;
-use Composer\Composer;
+use PHPUnit\Framework\TestCase as BaseTestCase;
/**
* Test for the OntoWikiInstaller
* code was taken from DokuWikiInstaller
*/
-class OntoWikiInstallerTest extends \PHPUnit_Framework_TestCase
+class OntoWikiInstallerTest extends BaseTestCase
{
/**
* @var OntoWikiInstaller
--- /dev/null
+<?php
+
+namespace Composer\Installers\Test;
+
+use Composer\Composer;
+use Composer\Installers\SiteDirectInstaller;
+use Composer\Package\Package;
+
+class SiteDirectInstallerTest extends TestCase
+{
+ /** @var SiteDirectInstaller $installer */
+ protected $installer;
+
+ /** @var Package */
+ private $package;
+
+ public function SetUp()
+ {
+ $this->package = new Package('sitedirect/some_name', '1.0.9', '1.0');
+ $this->installer = new SiteDirectInstaller(
+ $this->package,
+ new Composer()
+ );
+
+ }
+
+ /**
+ * @dataProvider dataProvider
+ */
+ public function testInflectPackageVars($data, $expected)
+ {
+ $result = $this->installer->inflectPackageVars($data);
+ $this->assertEquals($result, $expected);
+ }
+
+ /**
+ * @dataProvider dataProvider
+ */
+ public function testInstallPath($data, $expected)
+ {
+ $result = $this->installer->inflectPackageVars($data);
+ $path = $this->createPackage($data);
+
+ // use $result to get the proper capitalization for the vendor path
+ $expectedPath = "modules/{$result['vendor']}/{$result['name']}/";
+ $notExpectedPath = "modules/{$data['vendor']}/{$data['name']}/";
+ $this->assertEquals($expectedPath, $path);
+ $this->assertNotEquals($notExpectedPath, $path);
+ }
+
+ /**
+ * @param $data
+ * @return string
+ */
+ private function createPackage($data)
+ {
+ $fullName = "{$data['vendor']}/{$data['name']}";
+
+ $package = new Package($fullName, '1.0', '1.0');
+ $package->setType('sitedirect-module');
+ $installer = new SiteDirectInstaller($package, new Composer());
+
+ $path = $installer->getInstallPath($package, 'sitedirect');
+ return $path;
+ }
+
+ public function dataProvider()
+ {
+ return array(
+ array(
+ 'data' => array(
+ 'name' => 'kernel',
+ 'vendor' => 'sitedirect',
+ 'type' => 'sitedirect-module',
+ ),
+ 'expected' => array(
+ 'name' => 'Kernel',
+ 'vendor' => 'SiteDirect',
+ 'type' => 'sitedirect-module',
+ )
+ ),
+ array(
+ 'data' => array(
+ 'name' => 'that_guy',
+ 'vendor' => 'whatGuy',
+ 'type' => 'sitedirect-module',
+ ),
+ 'expected' => array(
+ 'name' => 'ThatGuy',
+ 'vendor' => 'whatGuy',
+ 'type' => 'sitedirect-module',
+ )
+ ),
+ array(
+ 'data' => array(
+ 'name' => 'checkout',
+ 'vendor' => 'someVendor',
+ 'type' => 'sitedirect-plugin',
+ ),
+ 'expected' => array(
+ 'name' => 'Checkout',
+ 'vendor' => 'someVendor',
+ 'type' => 'sitedirect-plugin',
+ )
+ ),
+ array(
+ 'data' => array(
+ 'name' => 'checkout',
+ 'vendor' => 'siteDirect',
+ 'type' => 'sitedirect-plugin',
+ ),
+ 'expected' => array(
+ 'name' => 'Checkout',
+ 'vendor' => 'SiteDirect',
+ 'type' => 'sitedirect-plugin',
+ )
+ ),
+ );
+ }
+}
use Composer\Installers\SyDESInstaller;
use Composer\Package\Package;
use Composer\Composer;
+use PHPUnit\Framework\TestCase as BaseTestCase;
-class SyDESInstallerTest extends \PHPUnit_Framework_TestCase
+class SyDESInstallerTest extends BaseTestCase
{
/**
* @var SyDESInstaller
use Composer\Package\AliasPackage;
use Composer\Package\LinkConstraint\VersionConstraint;
use Composer\Util\Filesystem;
+use PHPUnit\Framework\TestCase as BaseTestCase;
-abstract class TestCase extends \PHPUnit_Framework_TestCase
+abstract class TestCase extends BaseTestCase
{
private static $parser;
use Composer\Installers\VgmcpInstaller;
use Composer\Package\Package;
use Composer\Composer;
+use PHPUnit\Framework\TestCase as BaseTestCase;
-class VgmcpInstallerTest extends \PHPUnit_Framework_TestCase
+class VgmcpInstallerTest extends BaseTestCase
{
/**
* @var VgmcpInstaller
{"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
],
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^6.2"
"psr-4": { "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" }
},
"autoload-dev": {
- "psr-4": { "Doctrine\\Tests\\Common\\Inflector\\": "tests/Doctrine/Common/Inflector" }
+ "psr-4": { "Doctrine\\Tests\\Common\\Inflector\\": "tests/Doctrine/Tests/Common/Inflector" }
},
"extra": {
"branch-alias": {
- "dev-master": "1.2.x-dev"
+ "dev-master": "1.3.x-dev"
}
}
}
/**
* Plural inflector rules.
*
- * @var array
+ * @var string[][]
*/
private static $plural = array(
'rules' => array(
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
'/sis$/i' => 'ses',
'/([ti])um$/i' => '\1a',
+ '/(c)riterion$/i' => '\1riteria',
'/(p)erson$/i' => '\1eople',
'/(m)an$/i' => '\1en',
'/(c)hild$/i' => '\1hildren',
'ganglion' => 'ganglions',
'genie' => 'genies',
'genus' => 'genera',
+ 'goose' => 'geese',
'graffito' => 'graffiti',
'hippopotamus' => 'hippopotami',
'hoof' => 'hoofs',
'tornado' => 'tornadoes',
'trilby' => 'trilbys',
'turf' => 'turfs',
+ 'valve' => 'valves',
'volcano' => 'volcanoes',
)
);
/**
* Singular inflector rules.
*
- * @var array
+ * @var string[][]
*/
private static $singular = array(
'rules' => array(
'/(hive)s$/i' => '\1',
'/(drive)s$/i' => '\1',
'/(dive)s$/i' => '\1',
+ '/(olive)s$/i' => '\1',
'/([^fo])ves$/i' => '\1fe',
'/(^analy)ses$/i' => '\1sis',
'/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
+ '/(c)riteria$/i' => '\1riterion',
'/([ti])a$/i' => '\1um',
'/(p)eople$/i' => '\1\2erson',
'/(m)en$/i' => '\1an',
'.*pox',
'.*sheep',
'.*ss',
+ 'data',
'police',
'pants',
'clothes',
),
'irregular' => array(
- 'caches' => 'cache',
- 'criteria' => 'criterion',
- 'curves' => 'curve',
- 'emphases' => 'emphasis',
- 'foes' => 'foe',
- 'hoaxes' => 'hoax',
- 'media' => 'medium',
- 'neuroses' => 'neurosis',
- 'waves' => 'wave',
- 'oases' => 'oasis',
+ 'abuses' => 'abuse',
+ 'avalanches' => 'avalanche',
+ 'caches' => 'cache',
+ 'criteria' => 'criterion',
+ 'curves' => 'curve',
+ 'emphases' => 'emphasis',
+ 'foes' => 'foe',
+ 'geese' => 'goose',
+ 'graves' => 'grave',
+ 'hoaxes' => 'hoax',
+ 'media' => 'medium',
+ 'neuroses' => 'neurosis',
+ 'waves' => 'wave',
+ 'oases' => 'oasis',
+ 'valves' => 'valve',
)
);
* @var array
*/
private static $uninflected = array(
- 'Amoyese', 'bison', 'Borghese', 'bream', 'breeches', 'britches', 'buffalo', 'cantus',
- 'carp', 'chassis', 'clippers', 'cod', 'coitus', 'Congoese', 'contretemps', 'corps',
- 'debris', 'diabetes', 'djinn', 'eland', 'elk', 'equipment', 'Faroese', 'flounder',
- 'Foochowese', 'Furniture', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti',
- 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings',
- 'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'Luggage', 'mackerel', 'Maltese', '.*?media',
- 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese',
- 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese',
- 'proceedings', 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors',
- 'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'staff', 'swine',
- 'testes', 'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', 'whiting',
- 'wildebeest', 'Yengeese'
+ '.*?media', 'Amoyese', 'audio', 'bison', 'Borghese', 'bream', 'breeches',
+ 'britches', 'buffalo', 'cantus', 'carp', 'chassis', 'clippers', 'cod', 'coitus', 'compensation', 'Congoese',
+ 'contretemps', 'coreopsis', 'corps', 'data', 'debris', 'deer', 'diabetes', 'djinn', 'education', 'eland',
+ 'elk', 'emoji', 'equipment', 'evidence', 'Faroese', 'feedback', 'fish', 'flounder', 'Foochowese',
+ 'Furniture', 'furniture', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'gold',
+ 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', 'jackanapes', 'jedi',
+ 'Kiplingese', 'knowledge', 'Kongoese', 'love', 'Lucchese', 'Luggage', 'mackerel', 'Maltese', 'metadata',
+ 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese', 'nutrition', 'offspring',
+ 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'plankton', 'pliers', 'pokemon', 'police', 'Portuguese',
+ 'proceedings', 'rabies', 'rain', 'rhinoceros', 'rice', 'salmon', 'Sarawakese', 'scissors', 'sea[- ]bass',
+ 'series', 'Shavese', 'shears', 'sheep', 'siemens', 'species', 'staff', 'swine', 'traffic',
+ 'trousers', 'trout', 'tuna', 'us', 'Vermontese', 'Wenchowese', 'wheat', 'whiting', 'wildebeest', 'Yengeese'
);
/**
/**
* Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
- *
- * @param string $word The word to tableize.
- *
- * @return string The tableized word.
*/
- public static function tableize($word)
+ public static function tableize(string $word) : string
{
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word));
}
/**
* Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
- *
- * @param string $word The word to classify.
- *
- * @return string The classified word.
*/
- public static function classify($word)
+ public static function classify(string $word) : string
{
- return str_replace(' ', '', ucwords(strtr($word, '_-', ' ')));
+ return str_replace([' ', '_', '-'], '', ucwords($word, ' _-'));
}
/**
* Camelizes a word. This uses the classify() method and turns the first character to lowercase.
- *
- * @param string $word The word to camelize.
- *
- * @return string The camelized word.
*/
- public static function camelize($word)
+ public static function camelize(string $word) : string
{
return lcfirst(self::classify($word));
}
* Uppercases words with configurable delimeters between words.
*
* Takes a string and capitalizes all of the words, like PHP's built-in
- * ucwords function. This extends that behavior, however, by allowing the
+ * ucwords function. This extends that behavior, however, by allowing the
* word delimeters to be configured, rather than only separating on
* whitespace.
*
*
* @return string The string with all delimeter-separated words capitalized.
*/
- public static function ucwords($string, $delimiters = " \n\t\r\0\x0B-")
+ public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
{
- return preg_replace_callback(
- '/[^' . preg_quote($delimiters, '/') . ']+/',
- function($matches) {
- return ucfirst($matches[0]);
- },
- $string
- );
+ return ucwords($string, $delimiters);
}
/**
* Clears Inflectors inflected value caches, and resets the inflection
* rules to the initial values.
- *
- * @return void
*/
- public static function reset()
+ public static function reset() : void
{
if (empty(self::$initialState)) {
self::$initialState = get_class_vars('Inflector');
}
foreach (self::$initialState as $key => $val) {
- if ($key != 'initialState') {
+ if ($key !== 'initialState') {
self::${$key} = $val;
}
}
* ));
* }}}
*
- * @param string $type The type of inflection, either 'plural' or 'singular'
- * @param array $rules An array of rules to be added.
- * @param boolean $reset If true, will unset default inflections for all
- * new rules that are being defined in $rules.
+ * @param string $type The type of inflection, either 'plural' or 'singular'
+ * @param array|iterable $rules An array of rules to be added.
+ * @param boolean $reset If true, will unset default inflections for all
+ * new rules that are being defined in $rules.
*
* @return void
*/
- public static function rules($type, $rules, $reset = false)
+ public static function rules(string $type, iterable $rules, bool $reset = false) : void
{
foreach ($rules as $rule => $pattern) {
if ( ! is_array($pattern)) {
*
* @return string The word in plural form.
*/
- public static function pluralize($word)
+ public static function pluralize(string $word) : string
{
if (isset(self::$cache['pluralize'][$word])) {
return self::$cache['pluralize'][$word];
}
if (preg_match('/(.*)\\b(' . self::$plural['cacheIrregular'] . ')$/i', $word, $regs)) {
- self::$cache['pluralize'][$word] = $regs[1] . substr($word, 0, 1) . substr(self::$plural['merged']['irregular'][strtolower($regs[2])], 1);
+ self::$cache['pluralize'][$word] = $regs[1] . $word[0] . substr(self::$plural['merged']['irregular'][strtolower($regs[2])], 1);
return self::$cache['pluralize'][$word];
}
*
* @return string The word in singular form.
*/
- public static function singularize($word)
+ public static function singularize(string $word) : string
{
if (isset(self::$cache['singularize'][$word])) {
return self::$cache['singularize'][$word];
}
if (!isset(self::$singular['cacheUninflected']) || !isset(self::$singular['cacheIrregular'])) {
- self::$singular['cacheUninflected'] = '(?:' . join('|', self::$singular['merged']['uninflected']) . ')';
- self::$singular['cacheIrregular'] = '(?:' . join('|', array_keys(self::$singular['merged']['irregular'])) . ')';
+ self::$singular['cacheUninflected'] = '(?:' . implode('|', self::$singular['merged']['uninflected']) . ')';
+ self::$singular['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$singular['merged']['irregular'])) . ')';
}
if (preg_match('/(.*)\\b(' . self::$singular['cacheIrregular'] . ')$/i', $word, $regs)) {
- self::$cache['singularize'][$word] = $regs[1] . substr($word, 0, 1) . substr(self::$singular['merged']['irregular'][strtolower($regs[2])], 1);
+ self::$cache['singularize'][$word] = $regs[1] . $word[0] . substr(self::$singular['merged']['irregular'][strtolower($regs[2])], 1);
return self::$cache['singularize'][$word];
}
/**
* Get the specified configuration value.
*
- * @param string $key
+ * @param array|string $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
{
+ if (is_array($key)) {
+ return $this->getMany($key);
+ }
+
return Arr::get($this->items, $key, $default);
}
+ /**
+ * Get many configuration values.
+ *
+ * @param array $keys
+ * @return array
+ */
+ public function getMany($keys)
+ {
+ $config = [];
+
+ foreach ($keys as $key => $default) {
+ if (is_numeric($key)) {
+ list($key, $default) = [$default, null];
+ }
+
+ $config[$key] = Arr::get($this->items, $key, $default);
+ }
+
+ return $config;
+ }
+
/**
* Set a given configuration value.
*
}
],
"require": {
- "php": ">=5.6.4",
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*"
+ "php": "^7.1.3",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"config": {
namespace Illuminate\Console;
use Closure;
+use Illuminate\Support\ProcessUtils;
use Illuminate\Contracts\Events\Dispatcher;
-use Symfony\Component\Process\ProcessUtils;
use Illuminate\Contracts\Container\Container;
+use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Process\PhpExecutableFinder;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\BufferedOutput;
+use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application as SymfonyApplication;
use Symfony\Component\Console\Command\Command as SymfonyCommand;
+use Symfony\Component\Console\Exception\CommandNotFoundException;
use Illuminate\Contracts\Console\Application as ApplicationContract;
class Application extends SymfonyApplication implements ApplicationContract
*/
protected static $bootstrappers = [];
+ /**
+ * The Event Dispatcher.
+ *
+ * @var \Illuminate\Contracts\Events\Dispatcher
+ */
+ protected $events;
+
/**
* Create a new Artisan console application.
*
parent::__construct('Laravel Framework', $version);
$this->laravel = $laravel;
+ $this->events = $events;
$this->setAutoExit(false);
$this->setCatchExceptions(false);
- $events->dispatch(new Events\ArtisanStarting($this));
+ $this->events->dispatch(new Events\ArtisanStarting($this));
$this->bootstrap();
}
+ /**
+ * {@inheritdoc}
+ */
+ public function run(InputInterface $input = null, OutputInterface $output = null)
+ {
+ $commandName = $this->getCommandName(
+ $input = $input ?: new ArgvInput
+ );
+
+ $this->events->fire(
+ new Events\CommandStarting(
+ $commandName, $input, $output = $output ?: new ConsoleOutput
+ )
+ );
+
+ $exitCode = parent::run($input, $output);
+
+ $this->events->fire(
+ new Events\CommandFinished($commandName, $input, $output, $exitCode)
+ );
+
+ return $exitCode;
+ }
+
/**
* Determine the proper PHP executable.
*
}
}
- /*
+ /**
* Clear the console application bootstrappers.
*
* @return void
*
* @param string $command
* @param array $parameters
- * @param \Symfony\Component\Console\Output\OutputInterface $outputBuffer
+ * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
* @return int
*/
public function call($command, array $parameters = [], $outputBuffer = null)
{
- $parameters = collect($parameters)->prepend($command);
+ if (is_subclass_of($command, SymfonyCommand::class)) {
+ $command = $this->laravel->make($command)->getName();
+ }
+
+ if (! $this->has($command)) {
+ throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $command));
+ }
+
+ array_unshift($parameters, $command);
$this->lastOutput = $outputBuffer ?: new BufferedOutput;
$this->setCatchExceptions(false);
- $result = $this->run(new ArrayInput($parameters->toArray()), $this->lastOutput);
+ $result = $this->run(new ArrayInput($parameters), $this->lastOutput);
$this->setCatchExceptions(true);
*/
public function output()
{
- return $this->lastOutput ? $this->lastOutput->fetch() : '';
+ return $this->lastOutput && method_exists($this->lastOutput, 'fetch')
+ ? $this->lastOutput->fetch()
+ : '';
}
/**
namespace Illuminate\Console;
+use Illuminate\Support\Traits\Macroable;
use Illuminate\Contracts\Support\Arrayable;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\ArrayInput;
class Command extends SymfonyCommand
{
+ use Macroable;
+
/**
* The Laravel application instance.
*
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $method = method_exists($this, 'handle') ? 'handle' : 'fire';
-
- return $this->laravel->call([$this, $method]);
+ return $this->laravel->call([$this, 'handle']);
}
/**
$arguments['command'] = $command;
return $this->getApplication()->find($command)->run(
- new ArrayInput($arguments), $this->output
+ $this->createInputFromArguments($arguments), $this->output
);
}
$arguments['command'] = $command;
return $this->getApplication()->find($command)->run(
- new ArrayInput($arguments), new NullOutput
+ $this->createInputFromArguments($arguments), new NullOutput
);
}
+ /**
+ * Create an input instance from the given arguments.
+ *
+ * @param array $arguments
+ * @return \Symfony\Component\Console\Input\ArrayInput
+ */
+ protected function createInputFromArguments(array $arguments)
+ {
+ return tap(new ArrayInput($arguments), function ($input) {
+ if ($input->hasParameterOption(['--no-interaction'], true)) {
+ $input->setInteractive(false);
+ }
+ });
+ }
+
/**
* Determine if the given argument is present.
*
/**
* Get the value of a command argument.
*
- * @param string $key
+ * @param string|null $key
* @return string|array
*/
public function argument($key = null)
/**
* Get the value of a command option.
*
- * @param string $key
+ * @param string|null $key
* @return string|array
*/
public function option($key = null)
* Prompt the user for input.
*
* @param string $question
- * @param string $default
+ * @param string|null $default
* @return string
*/
public function ask($question, $default = null)
*
* @param string $question
* @param array $choices
- * @param string $default
+ * @param string|null $default
* @return string
*/
public function anticipate($question, array $choices, $default = null)
*
* @param string $question
* @param array $choices
- * @param string $default
+ * @param string|null $default
* @return string
*/
public function askWithCompletion($question, array $choices, $default = null)
*
* @param string $question
* @param array $choices
- * @param string $default
- * @param mixed $attempts
- * @param bool $multiple
+ * @param string|null $default
+ * @param mixed|null $attempts
+ * @param bool|null $multiple
* @return string
*/
public function choice($question, array $choices, $default = null, $attempts = null, $multiple = null)
*
* @param array $headers
* @param \Illuminate\Contracts\Support\Arrayable|array $rows
- * @param string $style
+ * @param string $tableStyle
+ * @param array $columnStyles
* @return void
*/
- public function table(array $headers, $rows, $style = 'default')
+ public function table($headers, $rows, $tableStyle = 'default', array $columnStyles = [])
{
$table = new Table($this->output);
$rows = $rows->toArray();
}
- $table->setHeaders($headers)->setRows($rows)->setStyle($style)->render();
+ $table->setHeaders((array) $headers)->setRows($rows)->setStyle($tableStyle);
+
+ foreach ($columnStyles as $columnIndex => $columnStyle) {
+ $table->setColumnStyle($columnIndex, $columnStyle);
+ }
+
+ $table->render();
}
/**
$this->comment('* '.$string.' *');
$this->comment(str_repeat('*', strlen($string) + 12));
- $this->output->writeln('');
+ $this->output->newLine();
}
/**
/**
* Get the verbosity level in terms of Symfony's OutputInterface level.
*
- * @param string|int $level
+ * @param string|int|null $level
* @return int
*/
protected function parseVerbosity($level = null)
--- /dev/null
+<?php
+
+namespace Illuminate\Console\Events;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class CommandFinished
+{
+ /**
+ * The command name.
+ *
+ * @var string
+ */
+ public $command;
+
+ /**
+ * The console input implementation.
+ *
+ * @var \Symfony\Component\Console\Input\InputInterface|null
+ */
+ public $input;
+
+ /**
+ * The command output implementation.
+ *
+ * @var \Symfony\Component\Console\Output\OutputInterface|null
+ */
+ public $output;
+
+ /**
+ * The command exit code.
+ *
+ * @var int
+ */
+ public $exitCode;
+
+ /**
+ * Create a new event instance.
+ *
+ * @param string $command
+ * @param \Symfony\Component\Console\Input\InputInterface $input
+ * @param \Symfony\Component\Console\Output\OutputInterface $output
+ * @param int $exitCode
+ * @return void
+ */
+ public function __construct($command, InputInterface $input, OutputInterface $output, $exitCode)
+ {
+ $this->input = $input;
+ $this->output = $output;
+ $this->command = $command;
+ $this->exitCode = $exitCode;
+ }
+}
--- /dev/null
+<?php
+
+namespace Illuminate\Console\Events;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class CommandStarting
+{
+ /**
+ * The command name.
+ *
+ * @var string
+ */
+ public $command;
+
+ /**
+ * The console input implementation.
+ *
+ * @var \Symfony\Component\Console\Input\InputInterface|null
+ */
+ public $input;
+
+ /**
+ * The command output implementation.
+ *
+ * @var \Symfony\Component\Console\Output\OutputInterface|null
+ */
+ public $output;
+
+ /**
+ * Create a new event instance.
+ *
+ * @param string $command
+ * @param \Symfony\Component\Console\Input\InputInterface $input
+ * @param \Symfony\Component\Console\Output\OutputInterface $output
+ * @return void
+ */
+ public function __construct($command, InputInterface $input, OutputInterface $output)
+ {
+ $this->input = $input;
+ $this->output = $output;
+ $this->command = $command;
+ }
+}
*
* @return bool|null
*/
- public function fire()
+ public function handle()
{
$name = $this->qualifyClass($this->getNameInput());
// First we will check to see if the class already exists. If it does, we don't want
// to create the class and overwrite the user's code. So, we will bail out so the
// code is untouched. Otherwise, we will continue generating this class' files.
- if ($this->alreadyExists($this->getNameInput())) {
+ if ((! $this->hasOption('force') ||
+ ! $this->option('force')) &&
+ $this->alreadyExists($this->getNameInput())) {
$this->error($this->type.' already exists!');
return false;
*/
protected function qualifyClass($name)
{
+ $name = ltrim($name, '\\/');
+
$rootNamespace = $this->rootNamespace();
if (Str::startsWith($name, $rootNamespace)) {
*/
protected function getPath($name)
{
- $name = str_replace_first($this->rootNamespace(), '', $name);
+ $name = Str::replaceFirst($this->rootNamespace(), '', $name);
return $this->laravel['path'].'/'.str_replace('\\', '/', $name).'.php';
}
protected function replaceNamespace(&$stub, $name)
{
$stub = str_replace(
- ['DummyNamespace', 'DummyRootNamespace'],
- [$this->getNamespace($name), $this->rootNamespace()],
+ ['DummyNamespace', 'DummyRootNamespace', 'NamespacedDummyUserModel'],
+ [$this->getNamespace($name), $this->rootNamespace(), config('auth.providers.users.model')],
$stub
);
return new InputArgument(trim($token, '*'), InputArgument::IS_ARRAY | InputArgument::REQUIRED, $description);
case Str::endsWith($token, '?'):
return new InputArgument(trim($token, '?'), InputArgument::OPTIONAL, $description);
+ case preg_match('/(.+)\=\*(.+)/', $token, $matches):
+ return new InputArgument($matches[1], InputArgument::IS_ARRAY, $description, preg_split('/,\s?/', $matches[2]));
case preg_match('/(.+)\=(.+)/', $token, $matches):
return new InputArgument($matches[1], InputArgument::OPTIONAL, $description, $matches[2]);
default:
return new InputOption(trim($token, '='), $shortcut, InputOption::VALUE_OPTIONAL, $description);
case Str::endsWith($token, '=*'):
return new InputOption(trim($token, '=*'), $shortcut, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, $description);
+ case preg_match('/(.+)\=\*(.+)/', $token, $matches):
+ return new InputOption($matches[1], $shortcut, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, $description, preg_split('/,\s?/', $matches[2]));
case preg_match('/(.+)\=(.+)/', $token, $matches):
return new InputOption($matches[1], $shortcut, InputOption::VALUE_OPTIONAL, $description, $matches[2]);
default:
{
$parts = preg_split('/\s+:\s+/', trim($token), 2);
- return count($parts) === 2 ? $parts : [$token, null];
+ return count($parts) === 2 ? $parts : [$token, ''];
}
}
--- /dev/null
+<?php
+
+namespace Illuminate\Console\Scheduling;
+
+use Illuminate\Contracts\Cache\Factory as Cache;
+
+class CacheEventMutex implements EventMutex
+{
+ /**
+ * The cache repository implementation.
+ *
+ * @var \Illuminate\Contracts\Cache\Factory
+ */
+ public $cache;
+
+ /**
+ * The cache store that should be used.
+ *
+ * @var string|null
+ */
+ public $store;
+
+ /**
+ * Create a new overlapping strategy.
+ *
+ * @param \Illuminate\Contracts\Cache\Factory $cache
+ * @return void
+ */
+ public function __construct(Cache $cache)
+ {
+ $this->cache = $cache;
+ }
+
+ /**
+ * Attempt to obtain an event mutex for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return bool
+ */
+ public function create(Event $event)
+ {
+ return $this->cache->store($this->store)->add(
+ $event->mutexName(), true, $event->expiresAt
+ );
+ }
+
+ /**
+ * Determine if an event mutex exists for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return bool
+ */
+ public function exists(Event $event)
+ {
+ return $this->cache->store($this->store)->has($event->mutexName());
+ }
+
+ /**
+ * Clear the event mutex for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return void
+ */
+ public function forget(Event $event)
+ {
+ $this->cache->store($this->store)->forget($event->mutexName());
+ }
+
+ /**
+ * Specify the cache store that should be used.
+ *
+ * @param string $store
+ * @return $this
+ */
+ public function useStore($store)
+ {
+ $this->store = $store;
+
+ return $this;
+ }
+}
+++ /dev/null
-<?php
-
-namespace Illuminate\Console\Scheduling;
-
-use Illuminate\Contracts\Cache\Repository as Cache;
-
-class CacheMutex implements Mutex
-{
- /**
- * The cache repository implementation.
- *
- * @var \Illuminate\Contracts\Cache\Repository
- */
- public $cache;
-
- /**
- * Create a new overlapping strategy.
- *
- * @param \Illuminate\Contracts\Cache\Repository $cache
- * @return void
- */
- public function __construct(Cache $cache)
- {
- $this->cache = $cache;
- }
-
- /**
- * Attempt to obtain a mutex for the given event.
- *
- * @param \Illuminate\Console\Scheduling\Event $event
- * @return bool
- */
- public function create(Event $event)
- {
- return $this->cache->add($event->mutexName(), true, 1440);
- }
-
- /**
- * Determine if a mutex exists for the given event.
- *
- * @param \Illuminate\Console\Scheduling\Event $event
- * @return bool
- */
- public function exists(Event $event)
- {
- return $this->cache->has($event->mutexName());
- }
-
- /**
- * Clear the mutex for the given event.
- *
- * @param \Illuminate\Console\Scheduling\Event $event
- * @return void
- */
- public function forget(Event $event)
- {
- $this->cache->forget($event->mutexName());
- }
-}
--- /dev/null
+<?php
+
+namespace Illuminate\Console\Scheduling;
+
+use DateTimeInterface;
+use Illuminate\Contracts\Cache\Factory as Cache;
+
+class CacheSchedulingMutex implements SchedulingMutex
+{
+ /**
+ * The cache factory implementation.
+ *
+ * @var \Illuminate\Contracts\Cache\Factory
+ */
+ public $cache;
+
+ /**
+ * The cache store that should be used.
+ *
+ * @var string|null
+ */
+ public $store;
+
+ /**
+ * Create a new scheduling strategy.
+ *
+ * @param \Illuminate\Contracts\Cache\Factory $cache
+ * @return void
+ */
+ public function __construct(Cache $cache)
+ {
+ $this->cache = $cache;
+ }
+
+ /**
+ * Attempt to obtain a scheduling mutex for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @param \DateTimeInterface $time
+ * @return bool
+ */
+ public function create(Event $event, DateTimeInterface $time)
+ {
+ return $this->cache->store($this->store)->add(
+ $event->mutexName().$time->format('Hi'), true, 60
+ );
+ }
+
+ /**
+ * Determine if a scheduling mutex exists for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @param \DateTimeInterface $time
+ * @return bool
+ */
+ public function exists(Event $event, DateTimeInterface $time)
+ {
+ return $this->cache->store($this->store)->has(
+ $event->mutexName().$time->format('Hi')
+ );
+ }
+
+ /**
+ * Specify the cache store that should be used.
+ *
+ * @param string $store
+ * @return $this
+ */
+ public function useStore($store)
+ {
+ $this->store = $store;
+
+ return $this;
+ }
+}
/**
* Create a new event instance.
*
- * @param \Illuminate\Console\Scheduling\Mutex $mutex
+ * @param \Illuminate\Console\Scheduling\EventMutex $mutex
* @param string $callback
* @param array $parameters
* @return void
*
* @throws \InvalidArgumentException
*/
- public function __construct(Mutex $mutex, $callback, array $parameters = [])
+ public function __construct(EventMutex $mutex, $callback, array $parameters = [])
{
if (! is_string($callback) && ! is_callable($callback)) {
throw new InvalidArgumentException(
return;
}
- register_shutdown_function(function () {
- $this->removeMutex();
+ $pid = getmypid();
+
+ register_shutdown_function(function () use ($pid) {
+ if ($pid === getmypid()) {
+ $this->removeMutex();
+ }
});
+ parent::callBeforeCallbacks($container);
+
try {
$response = $container->call($this->callback, $this->parameters);
} finally {
$this->removeMutex();
- }
- parent::callAfterCallbacks($container);
+ parent::callAfterCallbacks($container);
+ }
return $response;
}
/**
- * Remove the mutex file from disk.
+ * Clear the mutex for the event.
*
* @return void
*/
/**
* Do not allow the event to overlap each other.
*
+ * @param int $expiresAt
* @return $this
*
* @throws \LogicException
*/
- public function withoutOverlapping()
+ public function withoutOverlapping($expiresAt = 1440)
{
if (! isset($this->description)) {
throw new LogicException(
);
}
+ $this->withoutOverlapping = true;
+
+ $this->expiresAt = $expiresAt;
+
return $this->skip(function () {
return $this->mutex->exists($this);
});
}
+ /**
+ * Allow the event to only run on one server for each cron expression.
+ *
+ * @return $this
+ *
+ * @throws \LogicException
+ */
+ public function onOneServer()
+ {
+ if (! isset($this->description)) {
+ throw new LogicException(
+ "A scheduled event name is required to only run on one server. Use the 'name' method before 'onOneServer'."
+ );
+ }
+
+ $this->onOneServer = true;
+
+ return $this;
+ }
+
/**
* Get the mutex name for the scheduled command.
*
namespace Illuminate\Console\Scheduling;
use Illuminate\Console\Application;
-use Symfony\Component\Process\ProcessUtils;
+use Illuminate\Support\ProcessUtils;
class CommandBuilder
{
{
if ($event->runInBackground) {
return $this->buildBackgroundCommand($event);
- } else {
- return $this->buildForegroundCommand($event);
}
+
+ return $this->buildForegroundCommand($event);
}
/**
namespace Illuminate\Console\Scheduling;
use Closure;
-use Carbon\Carbon;
use Cron\CronExpression;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Carbon;
use GuzzleHttp\Client as HttpClient;
use Illuminate\Contracts\Mail\Mailer;
use Symfony\Component\Process\Process;
*
* @var string
*/
- public $expression = '* * * * * *';
+ public $expression = '* * * * *';
/**
* The timezone the date should be evaluated on.
*/
public $withoutOverlapping = false;
+ /**
+ * Indicates if the command should only be allowed to run on one server for each cron expression.
+ *
+ * @var bool
+ */
+ public $onOneServer = false;
+
+ /**
+ * The amount of time the mutex should be valid.
+ *
+ * @var int
+ */
+ public $expiresAt = 1440;
+
/**
* Indicates if the command should run in background.
*
public $description;
/**
- * The mutex implementation.
+ * The event mutex implementation.
*
- * @var \Illuminate\Console\Scheduling\Mutex
+ * @var \Illuminate\Console\Scheduling\EventMutex
*/
public $mutex;
* @param string $command
* @return void
*/
- public function __construct(Mutex $mutex, $command)
+ public function __construct(EventMutex $mutex, $command)
{
$this->mutex = $mutex;
$this->command = $command;
{
$this->ensureOutputIsBeingCapturedForEmail();
- $addresses = is_array($addresses) ? $addresses : func_get_args();
+ $addresses = Arr::wrap($addresses);
return $this->then(function (Mailer $mailer) use ($addresses, $onlyIfOutputExists) {
$this->emailOutput($mailer, $addresses, $onlyIfOutputExists);
return $this->description;
}
- return 'Scheduled Job Output';
+ return "Scheduled Job Output For [{$this->command}]";
}
/**
});
}
+ /**
+ * Register a callback to ping a given URL before the job runs if the given condition is true.
+ *
+ * @param bool $value
+ * @param string $url
+ * @return $this
+ */
+ public function pingBeforeIf($value, $url)
+ {
+ return $value ? $this->pingBefore($url) : $this;
+ }
+
/**
* Register a callback to ping a given URL after the job runs.
*
});
}
+ /**
+ * Register a callback to ping a given URL after the job runs if the given condition is true.
+ *
+ * @param bool $value
+ * @param string $url
+ * @return $this
+ */
+ public function thenPingIf($value, $url)
+ {
+ return $value ? $this->thenPing($url) : $this;
+ }
+
/**
* State that the command should run in background.
*
/**
* Do not allow the event to overlap each other.
*
+ * @param int $expiresAt
* @return $this
*/
- public function withoutOverlapping()
+ public function withoutOverlapping($expiresAt = 1440)
{
$this->withoutOverlapping = true;
+ $this->expiresAt = $expiresAt;
+
return $this->then(function () {
$this->mutex->forget($this);
})->skip(function () {
});
}
+ /**
+ * Allow the event to only run on one server for each cron expression.
+ *
+ * @return $this
+ */
+ public function onOneServer()
+ {
+ $this->onOneServer = true;
+
+ return $this;
+ }
+
/**
* Register a callback to further filter the schedule.
*
- * @param \Closure $callback
+ * @param \Closure|bool $callback
* @return $this
*/
- public function when(Closure $callback)
+ public function when($callback)
{
- $this->filters[] = $callback;
+ $this->filters[] = is_callable($callback) ? $callback : function () use ($callback) {
+ return $callback;
+ };
return $this;
}
/**
* Register a callback to further filter the schedule.
*
- * @param \Closure $callback
+ * @param \Closure|bool $callback
* @return $this
*/
- public function skip(Closure $callback)
+ public function skip($callback)
{
- $this->rejects[] = $callback;
+ $this->rejects[] = is_callable($callback) ? $callback : function () use ($callback) {
+ return $callback;
+ };
return $this;
}
* @param \DateTime|string $currentTime
* @param int $nth
* @param bool $allowCurrentDate
- * @return \Carbon\Carbon
+ * @return \Illuminate\Support\Carbon
*/
public function nextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
{
- return Carbon::instance($nextDue = CronExpression::factory(
+ return Carbon::instance(CronExpression::factory(
$this->getExpression()
)->getNextRunDate($currentTime, $nth, $allowCurrentDate));
}
}
/**
- * Set the mutex implementation to be used.
+ * Set the event mutex implementation to be used.
*
- * @param \Illuminate\Console\Scheduling\Mutex $mutex
+ * @param \Illuminate\Console\Scheduling\EventMutex $mutex
* @return $this
*/
- public function preventOverlapsUsing(Mutex $mutex)
+ public function preventOverlapsUsing(EventMutex $mutex)
{
$this->mutex = $mutex;
--- /dev/null
+<?php
+
+namespace Illuminate\Console\Scheduling;
+
+interface EventMutex
+{
+ /**
+ * Attempt to obtain an event mutex for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return bool
+ */
+ public function create(Event $event);
+
+ /**
+ * Determine if an event mutex exists for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return bool
+ */
+ public function exists(Event $event);
+
+ /**
+ * Clear the event mutex for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return void
+ */
+ public function forget(Event $event);
+}
namespace Illuminate\Console\Scheduling;
-use Carbon\Carbon;
+use Illuminate\Support\Carbon;
trait ManagesFrequencies
{
private function inTimeInterval($startTime, $endTime)
{
return function () use ($startTime, $endTime) {
- $now = Carbon::now()->getTimestamp();
-
- return $now >= strtotime($startTime) && $now <= strtotime($endTime);
+ return Carbon::now($this->timezone)->between(
+ Carbon::parse($startTime, $this->timezone),
+ Carbon::parse($endTime, $this->timezone),
+ true
+ );
};
}
+ /**
+ * Schedule the event to run every minute.
+ *
+ * @return $this
+ */
+ public function everyMinute()
+ {
+ return $this->spliceIntoPosition(1, '*');
+ }
+
+ /**
+ * Schedule the event to run every five minutes.
+ *
+ * @return $this
+ */
+ public function everyFiveMinutes()
+ {
+ return $this->spliceIntoPosition(1, '*/5');
+ }
+
+ /**
+ * Schedule the event to run every ten minutes.
+ *
+ * @return $this
+ */
+ public function everyTenMinutes()
+ {
+ return $this->spliceIntoPosition(1, '*/10');
+ }
+
+ /**
+ * Schedule the event to run every fifteen minutes.
+ *
+ * @return $this
+ */
+ public function everyFifteenMinutes()
+ {
+ return $this->spliceIntoPosition(1, '*/15');
+ }
+
+ /**
+ * Schedule the event to run every thirty minutes.
+ *
+ * @return $this
+ */
+ public function everyThirtyMinutes()
+ {
+ return $this->spliceIntoPosition(1, '0,30');
+ }
+
/**
* Schedule the event to run hourly.
*
}
/**
- * Schedule the event to run quarterly.
+ * Schedule the event to run twice monthly.
*
+ * @param int $first
+ * @param int $second
* @return $this
*/
- public function quarterly()
+ public function twiceMonthly($first = 1, $second = 16)
{
+ $days = $first.','.$second;
+
return $this->spliceIntoPosition(1, 0)
- ->spliceIntoPosition(2, 0)
- ->spliceIntoPosition(3, 1)
- ->spliceIntoPosition(4, '*/3');
+ ->spliceIntoPosition(2, 0)
+ ->spliceIntoPosition(3, $days);
}
/**
- * Schedule the event to run yearly.
+ * Schedule the event to run quarterly.
*
* @return $this
*/
- public function yearly()
+ public function quarterly()
{
return $this->spliceIntoPosition(1, 0)
->spliceIntoPosition(2, 0)
->spliceIntoPosition(3, 1)
- ->spliceIntoPosition(4, 1);
+ ->spliceIntoPosition(4, '1-12/3');
}
/**
- * Schedule the event to run every minute.
- *
- * @return $this
- */
- public function everyMinute()
- {
- return $this->spliceIntoPosition(1, '*');
- }
-
- /**
- * Schedule the event to run every five minutes.
- *
- * @return $this
- */
- public function everyFiveMinutes()
- {
- return $this->spliceIntoPosition(1, '*/5');
- }
-
- /**
- * Schedule the event to run every ten minutes.
- *
- * @return $this
- */
- public function everyTenMinutes()
- {
- return $this->spliceIntoPosition(1, '*/10');
- }
-
- /**
- * Schedule the event to run every thirty minutes.
+ * Schedule the event to run yearly.
*
* @return $this
*/
- public function everyThirtyMinutes()
+ public function yearly()
{
- return $this->spliceIntoPosition(1, '0,30');
+ return $this->spliceIntoPosition(1, 0)
+ ->spliceIntoPosition(2, 0)
+ ->spliceIntoPosition(3, 1)
+ ->spliceIntoPosition(4, 1);
}
/**
+++ /dev/null
-<?php
-
-namespace Illuminate\Console\Scheduling;
-
-interface Mutex
-{
- /**
- * Attempt to obtain a mutex for the given event.
- *
- * @param \Illuminate\Console\Scheduling\Event $event
- * @return bool
- */
- public function create(Event $event);
-
- /**
- * Determine if a mutex exists for the given event.
- *
- * @param \Illuminate\Console\Scheduling\Event $event
- * @return bool
- */
- public function exists(Event $event);
-
- /**
- * Clear the mutex for the given event.
- *
- * @param \Illuminate\Console\Scheduling\Event $event
- * @return void
- */
- public function forget(Event $event);
-}
namespace Illuminate\Console\Scheduling;
+use DateTimeInterface;
use Illuminate\Console\Application;
use Illuminate\Container\Container;
-use Symfony\Component\Process\ProcessUtils;
+use Illuminate\Support\ProcessUtils;
+use Illuminate\Contracts\Queue\ShouldQueue;
class Schedule
{
protected $events = [];
/**
- * The mutex implementation.
+ * The event mutex implementation.
*
- * @var \Illuminate\Console\Scheduling\Mutex
+ * @var \Illuminate\Console\Scheduling\EventMutex
*/
- protected $mutex;
+ protected $eventMutex;
/**
- * Create a new event instance.
+ * The scheduling mutex implementation.
+ *
+ * @var \Illuminate\Console\Scheduling\SchedulingMutex
+ */
+ protected $schedulingMutex;
+
+ /**
+ * Create a new schedule instance.
*
* @return void
*/
{
$container = Container::getInstance();
- $this->mutex = $container->bound(Mutex::class)
- ? $container->make(Mutex::class)
- : $container->make(CacheMutex::class);
+ $this->eventMutex = $container->bound(EventMutex::class)
+ ? $container->make(EventMutex::class)
+ : $container->make(CacheEventMutex::class);
+
+ $this->schedulingMutex = $container->bound(SchedulingMutex::class)
+ ? $container->make(SchedulingMutex::class)
+ : $container->make(CacheSchedulingMutex::class);
}
/**
*
* @param string|callable $callback
* @param array $parameters
- * @return \Illuminate\Console\Scheduling\Event
+ * @return \Illuminate\Console\Scheduling\CallbackEvent
*/
public function call($callback, array $parameters = [])
{
$this->events[] = $event = new CallbackEvent(
- $this->mutex, $callback, $parameters
+ $this->eventMutex, $callback, $parameters
);
return $event;
* Add a new job callback event to the schedule.
*
* @param object|string $job
- * @return \Illuminate\Console\Scheduling\Event
+ * @param string|null $queue
+ * @return \Illuminate\Console\Scheduling\CallbackEvent
*/
- public function job($job)
+ public function job($job, $queue = null)
{
- return $this->call(function () use ($job) {
- dispatch(is_string($job) ? resolve($job) : $job);
+ return $this->call(function () use ($job, $queue) {
+ $job = is_string($job) ? resolve($job) : $job;
+
+ if ($job instanceof ShouldQueue) {
+ dispatch($job)->onQueue($queue);
+ } else {
+ dispatch_now($job);
+ }
})->name(is_string($job) ? $job : get_class($job));
}
$command .= ' '.$this->compileParameters($parameters);
}
- $this->events[] = $event = new Event($this->mutex, $command);
+ $this->events[] = $event = new Event($this->eventMutex, $command);
return $event;
}
})->implode(' ');
}
+ /**
+ * Determine if the server is allowed to run this event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @param \DateTimeInterface $time
+ * @return bool
+ */
+ public function serverShouldRun(Event $event, DateTimeInterface $time)
+ {
+ return $this->schedulingMutex->create($event, $time);
+ }
+
/**
* Get all of the events on the schedule that are due.
*
* @param \Illuminate\Contracts\Foundation\Application $app
- * @return array
+ * @return \Illuminate\Support\Collection
*/
public function dueEvents($app)
{
{
return $this->events;
}
+
+ /**
+ * Specify the cache store that should be used to store mutexes.
+ *
+ * @param string $store
+ * @return $this
+ */
+ public function useCache($store)
+ {
+ if ($this->eventMutex instanceof CacheEventMutex) {
+ $this->eventMutex->useStore($store);
+ }
+
+ if ($this->schedulingMutex instanceof CacheSchedulingMutex) {
+ $this->schedulingMutex->useStore($store);
+ }
+
+ return $this;
+ }
}
*
* @return void
*/
- public function fire()
+ public function handle()
{
collect($this->schedule->events())->filter(function ($value) {
return $value->mutexName() == $this->argument('id');
namespace Illuminate\Console\Scheduling;
+use Illuminate\Support\Carbon;
use Illuminate\Console\Command;
class ScheduleRunCommand extends Command
*/
protected $schedule;
+ /**
+ * The 24 hour timestamp this scheduler command started running.
+ *
+ * @var \Illuminate\Support\Carbon;
+ */
+ protected $startedAt;
+
+ /**
+ * Check if any events ran.
+ *
+ * @var bool
+ */
+ protected $eventsRan = false;
+
/**
* Create a new command instance.
*
{
$this->schedule = $schedule;
+ $this->startedAt = Carbon::now();
+
parent::__construct();
}
*
* @return void
*/
- public function fire()
+ public function handle()
{
- $eventsRan = false;
-
foreach ($this->schedule->dueEvents($this->laravel) as $event) {
if (! $event->filtersPass($this->laravel)) {
continue;
}
- $this->line('<info>Running scheduled command:</info> '.$event->getSummaryForDisplay());
-
- $event->run($this->laravel);
+ if ($event->onOneServer) {
+ $this->runSingleServerEvent($event);
+ } else {
+ $this->runEvent($event);
+ }
- $eventsRan = true;
+ $this->eventsRan = true;
}
- if (! $eventsRan) {
+ if (! $this->eventsRan) {
$this->info('No scheduled commands are ready to run.');
}
}
+
+ /**
+ * Run the given single server event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return void
+ */
+ protected function runSingleServerEvent($event)
+ {
+ if ($this->schedule->serverShouldRun($event, $this->startedAt)) {
+ $this->runEvent($event);
+ } else {
+ $this->line('<info>Skipping command (has already run on another server):</info> '.$event->getSummaryForDisplay());
+ }
+ }
+
+ /**
+ * Run the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @return void
+ */
+ protected function runEvent($event)
+ {
+ $this->line('<info>Running scheduled command:</info> '.$event->getSummaryForDisplay());
+
+ $event->run($this->laravel);
+
+ $this->eventsRan = true;
+ }
}
--- /dev/null
+<?php
+
+namespace Illuminate\Console\Scheduling;
+
+use DateTimeInterface;
+
+interface SchedulingMutex
+{
+ /**
+ * Attempt to obtain a scheduling mutex for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @param \DateTimeInterface $time
+ * @return bool
+ */
+ public function create(Event $event, DateTimeInterface $time);
+
+ /**
+ * Determine if a scheduling mutex exists for the given event.
+ *
+ * @param \Illuminate\Console\Scheduling\Event $event
+ * @param \DateTimeInterface $time
+ * @return bool
+ */
+ public function exists(Event $event, DateTimeInterface $time);
+}
}
],
"require": {
- "php": ">=5.6.4",
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "nesbot/carbon": "~1.20",
- "symfony/console": "~3.2"
+ "php": "^7.1.3",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "symfony/console": "~4.0"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"suggest": {
+ "dragonmantank/cron-expression": "Required to use scheduling component (~2.0).",
"guzzlehttp/guzzle": "Required to use the ping methods on schedules (~6.0).",
- "mtdowling/cron-expression": "Required to use scheduling component (~1.0).",
- "symfony/process": "Required to use scheduling component (~3.2)."
+ "symfony/process": "Required to use scheduling component (~4.0)."
},
"config": {
"sort-packages": true
/**
* Get all dependencies for a given method.
*
- * @param \Illuminate\Container\Container
+ * @param \Illuminate\Container\Container $container
* @param callable|string $callback
* @param array $parameters
* @return array
$this->isAlias($abstract);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function has($id)
+ {
+ return $this->bound($id);
+ }
+
/**
* Determine if the given abstract type has been resolved.
*
/**
* Register a binding with the container.
*
- * @param string|array $abstract
+ * @param string $abstract
* @param \Closure|string|null $concrete
* @param bool $shared
* @return void
return $container->build($concrete);
}
- return $container->makeWith($concrete, $parameters);
+ return $container->make($concrete, $parameters);
};
}
/**
* Bind a callback to resolve with Container::call.
*
- * @param string $method
+ * @param array|string $method
* @param \Closure $callback
* @return void
*/
public function bindMethod($method, $callback)
{
- $this->methodBindings[$method] = $callback;
+ $this->methodBindings[$this->parseBindMethod($method)] = $callback;
+ }
+
+ /**
+ * Get the method to be bound in class@method format.
+ *
+ * @param array|string $method
+ * @return string
+ */
+ protected function parseBindMethod($method)
+ {
+ if (is_array($method)) {
+ return $method[0].'@'.$method[1];
+ }
+
+ return $method;
}
/**
/**
* Register a shared binding in the container.
*
- * @param string|array $abstract
+ * @param string $abstract
* @param \Closure|string|null $concrete
* @return void
*/
*
* @param string $abstract
* @param mixed $instance
- * @return void
+ * @return mixed
*/
public function instance($abstract, $instance)
{
if ($isBound) {
$this->rebound($abstract);
}
+
+ return $instance;
}
/**
}
/**
- * Resolve the given type with the given parameter overrides.
+ * An alias function name for make().
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
- public function makeWith($abstract, array $parameters)
+ public function makeWith($abstract, array $parameters = [])
{
- return $this->resolve($abstract, $parameters);
+ return $this->make($abstract, $parameters);
}
/**
* Resolve the given type from the container.
*
* @param string $abstract
+ * @param array $parameters
* @return mixed
*/
- public function make($abstract)
+ public function make($abstract, array $parameters = [])
+ {
+ return $this->resolve($abstract, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($id)
{
- return $this->resolve($abstract);
+ if ($this->has($id)) {
+ return $this->resolve($id);
+ }
+
+ throw new EntryNotFoundException;
}
/**
// If the class is null, it means the dependency is a string or some other
// primitive type which we can not resolve since it is not a class and
// we will just bomb out with an error since we have no-where to go.
- $results[] = is_null($class = $dependency->getClass())
+ $results[] = is_null($dependency->getClass())
? $this->resolvePrimitive($dependency)
: $this->resolveClass($dependency);
}
}
/**
- * Determine if the given dependency has a parameter override from makeWith.
+ * Determine if the given dependency has a parameter override.
*
* @param \ReflectionParameter $dependency
* @return bool
/**
* Register a new resolving callback.
*
- * @param string $abstract
+ * @param \Closure|string $abstract
* @param \Closure|null $callback
* @return void
*/
/**
* Register a new after resolving callback for all types.
*
- * @param string $abstract
- * @param \Closure|null $callback
+ * @param \Closure|string $abstract
+ * @param \Closure|null $callback
* @return void
*/
public function afterResolving($abstract, Closure $callback = null)
--- /dev/null
+<?php
+
+namespace Illuminate\Container;
+
+use Exception;
+use Psr\Container\NotFoundExceptionInterface;
+
+class EntryNotFoundException extends Exception implements NotFoundExceptionInterface
+{
+ //
+}
}
],
"require": {
- "php": ">=5.6.4",
- "illuminate/contracts": "5.4.*"
+ "php": "^7.1.3",
+ "illuminate/contracts": "5.6.*",
+ "psr/container": "~1.0"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"config": {
public function denies($ability, $arguments = []);
/**
- * Determine if the given ability should be granted.
+ * Determine if all of the given abilities should be granted for the current user.
*
- * @param string $ability
+ * @param iterable|string $abilities
* @param array|mixed $arguments
* @return bool
*/
- public function check($ability, $arguments = []);
+ public function check($abilities, $arguments = []);
+
+ /**
+ * Determine if any one of the given abilities should be granted for the current user.
+ *
+ * @param iterable|string $abilities
+ * @param array|mixed $arguments
+ * @return bool
+ */
+ public function any($abilities, $arguments = []);
/**
* Determine if the given ability should be granted for the current user.
* @return static
*/
public function forUser($user);
+
+ /**
+ * Get all of the defined abilities.
+ *
+ * @return array
+ */
+ public function abilities();
}
/**
* Get a broadcaster implementation by name.
*
- * @param string $name
+ * @param string|null $name
* @return void
*/
public function connection($name = null);
namespace Illuminate\Contracts\Broadcasting;
+use Illuminate\Broadcasting\Channel;
+
interface ShouldBroadcast
{
/**
* Get the channels the event should broadcast on.
*
- * @return array
+ * @return Channel|Channel[]
*/
public function broadcastOn();
}
*/
public function dispatchNow($command, $handler = null);
+ /**
+ * Determine if the given command has a handler.
+ *
+ * @param mixed $command
+ * @return bool
+ */
+ public function hasCommandHandler($command);
+
+ /**
+ * Retrieve the handler for a command.
+ *
+ * @param mixed $command
+ * @return bool|mixed
+ */
+ public function getCommandHandler($command);
+
/**
* Set the pipes commands should be piped through before dispatching.
*
* @return $this
*/
public function pipeThrough(array $pipes);
+
+ /**
+ * Map a command to a handler.
+ *
+ * @param array $map
+ * @return $this
+ */
+ public function map(array $map);
}
* Get a cache store instance by name.
*
* @param string|null $name
- * @return mixed
+ * @return \Illuminate\Contracts\Cache\Repository
*/
public function store($name = null);
}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+interface Lock
+{
+ /**
+ * Attempt to acquire the lock.
+ *
+ * @param callable|null $callback
+ * @return bool
+ */
+ public function get($callback = null);
+
+ /**
+ * Attempt to acquire the lock for the given number of seconds.
+ *
+ * @param int $seconds
+ * @param callable|null $callback
+ * @return bool
+ */
+ public function block($seconds, $callback = null);
+
+ /**
+ * Release the lock.
+ *
+ * @return void
+ */
+ public function release();
+}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+interface LockProvider
+{
+ /**
+ * Get a lock instance.
+ *
+ * @param string $name
+ * @param int $seconds
+ * @return \Illuminate\Contracts\Cache\Lock
+ */
+ public function lock($name, $seconds = 0);
+}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+use Exception;
+
+class LockTimeoutException extends Exception
+{
+ //
+}
namespace Illuminate\Contracts\Cache;
use Closure;
+use Psr\SimpleCache\CacheInterface;
-interface Repository
+interface Repository extends CacheInterface
{
/**
* Determine if an item exists in the cache.
*
* @param string $key
* @param mixed $value
- * @param \DateTime|float|int $minutes
+ * @param \DateTimeInterface|\DateInterval|float|int $minutes
* @return void
*/
public function put($key, $value, $minutes);
*
* @param string $key
* @param mixed $value
- * @param \DateTime|float|int $minutes
+ * @param \DateTimeInterface|\DateInterval|float|int $minutes
* @return bool
*/
public function add($key, $value, $minutes);
* Get an item from the cache, or store the default value.
*
* @param string $key
- * @param \DateTime|float|int $minutes
+ * @param \DateTimeInterface|\DateInterval|float|int $minutes
* @param \Closure $callback
* @return mixed
*/
* @return bool
*/
public function forget($key);
+
+ /**
+ * Get the cache store implementation.
+ *
+ * @return \Illuminate\Contracts\Cache\Store
+ */
+ public function getStore();
}
/**
* Get the specified configuration value.
*
- * @param string $key
+ * @param array|string $key
* @param mixed $default
* @return mixed
*/
interface Application
{
/**
- * Call a console application command.
+ * Run an Artisan console command by name.
*
* @param string $command
* @param array $parameters
+ * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
* @return int
*/
- public function call($command, array $parameters = []);
+ public function call($command, array $parameters = [], $outputBuffer = null);
/**
* Get the output from the last command.
* Handle an incoming console command.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
- * @param \Symfony\Component\Console\Output\OutputInterface $output
+ * @param \Symfony\Component\Console\Output\OutputInterface|null $output
* @return int
*/
public function handle($input, $output = null);
*
* @param string $command
* @param array $parameters
+ * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
* @return int
*/
- public function call($command, array $parameters = []);
+ public function call($command, array $parameters = [], $outputBuffer = null);
/**
* Queue an Artisan console command by name.
namespace Illuminate\Contracts\Container;
use Exception;
+use Psr\Container\ContainerExceptionInterface;
-class BindingResolutionException extends Exception
+class BindingResolutionException extends Exception implements ContainerExceptionInterface
{
//
}
namespace Illuminate\Contracts\Container;
use Closure;
+use Psr\Container\ContainerInterface;
-interface Container
+interface Container extends ContainerInterface
{
/**
* Determine if the given abstract type has been bound.
/**
* Resolve all of the bindings for a given tag.
*
- * @param array $tag
+ * @param string $tag
* @return array
*/
public function tagged($tag);
/**
* Register a binding with the container.
*
- * @param string|array $abstract
+ * @param string $abstract
* @param \Closure|string|null $concrete
* @param bool $shared
* @return void
/**
* Register a shared binding in the container.
*
- * @param string|array $abstract
+ * @param string $abstract
* @param \Closure|string|null $concrete
* @return void
*/
*
* @param string $abstract
* @param mixed $instance
- * @return void
+ * @return mixed
*/
public function instance($abstract, $instance);
* Resolve the given type from the container.
*
* @param string $abstract
+ * @param array $parameters
* @return mixed
*/
- public function make($abstract);
+ public function make($abstract, array $parameters = []);
/**
* Call the given Closure / class@method and inject its dependencies.
/**
* Register a new resolving callback.
*
- * @param string $abstract
+ * @param \Closure|string $abstract
* @param \Closure|null $callback
* @return void
*/
/**
* Register a new after resolving callback.
*
- * @param string $abstract
+ * @param \Closure|string $abstract
* @param \Closure|null $callback
* @return void
*/
* @param string $domain
* @param bool $secure
* @param bool $httpOnly
+ * @param bool $raw
+ * @param string|null $sameSite
* @return \Symfony\Component\HttpFoundation\Cookie
*/
- public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true);
+ public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true, $raw = false, $sameSite = null);
/**
* Create a cookie that lasts "forever" (five years).
* @param string $domain
* @param bool $secure
* @param bool $httpOnly
+ * @param bool $raw
+ * @param string|null $sameSite
* @return \Symfony\Component\HttpFoundation\Cookie
*/
- public function forever($name, $value, $path = null, $domain = null, $secure = false, $httpOnly = true);
+ public function forever($name, $value, $path = null, $domain = null, $secure = false, $httpOnly = true, $raw = false, $sameSite = null);
/**
* Expire the given cookie.
*/
public $id;
+ /**
+ * The relationships loaded on the model.
+ *
+ * @var array
+ */
+ public $relations;
+
+ /**
+ * The connection name of the model.
+ *
+ * @var string|null
+ */
+ public $connection;
+
/**
* Create a new model identifier.
*
* @param string $class
* @param mixed $id
+ * @param array $relations
+ * @param mixed $connection
* @return void
*/
- public function __construct($class, $id)
+ public function __construct($class, $id, array $relations, $connection)
{
$this->id = $id;
$this->class = $class;
+ $this->relations = $relations;
+ $this->connection = $connection;
}
}
*
* @param string $path
* @param string|resource $contents
- * @param string $visibility
+ * @param mixed $options
* @return bool
*/
- public function put($path, $contents, $visibility = null);
+ public function put($path, $contents, $options = []);
/**
* Get the visibility for the given path.
*/
public function environment();
+ /**
+ * Determine if the application is running in the console.
+ *
+ * @return bool
+ */
+ public function runningInConsole();
+
+ /**
+ * Determine if the application is running unit tests.
+ *
+ * @return bool
+ */
+ public function runningUnitTests();
+
/**
* Determine if the application is currently down for maintenance.
*
* Register a deferred provider and service.
*
* @param string $provider
- * @param string $service
+ * @param string|null $service
* @return void
*/
public function registerDeferredProvider($provider, $service = null);
* @return string
*/
public function getCachedServicesPath();
+
+ /**
+ * Get the path to the cached packages.php file.
+ *
+ * @return string
+ */
+ public function getCachedPackagesPath();
}
interface Hasher
{
+ /**
+ * Get information about the given hashed value.
+ *
+ * @param string $hashedValue
+ * @return array
+ */
+ public function info($hashedValue);
+
/**
* Hash the given value.
*
+++ /dev/null
-<?php
-
-namespace Illuminate\Contracts\Logging;
-
-interface Log
-{
- /**
- * Log an alert message to the logs.
- *
- * @param string $message
- * @param array $context
- * @return void
- */
- public function alert($message, array $context = []);
-
- /**
- * Log a critical message to the logs.
- *
- * @param string $message
- * @param array $context
- * @return void
- */
- public function critical($message, array $context = []);
-
- /**
- * Log an error message to the logs.
- *
- * @param string $message
- * @param array $context
- * @return void
- */
- public function error($message, array $context = []);
-
- /**
- * Log a warning message to the logs.
- *
- * @param string $message
- * @param array $context
- * @return void
- */
- public function warning($message, array $context = []);
-
- /**
- * Log a notice to the logs.
- *
- * @param string $message
- * @param array $context
- * @return void
- */
- public function notice($message, array $context = []);
-
- /**
- * Log an informational message to the logs.
- *
- * @param string $message
- * @param array $context
- * @return void
- */
- public function info($message, array $context = []);
-
- /**
- * Log a debug message to the logs.
- *
- * @param string $message
- * @param array $context
- * @return void
- */
- public function debug($message, array $context = []);
-
- /**
- * Log a message to the logs.
- *
- * @param string $level
- * @param string $message
- * @param array $context
- * @return void
- */
- public function log($level, $message, array $context = []);
-
- /**
- * Register a file log handler.
- *
- * @param string $path
- * @param string $level
- * @return void
- */
- public function useFiles($path, $level = 'debug');
-
- /**
- * Register a daily file log handler.
- *
- * @param string $path
- * @param int $days
- * @param string $level
- * @return void
- */
- public function useDailyFiles($path, $days = 0, $level = 'debug');
-}
/**
* Queue a new e-mail message for sending.
*
- * @param string|array $view
- * @param array $data
- * @param \Closure|string $callback
+ * @param string|array|\Illuminate\Contracts\Mail\Mailable $view
* @param string $queue
* @return mixed
*/
- public function queue($view, array $data, $callback, $queue = null);
+ public function queue($view, $queue = null);
/**
* Queue a new e-mail message for sending after (n) seconds.
*
- * @param int $delay
- * @param string|array $view
- * @param array $data
- * @param \Closure|string $callback
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @param string|array|\Illuminate\Contracts\Mail\Mailable $view
* @param string $queue
* @return mixed
*/
- public function later($delay, $view, array $data, $callback, $queue = null);
+ public function later($delay, $view, $queue = null);
}
/**
* Send the message using the given mailer.
*
- * @param Mailer $mailer
+ * @param \Illuminate\Contracts\Mail\Mailer $mailer
* @return void
*/
public function send(Mailer $mailer);
/**
* Queue the given message.
*
- * @param Queue $queue
+ * @param \Illuminate\Contracts\Queue\Factory $queue
* @return mixed
*/
public function queue(Queue $queue);
* Deliver the queued message after the given delay.
*
* @param \DateTime|int $delay
- * @param Queue $queue
+ * @param \Illuminate\Contracts\Queue\Factory $queue
* @return mixed
*/
public function later($delay, Queue $queue);
namespace Illuminate\Contracts\Mail;
+use Illuminate\Contracts\Mail\Mailable as MailableContract;
+
interface Mailer
{
+ /**
+ * Begin the process of mailing a mailable class instance.
+ *
+ * @param mixed $users
+ * @return \Illuminate\Mail\PendingMail
+ */
+ public function to($users);
+
+ /**
+ * Begin the process of mailing a mailable class instance.
+ *
+ * @param mixed $users
+ * @return \Illuminate\Mail\PendingMail
+ */
+ public function bcc($users);
+
/**
* Send a new message when only a raw text part.
*
* @param string $text
- * @param \Closure|string $callback
- * @return int
+ * @param mixed $callback
+ * @return void
*/
public function raw($text, $callback);
/**
* Send a new message using a view.
*
- * @param string|array $view
+ * @param string|array|MailableContract $view
* @param array $data
* @param \Closure|string $callback
* @return void
*/
public function isEmpty();
+ /**
+ * Determine if the list of items is not empty.
+ *
+ * @return bool
+ */
+ public function isNotEmpty();
+
/**
* Render the paginator using a given view.
*
interface Job
{
+ /**
+ * Get the job identifier.
+ *
+ * @return string
+ */
+ public function getJobId();
+
+ /**
+ * Get the decoded body of the job.
+ *
+ * @return array
+ */
+ public function payload();
+
/**
* Fire the job.
*
public function failed($e);
/**
- * The number of times to attempt a job.
+ * Get the number of times to attempt a job.
*
* @return int|null
*/
public function maxTries();
/**
- * The number of seconds the job can run.
+ * Get the number of seconds the job can run.
*
* @return int|null
*/
public function timeout();
+ /**
+ * Get the timestamp indicating when the job should timeout.
+ *
+ * @return int|null
+ */
+ public function timeoutAt();
+
/**
* Get the name of the queued job class.
*
*/
public function getQueue();
- /**
- * Get the raw body string for the job.
- *
- * @return string
- */
- public function getRawBody();
+ /**
+ * Get the raw body string for the job.
+ *
+ * @return string
+ */
+ public function getRawBody();
}
/**
* Push a new job onto the queue.
*
- * @param string $job
+ * @param string|object $job
* @param mixed $data
* @param string $queue
* @return mixed
* Push a new job onto the queue.
*
* @param string $queue
- * @param string $job
+ * @param string|object $job
* @param mixed $data
* @return mixed
*/
/**
* Push a new job onto the queue after a delay.
*
- * @param \DateTime|int $delay
- * @param string $job
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @param string|object $job
* @param mixed $data
* @param string $queue
* @return mixed
* Push a new job onto the queue after a delay.
*
* @param string $queue
- * @param \DateTime|int $delay
- * @param string $job
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @param string|object $job
* @param mixed $data
* @return mixed
*/
* @return array
*/
public function getQueueableIds();
+
+ /**
+ * Get the relationships of the entities being queued.
+ *
+ * @return array
+ */
+ public function getQueueableRelations();
+
+ /**
+ * Get the connection of the entities being queued.
+ *
+ * @return string|null
+ */
+ public function getQueueableConnection();
}
* @return mixed
*/
public function getQueueableId();
+
+ /**
+ * Get the relationships for the entity.
+ *
+ * @return array
+ */
+ public function getQueueableRelations();
+
+ /**
+ * Get the connection of the entity.
+ *
+ * @return string|null
+ */
+ public function getQueueableConnection();
}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Redis;
+
+use Closure;
+
+interface Connection
+{
+ /**
+ * Subscribe to a set of given channels for messages.
+ *
+ * @param array|string $channels
+ * @param \Closure $callback
+ * @return void
+ */
+ public function subscribe($channels, Closure $callback);
+
+ /**
+ * Subscribe to a set of given channels with wildcards.
+ *
+ * @param array|string $channels
+ * @param \Closure $callback
+ * @return void
+ */
+ public function psubscribe($channels, Closure $callback);
+
+ /**
+ * Run a command against the Redis database.
+ *
+ * @param string $method
+ * @param array $parameters
+ * @return mixed
+ */
+ public function command($method, array $parameters = []);
+}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Redis;
+
+use Exception;
+
+class LimiterTimeoutException extends Exception
+{
+ //
+}
* @param string $name
* @param string $controller
* @param array $options
- * @return void
+ * @return \Illuminate\Routing\PendingResourceRegistration
*/
public function resource($name, $controller, array $options = []);
*/
public function stream($callback, $status = 200, array $headers = []);
+ /**
+ * Return a new streamed response as a file download from the application.
+ *
+ * @param \Closure $callback
+ * @param string|null $name
+ * @param array $headers
+ * @param string|null $disposition
+ * @return \Symfony\Component\HttpFoundation\StreamedResponse
+ */
+ public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment');
+
/**
* Create a new file download response.
*
* @param \SplFileInfo|string $file
- * @param string $name
+ * @param string|null $name
* @param array $headers
* @param string|null $disposition
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
* @return string
*/
public function getRouteKeyName();
+
+ /**
+ * Retrieve the model for a bound value.
+ *
+ * @param mixed $value
+ * @return \Illuminate\Database\Eloquent\Model|null
+ */
+ public function resolveRouteBinding($value);
}
namespace Illuminate\Contracts\Support;
-interface MessageBag
+interface MessageBag extends Arrayable
{
/**
* Get the keys present in the message bag.
*/
public function all($format = null);
+ /**
+ * Get the raw messages in the container.
+ *
+ * @return array
+ */
+ public function getMessages();
+
/**
* Get the default message format.
*
public function isEmpty();
/**
- * Get the number of messages in the container.
+ * Determine if the message bag has any messages.
*
- * @return int
+ * @return bool
*/
- public function count();
+ public function isNotEmpty();
/**
- * Get the instance as an array.
+ * Get the number of messages in the container.
*
- * @return array
+ * @return int
*/
- public function toArray();
+ public function count();
}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface Responsable
+{
+ /**
+ * Create an HTTP response that represents the object.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function toResponse($request);
+}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Translation;
+
+interface Loader
+{
+ /**
+ * Load the messages for the given locale.
+ *
+ * @param string $locale
+ * @param string $group
+ * @param string $namespace
+ * @return array
+ */
+ public function load($locale, $group, $namespace = null);
+
+ /**
+ * Add a new namespace to the loader.
+ *
+ * @param string $namespace
+ * @param string $hint
+ * @return void
+ */
+ public function addNamespace($namespace, $hint);
+
+ /**
+ * Add a new JSON path to the loader.
+ *
+ * @param string $path
+ * @return void
+ */
+ public function addJsonPath($path);
+
+ /**
+ * Get an array of all the registered namespaces.
+ *
+ * @return array
+ */
+ public function namespaces();
+}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface ImplicitRule extends Rule
+{
+ //
+}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface Rule
+{
+ /**
+ * Determine if the validation rule passes.
+ *
+ * @param string $attribute
+ * @param mixed $value
+ * @return bool
+ */
+ public function passes($attribute, $value);
+
+ /**
+ * Get the validation error message.
+ *
+ * @return string
+ */
+ public function message();
+}
*
* @return void
*/
- public function validate();
+ public function validateResolved();
}
* @return $this
*/
public function after($callback);
+
+ /**
+ * Get all of the validation error messages.
+ *
+ * @return \Illuminate\Support\MessageBag
+ */
+ public function errors();
}
--- /dev/null
+<?php
+
+namespace Illuminate\Contracts\View;
+
+interface Engine
+{
+ /**
+ * Get the evaluated contents of the view.
+ *
+ * @param string $path
+ * @param array $data
+ * @return string
+ */
+ public function get($path, array $data = []);
+}
}
],
"require": {
- "php": ">=5.6.4"
+ "php": "^7.1.3",
+ "psr/container": "~1.0",
+ "psr/simple-cache": "~1.0"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"config": {
+++ /dev/null
-<?php
-
-namespace Illuminate\Events;
-
-use Illuminate\Contracts\Queue\Job;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Contracts\Container\Container;
-
-class CallQueuedHandler
-{
- /**
- * The container instance.
- *
- * @var \Illuminate\Contracts\Container\Container
- */
- protected $container;
-
- /**
- * Create a new job instance.
- *
- * @param \Illuminate\Contracts\Container\Container $container
- * @return void
- */
- public function __construct(Container $container)
- {
- $this->container = $container;
- }
-
- /**
- * Handle the queued job.
- *
- * @param \Illuminate\Contracts\Queue\Job $job
- * @param array $data
- * @return void
- */
- public function call(Job $job, array $data)
- {
- $handler = $this->setJobInstanceIfNecessary(
- $job, $this->container->make($data['class'])
- );
-
- call_user_func_array(
- [$handler, $data['method']], unserialize($data['data'])
- );
-
- if (! $job->isDeletedOrReleased()) {
- $job->delete();
- }
- }
-
- /**
- * Set the job instance of the given class if necessary.
- *
- * @param \Illuminate\Contracts\Queue\Job $job
- * @param mixed $instance
- * @return mixed
- */
- protected function setJobInstanceIfNecessary(Job $job, $instance)
- {
- if (in_array(InteractsWithQueue::class, class_uses_recursive(get_class($instance)))) {
- $instance->setJob($job);
- }
-
- return $instance;
- }
-
- /**
- * Call the failed method on the job instance.
- *
- * The event instance and the exception will be passed.
- *
- * @param array $data
- * @param \Exception $e
- * @return void
- */
- public function failed(array $data, $e)
- {
- $handler = $this->container->make($data['class']);
-
- $parameters = array_merge(unserialize($data['data']), [$e]);
-
- if (method_exists($handler, 'failed')) {
- call_user_func_array([$handler, 'failed'], $parameters);
- }
- }
-}
*/
public $tries;
+ /**
+ * The timestamp indicating when the job should timeout.
+ *
+ * @var int
+ */
+ public $timeoutAt;
+
/**
* The number of seconds the job can run before timing out.
*
{
return $this->class;
}
+
+ /**
+ * Prepare the instance for cloning.
+ *
+ * @return void
+ */
+ public function __clone()
+ {
+ $this->data = array_map(function ($data) {
+ return is_object($data) ? clone $data : $data;
+ }, $this->data);
+ }
}
use Exception;
use ReflectionClass;
+use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Container\Container;
use Illuminate\Contracts\Queue\ShouldQueue;
*/
protected $wildcards = [];
+ /**
+ * The cached wildcard listeners.
+ *
+ * @var array
+ */
+ protected $wildcardsCache = [];
+
/**
* The queue resolver instance.
*
protected function setupWildcardListen($event, $listener)
{
$this->wildcards[$event][] = $this->makeListener($listener, true);
+
+ $this->wildcardsCache = [];
}
/**
list($payload, $event) = [[$event], get_class($event)];
}
- return [$event, array_wrap($payload)];
+ return [$event, Arr::wrap($payload)];
}
/**
*/
public function getListeners($eventName)
{
- $listeners = isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : [];
+ $listeners = $this->listeners[$eventName] ?? [];
$listeners = array_merge(
- $listeners, $this->getWildcardListeners($eventName)
+ $listeners,
+ $this->wildcardsCache[$eventName] ?? $this->getWildcardListeners($eventName)
);
return class_exists($eventName, false)
}
}
- return $wildcards;
+ return $this->wildcardsCache[$eventName] = $wildcards;
}
/**
/**
* Register an event listener with the dispatcher.
*
- * @param string|\Closure $listener
+ * @param \Closure|string $listener
* @param bool $wildcard
* @return \Closure
*/
return function ($event, $payload) use ($listener, $wildcard) {
if ($wildcard) {
return $listener($event, $payload);
- } else {
- return $listener(...array_values($payload));
}
+
+ return $listener(...array_values($payload));
};
}
return function ($event, $payload) use ($listener, $wildcard) {
if ($wildcard) {
return call_user_func($this->createClassCallable($listener), $event, $payload);
- } else {
- return call_user_func_array(
- $this->createClassCallable($listener), $payload
- );
}
+
+ return call_user_func_array(
+ $this->createClassCallable($listener), $payload
+ );
};
}
if ($this->handlerShouldBeQueued($class)) {
return $this->createQueuedHandlerCallable($class, $method);
- } else {
- return [$this->container->make($class), $method];
}
+
+ return [$this->container->make($class), $method];
}
/**
return is_object($a) ? clone $a : $a;
}, func_get_args());
- if (method_exists($class, 'queue')) {
- $this->callQueueMethodOnHandler($class, $method, $arguments);
- } else {
+ if ($this->handlerWantsToBeQueued($class, $arguments)) {
$this->queueHandler($class, $method, $arguments);
}
};
}
/**
- * Call the queue method on the handler class.
+ * Determine if the event handler wants to be queued.
*
* @param string $class
- * @param string $method
* @param array $arguments
- * @return void
+ * @return bool
*/
- protected function callQueueMethodOnHandler($class, $method, $arguments)
+ protected function handlerWantsToBeQueued($class, $arguments)
{
- $handler = (new ReflectionClass($class))->newInstanceWithoutConstructor();
+ if (method_exists($class, 'shouldQueue')) {
+ return $this->container->make($class)->shouldQueue($arguments[0]);
+ }
- $handler->queue($this->resolveQueue(), 'Illuminate\Events\CallQueuedHandler@call', [
- 'class' => $class, 'method' => $method, 'data' => serialize($arguments),
- ]);
+ return true;
}
/**
list($listener, $job) = $this->createListenerAndJob($class, $method, $arguments);
$connection = $this->resolveQueue()->connection(
- isset($listener->connection) ? $listener->connection : null
+ $listener->connection ?? null
);
- $queue = isset($listener->queue) ? $listener->queue : null;
+ $queue = $listener->queue ?? null;
isset($listener->delay)
? $connection->laterOn($queue, $listener->delay, $job)
{
$listener = (new ReflectionClass($class))->newInstanceWithoutConstructor();
- return [$listener, $this->propogateListenerOptions(
+ return [$listener, $this->propagateListenerOptions(
$listener, new CallQueuedListener($class, $method, $arguments)
)];
}
/**
- * Propogate listener options to the job.
+ * Propagate listener options to the job.
*
* @param mixed $listener
* @param mixed $job
* @return mixed
*/
- protected function propogateListenerOptions($listener, $job)
+ protected function propagateListenerOptions($listener, $job)
{
return tap($job, function ($job) use ($listener) {
- $job->tries = isset($listener->tries) ? $listener->tries : null;
- $job->timeout = isset($listener->timeout) ? $listener->timeout : null;
+ $job->tries = $listener->tries ?? null;
+ $job->timeout = $listener->timeout ?? null;
+ $job->timeoutAt = method_exists($listener, 'retryUntil')
+ ? $listener->retryUntil() : null;
});
}
}
],
"require": {
- "php": ">=5.6.4",
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*"
+ "php": "^7.1.3",
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"config": {
--- /dev/null
+<?php
+
+namespace Illuminate\Filesystem;
+
+use Illuminate\Contracts\Cache\Repository;
+use League\Flysystem\Cached\Storage\AbstractCache;
+
+class Cache extends AbstractCache
+{
+ /**
+ * The cache repository implementation.
+ *
+ * @var \Illuminate\Contracts\Cache\Repository
+ */
+ protected $repository;
+
+ /**
+ * The cache key.
+ *
+ * @var string
+ */
+ protected $key;
+
+ /**
+ * The cache expiration time in minutes.
+ *
+ * @var int
+ */
+ protected $expire;
+
+ /**
+ * Create a new cache instance.
+ *
+ * @param \Illuminate\Contracts\Cache\Repository $repository
+ * @param string $key
+ * @param int|null $expire
+ */
+ public function __construct(Repository $repository, $key = 'flysystem', $expire = null)
+ {
+ $this->key = $key;
+ $this->repository = $repository;
+
+ if (! is_null($expire)) {
+ $this->expire = (int) ceil($expire / 60);
+ }
+ }
+
+ /**
+ * Load the cache.
+ *
+ * @return void
+ */
+ public function load()
+ {
+ $contents = $this->repository->get($this->key);
+
+ if (! is_null($contents)) {
+ $this->setFromStorage($contents);
+ }
+ }
+
+ /**
+ * Persist the cache.
+ *
+ * @return void
+ */
+ public function save()
+ {
+ $contents = $this->getForStorage();
+
+ if (! is_null($this->expire)) {
+ $this->repository->put($this->key, $contents, $this->expire);
+ } else {
+ $this->repository->forever($this->key, $contents);
+ }
+ }
+}
* Get an array of all files in a directory.
*
* @param string $directory
- * @return array
+ * @param bool $hidden
+ * @return \Symfony\Component\Finder\SplFileInfo[]
*/
- public function files($directory)
+ public function files($directory, $hidden = false)
{
- $glob = glob($directory.DIRECTORY_SEPARATOR.'*');
-
- if ($glob === false) {
- return [];
- }
-
- // To get the appropriate files, we'll simply glob the directory and filter
- // out any "files" that are not truly files so we do not end up with any
- // directories in our list, but only true files within the directory.
- return array_filter($glob, function ($file) {
- return filetype($file) == 'file';
- });
+ return iterator_to_array(
+ Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->depth(0)->sortByName(),
+ false
+ );
}
/**
*
* @param string $directory
* @param bool $hidden
- * @return array
+ * @return \Symfony\Component\Finder\SplFileInfo[]
*/
public function allFiles($directory, $hidden = false)
{
- return iterator_to_array(Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory), false);
+ return iterator_to_array(
+ Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->sortByName(),
+ false
+ );
}
/**
{
$directories = [];
- foreach (Finder::create()->in($directory)->directories()->depth(0) as $dir) {
+ foreach (Finder::create()->in($directory)->directories()->depth(0)->sortByName() as $dir) {
$directories[] = $dir->getPathname();
}
use Illuminate\Http\File;
use Illuminate\Support\Str;
use InvalidArgumentException;
+use Illuminate\Support\Carbon;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
use League\Flysystem\AdapterInterface;
use PHPUnit\Framework\Assert as PHPUnit;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
+use League\Flysystem\Cached\CachedAdapter;
use League\Flysystem\FileNotFoundException;
+use League\Flysystem\Rackspace\RackspaceAdapter;
use League\Flysystem\Adapter\Local as LocalAdapter;
+use Symfony\Component\HttpFoundation\StreamedResponse;
use Illuminate\Contracts\Filesystem\Cloud as CloudFilesystemContract;
use Illuminate\Contracts\Filesystem\Filesystem as FilesystemContract;
use Illuminate\Contracts\Filesystem\FileNotFoundException as ContractFileNotFoundException;
+/**
+ * @mixin \League\Flysystem\FilesystemInterface
+ */
class FilesystemAdapter implements FilesystemContract, CloudFilesystemContract
{
/**
return $this->driver->has($path);
}
+ /**
+ * Get the full path for the file at the given "short" path.
+ *
+ * @param string $path
+ * @return string
+ */
+ public function path($path)
+ {
+ return $this->driver->getAdapter()->getPathPrefix().$path;
+ }
+
/**
* Get the contents of a file.
*
}
}
+ /**
+ * Create a streamed response for a given file.
+ *
+ * @param string $path
+ * @param string|null $name
+ * @param array|null $headers
+ * @param string|null $disposition
+ * @return \Symfony\Component\HttpFoundation\StreamedResponse
+ */
+ public function response($path, $name = null, array $headers = [], $disposition = 'inline')
+ {
+ $response = new StreamedResponse;
+
+ $disposition = $response->headers->makeDisposition($disposition, $name ?? basename($path));
+
+ $response->headers->replace($headers + [
+ 'Content-Type' => $this->mimeType($path),
+ 'Content-Length' => $this->size($path),
+ 'Content-Disposition' => $disposition,
+ ]);
+
+ $response->setCallback(function () use ($path) {
+ $stream = $this->driver->readStream($path);
+ fpassthru($stream);
+ fclose($stream);
+ });
+
+ return $response;
+ }
+
+ /**
+ * Create a streamed download response for a given file.
+ *
+ * @param string $path
+ * @param string|null $name
+ * @param array|null $headers
+ * @return \Symfony\Component\HttpFoundation\StreamedResponse
+ */
+ public function download($path, $name = null, array $headers = [])
+ {
+ return $this->response($path, $name, $headers, 'attachment');
+ }
+
/**
* Write the contents of a file.
*
* @param string $path
* @param string|resource $contents
- * @param array $options
+ * @param mixed $options
* @return bool
*/
public function put($path, $contents, $options = [])
{
- if (is_string($options)) {
- $options = ['visibility' => $options];
- }
+ $options = is_string($options)
+ ? ['visibility' => $options]
+ : (array) $options;
// If the given contents is actually a file or uploaded file instance than we will
// automatically store the file using a stream. This provides a convenient path
{
$adapter = $this->driver->getAdapter();
+ if ($adapter instanceof CachedAdapter) {
+ $adapter = $adapter->getAdapter();
+ }
+
if (method_exists($adapter, 'getUrl')) {
return $adapter->getUrl($path);
+ } elseif (method_exists($this->driver, 'getUrl')) {
+ return $this->driver->getUrl($path);
} elseif ($adapter instanceof AwsS3Adapter) {
return $this->getAwsUrl($adapter, $path);
+ } elseif ($adapter instanceof RackspaceAdapter) {
+ return $this->getRackspaceUrl($adapter, $path);
} elseif ($adapter instanceof LocalAdapter) {
return $this->getLocalUrl($path);
} else {
*/
protected function getAwsUrl($adapter, $path)
{
+ // If an explicit base URL has been set on the disk configuration then we will use
+ // it as the base URL instead of the default path. This allows the developer to
+ // have full control over the base path for this filesystem's generated URLs.
+ if (! is_null($url = $this->driver->getConfig()->get('url'))) {
+ return $this->concatPathToUrl($url, $adapter->getPathPrefix().$path);
+ }
+
return $adapter->getClient()->getObjectUrl(
$adapter->getBucket(), $adapter->getPathPrefix().$path
);
}
+ /**
+ * Get the URL for the file at the given path.
+ *
+ * @param \League\Flysystem\Rackspace\RackspaceAdapter $adapter
+ * @param string $path
+ * @return string
+ */
+ protected function getRackspaceUrl($adapter, $path)
+ {
+ return (string) $adapter->getContainer()->getObject($path)->getPublicUrl();
+ }
+
/**
* Get the URL for the file at the given path.
*
// it as the base URL instead of the default path. This allows the developer to
// have full control over the base path for this filesystem's generated URLs.
if ($config->has('url')) {
- return rtrim($config->get('url'), '/').'/'.ltrim($path, '/');
+ return $this->concatPathToUrl($config->get('url'), $path);
}
$path = '/storage/'.$path;
// are really supposed to use. We will remove the public from this path here.
if (Str::contains($path, '/storage/public/')) {
return Str::replaceFirst('/public/', '/', $path);
+ }
+
+ return $path;
+ }
+
+ /**
+ * Get a temporary URL for the file at the given path.
+ *
+ * @param string $path
+ * @param \DateTimeInterface $expiration
+ * @param array $options
+ * @return string
+ */
+ public function temporaryUrl($path, $expiration, array $options = [])
+ {
+ $adapter = $this->driver->getAdapter();
+
+ if ($adapter instanceof CachedAdapter) {
+ $adapter = $adapter->getAdapter();
+ }
+
+ if (method_exists($adapter, 'getTemporaryUrl')) {
+ return $adapter->getTemporaryUrl($path, $expiration, $options);
+ } elseif ($adapter instanceof AwsS3Adapter) {
+ return $this->getAwsTemporaryUrl($adapter, $path, $expiration, $options);
+ } elseif ($adapter instanceof RackspaceAdapter) {
+ return $this->getRackspaceTemporaryUrl($adapter, $path, $expiration, $options);
} else {
- return $path;
+ throw new RuntimeException('This driver does not support creating temporary URLs.');
}
}
+ /**
+ * Get a temporary URL for the file at the given path.
+ *
+ * @param \League\Flysystem\AwsS3v3\AwsS3Adapter $adapter
+ * @param string $path
+ * @param \DateTimeInterface $expiration
+ * @param array $options
+ * @return string
+ */
+ public function getAwsTemporaryUrl($adapter, $path, $expiration, $options)
+ {
+ $client = $adapter->getClient();
+
+ $command = $client->getCommand('GetObject', array_merge([
+ 'Bucket' => $adapter->getBucket(),
+ 'Key' => $adapter->getPathPrefix().$path,
+ ], $options));
+
+ return (string) $client->createPresignedRequest(
+ $command, $expiration
+ )->getUri();
+ }
+
+ /**
+ * Get a temporary URL for the file at the given path.
+ *
+ * @param \League\Flysystem\Rackspace\RackspaceAdapter $adapter
+ * @param string $path
+ * @param \DateTimeInterface $expiration
+ * @param array $options
+ * @return string
+ */
+ public function getRackspaceTemporaryUrl($adapter, $path, $expiration, $options)
+ {
+ return $adapter->getContainer()->getObject($path)->getTemporaryUrl(
+ Carbon::now()->diffInSeconds($expiration),
+ $options['method'] ?? 'GET',
+ $options['forcePublicUrl'] ?? true
+ );
+ }
+
+ /**
+ * Concatenate a path to a URL.
+ *
+ * @param string $url
+ * @param string $path
+ * @return string
+ */
+ protected function concatPathToUrl($url, $path)
+ {
+ return rtrim($url, '/').'/'.ltrim($path, '/');
+ }
+
/**
* Get an array of all files in a directory.
*
return $this->driver->deleteDir($directory);
}
+ /**
+ * Flush the Flysystem cache.
+ *
+ * @return void
+ */
+ public function flushCache()
+ {
+ $adapter = $this->driver->getAdapter();
+
+ if ($adapter instanceof CachedAdapter) {
+ $adapter->getCache()->flush();
+ }
+ }
+
/**
* Get the Flysystem driver.
*
return AdapterInterface::VISIBILITY_PRIVATE;
}
- throw new InvalidArgumentException('Unknown visibility: '.$visibility);
+ throw new InvalidArgumentException("Unknown visibility: {$visibility}");
}
/**
use Illuminate\Support\Arr;
use InvalidArgumentException;
use League\Flysystem\AdapterInterface;
+use League\Flysystem\Sftp\SftpAdapter;
use League\Flysystem\FilesystemInterface;
+use League\Flysystem\Cached\CachedAdapter;
use League\Flysystem\Filesystem as Flysystem;
use League\Flysystem\Adapter\Ftp as FtpAdapter;
use League\Flysystem\Rackspace\RackspaceAdapter;
use League\Flysystem\Adapter\Local as LocalAdapter;
use League\Flysystem\AwsS3v3\AwsS3Adapter as S3Adapter;
+use League\Flysystem\Cached\Storage\Memory as MemoryStore;
use Illuminate\Contracts\Filesystem\Factory as FactoryContract;
+/**
+ * @mixin \Illuminate\Contracts\Filesystem\Filesystem
+ */
class FilesystemManager implements FactoryContract
{
/**
*/
protected function get($name)
{
- return isset($this->disks[$name]) ? $this->disks[$name] : $this->resolve($name);
+ return $this->disks[$name] ?? $this->resolve($name);
}
/**
*/
public function createLocalDriver(array $config)
{
- $permissions = isset($config['permissions']) ? $config['permissions'] : [];
+ $permissions = $config['permissions'] ?? [];
- $links = Arr::get($config, 'links') === 'skip'
+ $links = ($config['links'] ?? null) === 'skip'
? LocalAdapter::SKIP_LINKS
: LocalAdapter::DISALLOW_LINKS;
*/
public function createFtpDriver(array $config)
{
- $ftpConfig = Arr::only($config, [
- 'host', 'username', 'password', 'port', 'root', 'passive', 'ssl', 'timeout',
- ]);
+ return $this->adapt($this->createFlysystem(
+ new FtpAdapter($config), $config
+ ));
+ }
+ /**
+ * Create an instance of the sftp driver.
+ *
+ * @param array $config
+ * @return \Illuminate\Contracts\Filesystem\Filesystem
+ */
+ public function createSftpDriver(array $config)
+ {
return $this->adapt($this->createFlysystem(
- new FtpAdapter($ftpConfig), $config
+ new SftpAdapter($config), $config
));
}
{
$s3Config = $this->formatS3Config($config);
- $root = isset($s3Config['root']) ? $s3Config['root'] : null;
+ $root = $s3Config['root'] ?? null;
- $options = isset($config['options']) ? $config['options'] : [];
+ $options = $config['options'] ?? [];
return $this->adapt($this->createFlysystem(
new S3Adapter(new S3Client($s3Config), $s3Config['bucket'], $root, $options), $config
'username' => $config['username'], 'apiKey' => $config['key'],
]);
- $root = isset($config['root']) ? $config['root'] : null;
+ $root = $config['root'] ?? null;
return $this->adapt($this->createFlysystem(
new RackspaceAdapter($this->getRackspaceContainer($client, $config), $root), $config
*/
protected function getRackspaceContainer(Rackspace $client, array $config)
{
- $urlType = Arr::get($config, 'url_type');
+ $urlType = $config['url_type'] ?? null;
$store = $client->objectStoreService('cloudFiles', $config['region'], $urlType);
*
* @param \League\Flysystem\AdapterInterface $adapter
* @param array $config
- * @return \League\Flysystem\FlysystemInterface
+ * @return \League\Flysystem\FilesystemInterface
*/
protected function createFlysystem(AdapterInterface $adapter, array $config)
{
+ $cache = Arr::pull($config, 'cache');
+
$config = Arr::only($config, ['visibility', 'disable_asserts', 'url']);
+ if ($cache) {
+ $adapter = new CachedAdapter($adapter, $this->createCacheStore($cache));
+ }
+
return new Flysystem($adapter, count($config) > 0 ? $config : null);
}
+ /**
+ * Create a cache store instance.
+ *
+ * @param mixed $config
+ * @return \League\Flysystem\Cached\CacheInterface
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected function createCacheStore($config)
+ {
+ if ($config === true) {
+ return new MemoryStore;
+ }
+
+ return new Cache(
+ $this->app['cache']->store($config['store']),
+ $config['prefix'] ?? 'flysystem',
+ $config['expire'] ?? null
+ );
+ }
+
/**
* Adapt the filesystem implementation.
*
return $this->app['config']['filesystems.cloud'];
}
+ /**
+ * Unset the given disk instances.
+ *
+ * @param array|string $disk
+ * @return $this
+ */
+ public function forgetDisk($disk)
+ {
+ foreach ((array) $disk as $diskName) {
+ unset($this->disks[$diskName]);
+ }
+
+ return $this;
+ }
+
/**
* Register a custom driver creator Closure.
*
}
],
"require": {
- "php": ">=5.6.4",
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "symfony/finder": "~3.2"
+ "php": "^7.1.3",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "symfony/finder": "~4.0"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"suggest": {
"league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).",
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).",
- "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0)."
+ "league/flysystem-cached-adapter": "Required to use the Flysystem cache (~1.0).",
+ "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).",
+ "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (~1.0)."
},
"config": {
"sort-packages": true
namespace Illuminate\Support;
use ArrayAccess;
+use InvalidArgumentException;
use Illuminate\Support\Traits\Macroable;
class Arr
*/
public static function crossJoin(...$arrays)
{
- return array_reduce($arrays, function ($results, $array) {
- return static::collapse(array_map(function ($parent) use ($array) {
- return array_map(function ($item) use ($parent) {
- return array_merge($parent, [$item]);
- }, $array);
- }, $results));
- }, [[]]);
+ $results = [[]];
+
+ foreach ($arrays as $index => $array) {
+ $append = [];
+
+ foreach ($results as $product) {
+ foreach ($array as $item) {
+ $product[$index] = $item;
+
+ $append[] = $product;
+ }
+ }
+
+ $results = $append;
+ }
+
+ return $results;
}
/**
}
/**
- * Get all of the given array except for a specified array of items.
+ * Get all of the given array except for a specified array of keys.
*
* @param array $array
* @param array|string $keys
*/
public static function flatten($array, $depth = INF)
{
- return array_reduce($array, function ($result, $item) use ($depth) {
+ $result = [];
+
+ foreach ($array as $item) {
$item = $item instanceof Collection ? $item->all() : $item;
if (! is_array($item)) {
- return array_merge($result, [$item]);
+ $result[] = $item;
} elseif ($depth === 1) {
- return array_merge($result, array_values($item));
+ $result = array_merge($result, array_values($item));
} else {
- return array_merge($result, static::flatten($item, $depth - 1));
+ $result = array_merge($result, static::flatten($item, $depth - 1));
}
- }, []);
+ }
+
+ return $result;
}
/**
return $array[$key];
}
+ if (strpos($key, '.') === false) {
+ return $array[$key] ?? value($default);
+ }
+
foreach (explode('.', $key) as $segment) {
if (static::accessible($array) && static::exists($array, $segment)) {
$array = $array[$segment];
} else {
$itemKey = data_get($item, $key);
+ if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
+ $itemKey = (string) $itemKey;
+ }
+
$results[$itemKey] = $itemValue;
}
}
return $value;
}
+ /**
+ * Get one or a specified number of random values from an array.
+ *
+ * @param array $array
+ * @param int|null $number
+ * @return mixed
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function random($array, $number = null)
+ {
+ $requested = is_null($number) ? 1 : $number;
+
+ $count = count($array);
+
+ if ($requested > $count) {
+ throw new InvalidArgumentException(
+ "You requested {$requested} items, but there are only {$count} items available."
+ );
+ }
+
+ if (is_null($number)) {
+ return $array[array_rand($array)];
+ }
+
+ if ((int) $number === 0) {
+ return [];
+ }
+
+ $keys = array_rand($array, $number);
+
+ $results = [];
+
+ foreach ((array) $keys as $key) {
+ $results[] = $array[$key];
+ }
+
+ return $results;
+ }
+
/**
* Set an array item to a given value using "dot" notation.
*
* Shuffle the given array and return the result.
*
* @param array $array
+ * @param int|null $seed
* @return array
*/
- public static function shuffle($array)
+ public static function shuffle($array, $seed = null)
{
- shuffle($array);
+ if (is_null($seed)) {
+ shuffle($array);
+ } else {
+ srand($seed);
+
+ usort($array, function () {
+ return rand(-1, 1);
+ });
+ }
return $array;
}
* Sort the array using the given callback or "dot" notation.
*
* @param array $array
- * @param callable|string $callback
+ * @param callable|string|null $callback
* @return array
*/
- public static function sort($array, $callback)
+ public static function sort($array, $callback = null)
{
return Collection::make($array)->sortBy($callback)->all();
}
}
/**
- * If the given value is not an array, wrap it in one.
+ * If the given value is not an array and not null, wrap it in one.
*
* @param mixed $value
* @return array
*/
public static function wrap($value)
{
+ if (is_null($value)) {
+ return [];
+ }
+
return ! is_array($value) ? [$value] : $value;
}
}
--- /dev/null
+<?php
+
+namespace Illuminate\Support;
+
+use JsonSerializable;
+use Carbon\Carbon as BaseCarbon;
+use Illuminate\Support\Traits\Macroable;
+
+class Carbon extends BaseCarbon implements JsonSerializable
+{
+ use Macroable;
+
+ /**
+ * The custom Carbon JSON serializer.
+ *
+ * @var callable|null
+ */
+ protected static $serializer;
+
+ /**
+ * Prepare the object for JSON serialization.
+ *
+ * @return array|string
+ */
+ public function jsonSerialize()
+ {
+ if (static::$serializer) {
+ return call_user_func(static::$serializer, $this);
+ }
+
+ $carbon = $this;
+
+ return call_user_func(function () use ($carbon) {
+ return get_object_vars($carbon);
+ });
+ }
+
+ /**
+ * JSON serialize all Carbon instances using the given callback.
+ *
+ * @param callable $callback
+ * @return void
+ */
+ public static function serializeUsing($callback)
+ {
+ static::$serializer = $callback;
+ }
+}
namespace Illuminate\Support;
+use stdClass;
use Countable;
use Exception;
use ArrayAccess;
use CachingIterator;
use JsonSerializable;
use IteratorAggregate;
-use InvalidArgumentException;
+use Illuminate\Support\Debug\Dumper;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Arrayable;
+/**
+ * @property-read HigherOrderCollectionProxy $average
+ * @property-read HigherOrderCollectionProxy $avg
+ * @property-read HigherOrderCollectionProxy $contains
+ * @property-read HigherOrderCollectionProxy $each
+ * @property-read HigherOrderCollectionProxy $every
+ * @property-read HigherOrderCollectionProxy $filter
+ * @property-read HigherOrderCollectionProxy $first
+ * @property-read HigherOrderCollectionProxy $flatMap
+ * @property-read HigherOrderCollectionProxy $groupBy
+ * @property-read HigherOrderCollectionProxy $keyBy
+ * @property-read HigherOrderCollectionProxy $map
+ * @property-read HigherOrderCollectionProxy $max
+ * @property-read HigherOrderCollectionProxy $min
+ * @property-read HigherOrderCollectionProxy $partition
+ * @property-read HigherOrderCollectionProxy $reject
+ * @property-read HigherOrderCollectionProxy $sortBy
+ * @property-read HigherOrderCollectionProxy $sortByDesc
+ * @property-read HigherOrderCollectionProxy $sum
+ * @property-read HigherOrderCollectionProxy $unique
+ *
+ * Class Collection
+ */
class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
{
use Macroable;
* @var array
*/
protected static $proxies = [
- 'contains', 'each', 'every', 'filter', 'first', 'flatMap',
- 'map', 'partition', 'reject', 'sortBy', 'sortByDesc', 'sum',
+ 'average', 'avg', 'contains', 'each', 'every', 'filter', 'first',
+ 'flatMap', 'groupBy', 'keyBy', 'map', 'max', 'min', 'partition',
+ 'reject', 'sortBy', 'sortByDesc', 'sum', 'unique',
];
/**
return new static($items);
}
+ /**
+ * Wrap the given value in a collection if applicable.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public static function wrap($value)
+ {
+ return $value instanceof self
+ ? new static($value)
+ : new static(Arr::wrap($value));
+ }
+
+ /**
+ * Get the underlying items from the given collection if applicable.
+ *
+ * @param array|static $value
+ * @return array
+ */
+ public static function unwrap($value)
+ {
+ return $value instanceof self ? $value->all() : $value;
+ }
+
/**
* Create a new collection by invoking the callback a given amount of times.
*
- * @param int $amount
+ * @param int $number
* @param callable $callback
* @return static
*/
- public static function times($amount, callable $callback = null)
+ public static function times($number, callable $callback = null)
{
- if ($amount < 1) {
+ if ($number < 1) {
return new static;
}
if (is_null($callback)) {
- return new static(range(1, $amount));
+ return new static(range(1, $number));
}
- return (new static(range(1, $amount)))->map($callback);
+ return (new static(range(1, $number)))->map($callback);
}
/**
return;
}
- $values = with(isset($key) ? $this->pluck($key) : $this)
+ $values = (isset($key) ? $this->pluck($key) : $this)
->sort()->values();
$middle = (int) ($count / 2);
{
if (func_num_args() == 1) {
if ($this->useAsCallable($key)) {
- return ! is_null($this->first($key));
+ $placeholder = new stdClass;
+
+ return $this->first($key, $placeholder) !== $placeholder;
}
return in_array($key, $this->items);
}
- if (func_num_args() == 2) {
- $value = $operator;
-
- $operator = '=';
- }
-
- return $this->contains($this->operatorForWhere($key, $operator, $value));
+ return $this->contains($this->operatorForWhere(...func_get_args()));
}
/**
));
}
+ /**
+ * Dump the collection and end the script.
+ *
+ * @return void
+ */
+ public function dd(...$args)
+ {
+ call_user_func_array([$this, 'dump'], $args);
+
+ die(1);
+ }
+
+ /**
+ * Dump the collection.
+ *
+ * @return $this
+ */
+ public function dump()
+ {
+ (new static(func_get_args()))
+ ->push($this)
+ ->each(function ($item) {
+ (new Dumper)->dump($item);
+ });
+
+ return $this;
+ }
+
/**
* Get the items in the collection that are not present in the given items.
*
return new static(array_diff($this->items, $this->getArrayableItems($items)));
}
+ /**
+ * Get the items in the collection that are not present in the given items.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffUsing($items, callable $callback)
+ {
+ return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));
+ }
+
/**
* Get the items in the collection whose keys and values are not present in the given items.
*
return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
}
+ /**
+ * Get the items in the collection whose keys and values are not present in the given items.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffAssocUsing($items, callable $callback)
+ {
+ return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
+ }
+
/**
* Get the items in the collection whose keys are not present in the given items.
*
return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
}
+ /**
+ * Get the items in the collection whose keys are not present in the given items.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffKeysUsing($items, callable $callback)
+ {
+ return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
+ }
+
/**
* Execute a callback over each item.
*
*/
public function eachSpread(callable $callback)
{
- return $this->each(function ($chunk) use ($callback) {
+ return $this->each(function ($chunk, $key) use ($callback) {
+ $chunk[] = $key;
+
return $callback(...$chunk);
});
}
return true;
}
- if (func_num_args() == 2) {
- $value = $operator;
-
- $operator = '=';
- }
-
- return $this->every($this->operatorForWhere($key, $operator, $value));
+ return $this->every($this->operatorForWhere(...func_get_args()));
}
/**
* Get all items except for those with the specified keys.
*
- * @param mixed $keys
+ * @param \Illuminate\Support\Collection|mixed $keys
* @return static
*/
public function except($keys)
{
- $keys = is_array($keys) ? $keys : func_get_args();
+ if ($keys instanceof self) {
+ $keys = $keys->all();
+ } elseif (! is_array($keys)) {
+ $keys = func_get_args();
+ }
return new static(Arr::except($this->items, $keys));
}
public function when($value, callable $callback, callable $default = null)
{
if ($value) {
- return $callback($this);
+ return $callback($this, $value);
} elseif ($default) {
- return $default($this);
+ return $default($this, $value);
}
return $this;
}
+ /**
+ * Apply the callback if the value is falsy.
+ *
+ * @param bool $value
+ * @param callable $callback
+ * @param callable $default
+ * @return mixed
+ */
+ public function unless($value, callable $callback, callable $default = null)
+ {
+ return $this->when(! $value, $callback, $default);
+ }
+
/**
* Filter items by the given key value pair.
*
*/
public function where($key, $operator, $value = null)
{
- if (func_num_args() == 2) {
- $value = $operator;
-
- $operator = '=';
- }
-
- return $this->filter($this->operatorForWhere($key, $operator, $value));
+ return $this->filter($this->operatorForWhere(...func_get_args()));
}
/**
* @param mixed $value
* @return \Closure
*/
- protected function operatorForWhere($key, $operator, $value)
+ protected function operatorForWhere($key, $operator, $value = null)
{
+ if (func_num_args() == 2) {
+ $value = $operator;
+
+ $operator = '=';
+ }
+
return function ($item) use ($key, $operator, $value) {
$retrieved = data_get($item, $key);
+ $strings = array_filter([$retrieved, $value], function ($value) {
+ return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
+ });
+
+ if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
+ return in_array($operator, ['!=', '<>', '!==']);
+ }
+
switch ($operator) {
default:
case '=':
return $this->whereNotIn($key, $values, true);
}
+ /**
+ * Filter the items, removing any items that don't match the given type.
+ *
+ * @param string $type
+ * @return static
+ */
+ public function whereInstanceOf($type)
+ {
+ return $this->filter(function ($value) use ($type) {
+ return $value instanceof $type;
+ });
+ }
+
/**
* Get the first item from the collection.
*
return Arr::first($this->items, $callback, $default);
}
+ /**
+ * Get the first item by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return static
+ */
+ public function firstWhere($key, $operator, $value = null)
+ {
+ return $this->first($this->operatorForWhere(...func_get_args()));
+ }
+
/**
* Get a flattened array of the items in the collection.
*
*/
public function groupBy($groupBy, $preserveKeys = false)
{
+ if (is_array($groupBy)) {
+ $nextGroups = $groupBy;
+
+ $groupBy = array_shift($nextGroups);
+ }
+
$groupBy = $this->valueRetriever($groupBy);
$results = [];
}
}
- return new static($results);
+ $result = new static($results);
+
+ if (! empty($nextGroups)) {
+ return $result->map->groupBy($nextGroups, $preserveKeys);
+ }
+
+ return $result;
}
/**
*/
public function has($key)
{
- return $this->offsetExists($key);
+ $keys = is_array($key) ? $key : func_get_args();
+
+ foreach ($keys as $value) {
+ if (! $this->offsetExists($value)) {
+ return false;
+ }
+ }
+
+ return true;
}
/**
return new static(array_intersect($this->items, $this->getArrayableItems($items)));
}
+ /**
+ * Intersect the collection with the given items by key.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function intersectByKeys($items)
+ {
+ return new static(array_intersect_key(
+ $this->items, $this->getArrayableItems($items)
+ ));
+ }
+
/**
* Determine if the collection is empty or not.
*
*/
public function mapSpread(callable $callback)
{
- return $this->map(function ($chunk) use ($callback) {
+ return $this->map(function ($chunk, $key) use ($callback) {
+ $chunk[] = $key;
+
return $callback(...$chunk);
});
}
+ /**
+ * Run a dictionary map over the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapToDictionary(callable $callback)
+ {
+ $dictionary = [];
+
+ foreach ($this->items as $key => $item) {
+ $pair = $callback($item, $key);
+
+ $key = key($pair);
+
+ $value = reset($pair);
+
+ if (! isset($dictionary[$key])) {
+ $dictionary[$key] = [];
+ }
+
+ $dictionary[$key][] = $value;
+ }
+
+ return new static($dictionary);
+ }
+
/**
* Run a grouping map over the items.
*
*/
public function mapToGroups(callable $callback)
{
- $groups = $this->map($callback)->reduce(function ($groups, $pair) {
- $groups[key($pair)][] = reset($pair);
+ $groups = $this->mapToDictionary($callback);
- return $groups;
- }, []);
-
- return (new static($groups))->map([$this, 'make']);
+ return $groups->map([$this, 'make']);
}
/**
return $this->map($callback)->collapse();
}
+ /**
+ * Map the values into a new class.
+ *
+ * @param string $class
+ * @return static
+ */
+ public function mapInto($class)
+ {
+ return $this->map(function ($value, $key) use ($class) {
+ return new $class($value, $key);
+ });
+ }
+
/**
* Get the max value of a given key.
*
return new static($this->items);
}
+ if ($keys instanceof self) {
+ $keys = $keys->all();
+ }
+
$keys = is_array($keys) ? $keys : func_get_args();
return new static(Arr::only($this->items, $keys));
*/
public function forPage($page, $perPage)
{
- return $this->slice(($page - 1) * $perPage, $perPage);
+ $offset = max(0, ($page - 1) * $perPage);
+
+ return $this->slice($offset, $perPage);
}
/**
* Partition the collection into two arrays using the given callback or key.
*
- * @param callable|string $callback
+ * @param callable|string $key
+ * @param mixed $operator
+ * @param mixed $value
* @return static
*/
- public function partition($callback)
+ public function partition($key, $operator = null, $value = null)
{
$partitions = [new static, new static];
- $callback = $this->valueRetriever($callback);
+ $callback = func_num_args() == 1
+ ? $this->valueRetriever($key)
+ : $this->operatorForWhere(...func_get_args());
foreach ($this->items as $key => $item) {
- $partitions[(int) ! $callback($item)][$key] = $item;
+ $partitions[(int) ! $callback($item, $key)][$key] = $item;
}
return new static($partitions);
/**
* Push all of the given items onto the collection.
*
- * @param \Traversable $source
- * @return self
+ * @param \Traversable|array $source
+ * @return $this
*/
public function concat($source)
{
}
/**
- * Get one or more items randomly from the collection.
+ * Get one or a specified number of items randomly from the collection.
*
- * @param int|null $amount
+ * @param int|null $number
* @return mixed
*
* @throws \InvalidArgumentException
*/
- public function random($amount = 1)
+ public function random($number = null)
{
- if ($amount > ($count = $this->count())) {
- throw new InvalidArgumentException("You requested {$amount} items, but there are only {$count} items in the collection.");
+ if (is_null($number)) {
+ return Arr::random($this->items);
}
- $keys = array_rand($this->items, $amount);
-
- if (count(func_get_args()) == 0) {
- return $this->items[$keys];
- }
-
- $keys = array_wrap($keys);
-
- return new static(array_intersect_key($this->items, array_flip($keys)));
+ return new static(Arr::random($this->items, $number));
}
/**
*/
public function shuffle($seed = null)
{
- $items = $this->items;
-
- if (is_null($seed)) {
- shuffle($items);
- } else {
- srand($seed);
-
- usort($items, function () {
- return rand(-1, 1);
- });
- }
-
- return new static($items);
+ return new static(Arr::shuffle($this->items, $seed));
}
/**
}
$descending ? arsort($results, $options)
- : asort($results, $options);
+ : asort($results, $options);
// Once we have sorted all of the keys in the array, we will loop through them
// and grab the corresponding model so we can set the underlying items list
return $this->sortBy($callback, $options, true);
}
+ /**
+ * Sort the collection keys.
+ *
+ * @param int $options
+ * @param bool $descending
+ * @return static
+ */
+ public function sortKeys($options = SORT_REGULAR, $descending = false)
+ {
+ $items = $this->items;
+
+ $descending ? krsort($items, $options) : ksort($items, $options);
+
+ return new static($items);
+ }
+
+ /**
+ * Sort the collection keys in descending order.
+ *
+ * @param int $options
+ * @return static
+ */
+ public function sortKeysDesc($options = SORT_REGULAR)
+ {
+ return $this->sortKeys($options, true);
+ }
+
/**
* Splice a portion of the underlying collection array.
*
*/
public function unique($key = null, $strict = false)
{
- if (is_null($key)) {
- return new static(array_unique($this->items, SORT_REGULAR));
- }
-
$callback = $this->valueRetriever($key);
$exists = [];
return new static(call_user_func_array('array_map', $params));
}
+ /**
+ * Pad collection to the specified length with a value.
+ *
+ * @param int $size
+ * @param mixed $value
+ * @return static
+ */
+ public function pad($size, $value)
+ {
+ return new static(array_pad($this->items, $size, $value));
+ }
+
/**
* Get the collection of items as a plain array.
*
return json_decode($value->toJson(), true);
} elseif ($value instanceof Arrayable) {
return $value->toArray();
- } else {
- return $value;
}
+
+ return $value;
}, $this->items);
}
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Process\Process;
-use Symfony\Component\Process\ProcessUtils;
use Symfony\Component\Process\PhpExecutableFinder;
class Composer
public function dump($value)
{
if (class_exists(CliDumper::class)) {
- $dumper = 'cli' === PHP_SAPI ? new CliDumper : new HtmlDumper;
+ $dumper = in_array(PHP_SAPI, ['cli', 'phpdbg']) ? new CliDumper : new HtmlDumper;
$dumper->dump((new VarCloner)->cloneVar($value));
} else {
/**
* @method static int handle(\Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface $output = null)
- * @method static int call(string $command, array $parameters = [])
+ * @method static int call(string $command, array $parameters = [], $outputBuffer = null)
* @method static int queue(string $command, array $parameters = [])
* @method static array all()
* @method static string output()
namespace Illuminate\Support\Facades;
/**
+ * @method static void compile($path = null)
+ * @method static string getPath()
+ * @method static void setPath($path)
+ * @method static string compileString($value)
+ * @method static string stripParentheses($expression)
+ * @method static void extend(callable $compiler)
+ * @method static array getExtensions()
+ * @method static void if($name, callable $callback)
+ * @method static bool check($name, ...$parameters)
+ * @method static void component($path, $alias = null)
+ * @method static void include($path, $alias = null)
+ * @method static void directive($name, callable $handler)
+ * @method static array getCustomDirectives()
+ * @method static void setEchoFormat($format)
+ * @method static void withDoubleEncoding()
+ * @method static void withoutDoubleEncoding()
+ *
* @see \Illuminate\View\Compilers\BladeCompiler
*/
class Blade extends Facade
use Illuminate\Contracts\Broadcasting\Factory as BroadcastingFactoryContract;
/**
+ * @method static void connection($name = null);
+ *
* @see \Illuminate\Contracts\Broadcasting\Factory
*/
class Broadcast extends Facade
use Illuminate\Contracts\Bus\Dispatcher as BusDispatcherContract;
/**
+ * @method static mixed dispatch($command)
+ * @method static mixed dispatchNow($command, $handler = null)
+ * @method static bool hasCommandHandler($command)
+ * @method static bool|mixed getCommandHandler($command)
+ * @method static \Illuminate\Contracts\Bus\Dispatcher pipeThrough(array $pipes)
+ * @method static \Illuminate\Contracts\Bus\Dispatcher map(array $map)
+ *
* @see \Illuminate\Contracts\Bus\Dispatcher
*/
class Bus extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Contracts\Cache\Repository store(string|null $name = null)
+ * @method static bool has(string $key)
+ * @method static mixed get(string $key, mixed $default = null)
+ * @method static mixed pull(string $key, mixed $default = null)
+ * @method static void put(string $key, $value, \DateTimeInterface|\DateInterval|float|int $minutes)
+ * @method static bool add(string $key, $value, \DateTimeInterface|\DateInterval|float|int $minutes)
+ * @method static int|bool increment(string $key, $value = 1)
+ * @method static int|bool decrement(string $key, $value = 1)
+ * @method static void forever(string $key, $value)
+ * @method static mixed remember(string $key, \DateTimeInterface|\DateInterval|float|int $minutes, \Closure $callback)
+ * @method static mixed sear(string $key, \Closure $callback)
+ * @method static mixed rememberForever(string $key, \Closure $callback)
+ * @method static bool forget(string $key)
+ * @method static \Illuminate\Contracts\Cache\Store getStore()
+ *
* @see \Illuminate\Cache\CacheManager
* @see \Illuminate\Cache\Repository
*/
namespace Illuminate\Support\Facades;
/**
+ * @method static bool has($key)
+ * @method static mixed get($key, $default = null)
+ * @method static array all()
+ * @method static void set($key, $value = null)
+ * @method static void prepend($key, $value)
+ * @method static void push($key, $value)
+ *
* @see \Illuminate\Config\Repository
*/
class Config extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static void queue(...$parameters)
+ * @method static unqueue($name)
+ * @method static array getQueuedCookies()
+ *
* @see \Illuminate\Cookie\CookieJar
*/
class Cookie extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static string encrypt(string $value, bool $serialize = true)
+ * @method static string decrypt(string $payload, bool $unserialize = true)
+ *
* @see \Illuminate\Encryption\Encrypter
*/
class Crypt extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Database\ConnectionInterface connection(string $name = null)
+ * @method static string getDefaultConnection()
+ * @method static void setDefaultConnection(string $name)
+ * @method static \Illuminate\Database\Query\Builder table(string $table)
+ * @method static \Illuminate\Database\Query\Expression raw($value)
+ * @method static mixed selectOne(string $query, array $bindings = [])
+ * @method static array select(string $query, array $bindings = [])
+ * @method static bool insert(string $query, array $bindings = [])
+ * @method static int update(string $query, array $bindings = [])
+ * @method static int delete(string $query, array $bindings = [])
+ * @method static bool statement(string $query, array $bindings = [])
+ * @method static int affectingStatement(string $query, array $bindings = [])
+ * @method static bool unprepared(string $query)
+ * @method static array prepareBindings(array $bindings)
+ * @method static mixed transaction(\Closure $callback, int $attempts = 1)
+ * @method static void beginTransaction()
+ * @method static void commit()
+ * @method static void rollBack()
+ * @method static int transactionLevel()
+ * @method static array pretend(\Closure $callback)
+ *
* @see \Illuminate\Database\DatabaseManager
* @see \Illuminate\Database\Connection
*/
use Illuminate\Support\Testing\Fakes\EventFake;
/**
+ * @method static void listen(string | array $events, $listener)
+ * @method static bool hasListeners(string $eventName)
+ * @method static void subscribe(object | string $subscriber)
+ * @method static array|null until(string | object $event, $payload = [])
+ * @method static array|null dispatch(string | object $event, $payload = [], bool $halt = false)
+ * @method static void push(string $event, array $payload = [])
+ * @method static void flush(string $event)
+ * @method static void forget(string $event)
+ * @method static void forgetPushed()
+ *
* @see \Illuminate\Events\Dispatcher
*/
class Event extends Facade
/**
* Replace the bound instance with a fake.
*
+ * @param array|string $eventsToFake
* @return void
*/
- public static function fake()
+ public static function fake($eventsToFake = [])
{
- static::swap($fake = new EventFake);
+ static::swap($fake = new EventFake(static::getFacadeRoot(), $eventsToFake));
Model::setEventDispatcher($fake);
}
namespace Illuminate\Support\Facades;
/**
+ * @method static bool exists(string $path)
+ * @method static string get(string $path, bool $lock = false)
+ * @method static string sharedGet(string $path)
+ * @method static mixed getRequire(string $path)
+ * @method static mixed requireOnce(string $file)
+ * @method static string hash(string $path)
+ * @method static int put(string $path, string $contents, bool $lock = false)
+ * @method static int prepend(string $path, string $data)
+ * @method static int append(string $path, string $data)
+ * @method static mixed chmod(string $path, int $mode = null)
+ * @method static bool delete(string|array $paths)
+ * @method static bool move(string $path, string $target)
+ * @method static bool copy(string $path, string $target)
+ * @method static void link(string $target, string $link)
+ * @method static string name(string $path)
+ * @method static string basename(string $path)
+ * @method static string dirname(string $path)
+ * @method static string extension(string $path)
+ * @method static string type(string $path)
+ * @method static string|false mimeType(string $path)
+ * @method static int size(string $path)
+ * @method static int lastModified(string $path)
+ * @method static bool isDirectory(string $directory)
+ * @method static bool isReadable(string $path)
+ * @method static bool isWritable(string $path)
+ * @method static bool isFile(string $file)
+ * @method static array glob(string $pattern, int $flags = 0)
+ * @method static \Symfony\Component\Finder\SplFileInfo[] files(string $directory, bool $hidden = false)
+ * @method static \Symfony\Component\Finder\SplFileInfo[] allFiles(string $directory, bool $hidden = false)
+ * @method static array directories(string $directory)
+ * @method static bool makeDirectory(string $path, int $mode = 0755, bool $recursive = false, bool $force = false)
+ * @method static bool moveDirectory(string $from, string $to, bool $overwrite = false)
+ * @method static bool copyDirectory(string $directory, string $destination, int $options = null)
+ * @method static bool deleteDirectory(string $directory, bool $preserve = false)
+ * @method static bool cleanDirectory(string $directory)
+ *
* @see \Illuminate\Filesystem\Filesystem
*/
class File extends Facade
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
/**
+ * @method static bool has(string $ability)
+ * @method static \Illuminate\Contracts\Auth\Access\Gate define(string $ability, callable | string $callback)
+ * @method static \Illuminate\Contracts\Auth\Access\Gate policy(string $class, string $policy)
+ * @method static \Illuminate\Contracts\Auth\Access\Gate before(callable $callback)
+ * @method static \Illuminate\Contracts\Auth\Access\Gate after(callable $callback)
+ * @method static bool allows(string $ability, array | mixed $arguments = [])
+ * @method static bool denies(string $ability, array | mixed $arguments = [])
+ * @method static bool check(iterable | string $abilities, array | mixed $arguments = [])
+ * @method static bool any(iterable | string $abilities, array | mixed $arguments = [])
+ * @method static \Illuminate\Auth\Access\Response authorize(string $ability, array | mixed $arguments = [])
+ * @method static mixed getPolicyFor(object | string $class)
+ * @method static \Illuminate\Contracts\Auth\Access\Gate forUser(\Illuminate\Contracts\Auth\Authenticatable | mixed $user)
+ * @method static array abilities()
+ *
* @see \Illuminate\Contracts\Auth\Access\Gate
*/
class Gate extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static array info(string $hashedValue)
+ * @method static string make(string $value, array $options = [])
+ * @method static bool check(string $value, string $hashedValue, array $options = [])
+ * @method static bool needsRehash(string $hashedValue, array $options = [])
+ *
* @see \Illuminate\Hashing\BcryptHasher
*/
class Hash extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Http\Request instance()
+ * @method static string method()
+ * @method static string root()
+ * @method static string url()
+ * @method static string fullUrl()
+ * @method static string fullUrlWithQuery(array $query)
+ * @method static string path()
+ * @method static string decodedPath()
+ * @method static string|null segment(int $index, string|null $default = null)
+ * @method static array segments()
+ * @method static bool is(...$patterns)
+ * @method static bool routeIs(...$patterns)
+ * @method static bool fullUrlIs(...$patterns)
+ * @method static bool ajax()
+ * @method static bool pjax()
+ * @method static bool secure()
+ * @method static string ip()
+ * @method static array ips()
+ * @method static string userAgent()
+ * @method static \Illuminate\Http\Request merge(array $input)
+ * @method static \Illuminate\Http\Request replace(array $input)
+ * @method static \Symfony\Component\HttpFoundation\ParameterBag|mixed json(string $key = null, $default = null)
+ * @method static \Illuminate\Session\Store session()
+ * @method static \Illuminate\Session\Store|null getSession()
+ * @method static void setLaravelSession(\Illuminate\Contracts\Session\Session $session)
+ * @method static mixed user(string|null $guard = null)
+ * @method static \Illuminate\Routing\Route|object|string route(string|null $param = null)
+ * @method static string fingerprint()
+ * @method static \Illuminate\Http\Request setJson(\Symfony\Component\HttpFoundation\ParameterBag $json)
+ * @method static \Closure getUserResolver()
+ * @method static \Illuminate\Http\Request setUserResolver(\Closure $callback)
+ * @method static \Closure getRouteResolver()
+ * @method static \Illuminate\Http\Request setRouteResolver(\Closure $callback)
+ * @method static array toArray()
+ * @method static bool offsetExists(string $offset)
+ * @method static mixed offsetGet(string $offset)
+ * @method static void offsetSet(string $offset, $value)
+ * @method static void offsetUnset(string $offset)
+ *
* @see \Illuminate\Http\Request
*/
class Input extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static mixed trans(string $key, array $replace = [], string $locale = null)
+ * @method static string transChoice(string $key, int | array | \Countable $number, array $replace = [], string $locale = null)
+ * @method static string getLocale()
+ * @method static void setLocale(string $locale)
+ *
* @see \Illuminate\Translation\Translator
*/
class Lang extends Facade
use Psr\Log\LoggerInterface;
/**
- * @see \Illuminate\Log\Writer
+ * @method static void emergency(string $message, array $context = [])
+ * @method static void alert(string $message, array $context = [])
+ * @method static void critical(string $message, array $context = [])
+ * @method static void error(string $message, array $context = [])
+ * @method static void warning(string $message, array $context = [])
+ * @method static void notice(string $message, array $context = [])
+ * @method static void info(string $message, array $context = [])
+ * @method static void debug(string $message, array $context = [])
+ * @method static void log($level, string $message, array $context = [])
+ *
+ * @see \Illuminate\Log\Logger
*/
class Log extends Facade
{
use Illuminate\Support\Testing\Fakes\MailFake;
/**
+ * @method static \Illuminate\Mail\PendingMail to($users)
+ * @method static \Illuminate\Mail\PendingMail bcc($users)
+ * @method static void raw(string $text, $callback)
+ * @method static void send(string|array|\Illuminate\Contracts\Mail\Mailable $view, array $data = [], \Closure|string $callback = null)
+ * @method static array failures()
+ * @method static mixed queue(string|array|\Illuminate\Contracts\Mail\Mailable $view, string $queue = null)
+ * @method static mixed later(\DateTimeInterface|\DateInterval|int $delay, string|array|\Illuminate\Contracts\Mail\Mailable $view, string $queue = null)
+ *
* @see \Illuminate\Mail\Mailer
*/
class Mail extends Facade
namespace Illuminate\Support\Facades;
use Illuminate\Notifications\ChannelManager;
+use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Testing\Fakes\NotificationFake;
/**
+ * @method static void send(\Illuminate\Support\Collection|array|mixed $notifiables, $notification)
+ * @method static void sendNow(\Illuminate\Support\Collection|array|mixed $notifiables, $notification)
+ * @method static mixed channel(string|null $name = null)
+ *
* @see \Illuminate\Notifications\ChannelManager
*/
class Notification extends Facade
/**
* Replace the bound instance with a fake.
*
- * @return void
+ * @return \Illuminate\Support\Testing\Fakes\NotificationFake
*/
public static function fake()
{
- static::swap(new NotificationFake);
+ static::swap($fake = new NotificationFake);
+
+ return $fake;
+ }
+
+ /**
+ * Begin sending a notification to an anonymous notifiable.
+ *
+ * @param string $channel
+ * @param mixed $route
+ * @return \Illuminate\Notifications\AnonymousNotifiable
+ */
+ public static function route($channel, $route)
+ {
+ return (new AnonymousNotifiable)->route($channel, $route);
}
/**
namespace Illuminate\Support\Facades;
/**
+ * @method static string sendResetLink(array $credentials)
+ * @method static mixed reset(array $credentials, \Closure $callback)
+ * @method static void validator(\Closure $callback)
+ * @method static bool validateNewPassword(array $credentials)
+ *
* @see \Illuminate\Auth\Passwords\PasswordBroker
*/
class Password extends Facade
use Illuminate\Support\Testing\Fakes\QueueFake;
/**
+ * @method static int size(string $queue = null)
+ * @method static mixed push(string|object $job, string $data = '', $queue = null)
+ * @method static mixed pushOn(string $queue, string|object $job, $data = '')
+ * @method static mixed pushRaw(string $payload, string $queue = null, array $options = [])
+ * @method static mixed later(\DateTimeInterface|\DateInterval|int $delay, string|object $job, $data = '', string $queue = null)
+ * @method static mixed laterOn(string $queue, \DateTimeInterface|\DateInterval|int $delay, string|object $job, $data = '')
+ * @method static mixed bulk(array $jobs, $data = '', string $queue = null)
+ * @method static \Illuminate\Contracts\Queue\Job|null pop(string $queue = null)
+ * @method static string getConnectionName()
+ * @method static \Illuminate\Contracts\Queue\Queue setConnectionName(string $name)
+ *
* @see \Illuminate\Queue\QueueManager
* @see \Illuminate\Queue\Queue
*/
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Http\RedirectResponse home(int $status = 302)
+ * @method static \Illuminate\Http\RedirectResponse back(int $status = 302, array $headers = [], $fallback = false)
+ * @method static \Illuminate\Http\RedirectResponse refresh(int $status = 302, array $headers = [])
+ * @method static \Illuminate\Http\RedirectResponse guest(string $path, int $status = 302, array $headers = [], bool $secure = null)
+ * @method static intended(string $default = '/', int $status = 302, array $headers = [], bool $secure = null)
+ * @method static \Illuminate\Http\RedirectResponse to(string $path, int $status = 302, array $headers = [], bool $secure = null)
+ * @method static \Illuminate\Http\RedirectResponse away(string $path, int $status = 302, array $headers = [])
+ * @method static \Illuminate\Http\RedirectResponse secure(string $path, int $status = 302, array $headers = [])
+ * @method static \Illuminate\Http\RedirectResponse route(string $route, array $parameters = [], int $status = 302, array $headers = [])
+ * @method static \Illuminate\Http\RedirectResponse action(string $action, array $parameters = [], int $status = 302, array $headers = [])
+ * @method static \Illuminate\Routing\UrlGenerator getUrlGenerator()
+ * @method static void setSession(\Illuminate\Session\Store $session)
+ *
* @see \Illuminate\Routing\Redirector
*/
class Redirect extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Redis\Connections\Connection connection(string $name = null)
+ *
* @see \Illuminate\Redis\RedisManager
* @see \Illuminate\Contracts\Redis\Factory
*/
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Http\Request instance()
+ * @method static string method()
+ * @method static string root()
+ * @method static string url()
+ * @method static string fullUrl()
+ * @method static string fullUrlWithQuery(array $query)
+ * @method static string path()
+ * @method static string decodedPath()
+ * @method static string|null segment(int $index, string|null $default = null)
+ * @method static array segments()
+ * @method static bool is(...$patterns)
+ * @method static bool routeIs(...$patterns)
+ * @method static bool fullUrlIs(...$patterns)
+ * @method static bool ajax()
+ * @method static bool pjax()
+ * @method static bool secure()
+ * @method static string ip()
+ * @method static array ips()
+ * @method static string userAgent()
+ * @method static \Illuminate\Http\Request merge(array $input)
+ * @method static \Illuminate\Http\Request replace(array $input)
+ * @method static \Symfony\Component\HttpFoundation\ParameterBag|mixed json(string $key = null, $default = null)
+ * @method static \Illuminate\Session\Store session()
+ * @method static \Illuminate\Session\Store|null getSession()
+ * @method static void setLaravelSession(\Illuminate\Contracts\Session\Session $session)
+ * @method static mixed user(string|null $guard = null)
+ * @method static \Illuminate\Routing\Route|object|string route(string|null $param = null)
+ * @method static string fingerprint()
+ * @method static \Illuminate\Http\Request setJson(\Symfony\Component\HttpFoundation\ParameterBag $json)
+ * @method static \Closure getUserResolver()
+ * @method static \Illuminate\Http\Request setUserResolver(\Closure $callback)
+ * @method static \Closure getRouteResolver()
+ * @method static \Illuminate\Http\Request setRouteResolver(\Closure $callback)
+ * @method static array toArray()
+ * @method static bool offsetExists(string $offset)
+ * @method static mixed offsetGet(string $offset)
+ * @method static void offsetSet(string $offset, $value)
+ * @method static void offsetUnset(string $offset)
+ *
* @see \Illuminate\Http\Request
*/
class Request extends Facade
use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract;
/**
+ * @method static \Illuminate\Http\Response make(string $content = '', int $status = 200, array $headers = [])
+ * @method static \Illuminate\Http\Response view(string $view, array $data = [], int $status = 200, array $headers = [])
+ * @method static \Illuminate\Http\JsonResponse json(string | array $data = [], int $status = 200, array $headers = [], int $options = 0)
+ * @method static \Illuminate\Http\JsonResponse jsonp(string $callback, string | array $data = [], int $status = 200, array $headers = [], int $options = 0)
+ * @method static \Symfony\Component\HttpFoundation\StreamedResponse stream(\Closure $callback, int $status = 200, array $headers = [])
+ * @method static \Symfony\Component\HttpFoundation\StreamedResponse streamDownload(\Closure $callback, string | null $name = null, array $headers = [], string | null $disposition = 'attachment')
+ * @method static \Symfony\Component\HttpFoundation\BinaryFileResponse download(\SplFileInfo | string $file, string | null $name = null, array $headers = [], string | null $disposition = 'attachment')
+ * @method static \Illuminate\Http\RedirectResponse redirectTo(string $path, int $status = 302, array $headers = [], bool | null $secure = null)
+ * @method static \Illuminate\Http\RedirectResponse redirectToRoute(string $route, array $parameters = [], int $status = 302, array $headers = [])
+ * @method static \Illuminate\Http\RedirectResponse redirectToAction(string $action, array $parameters = [], int $status = 302, array $headers = [])
+ * @method static \Illuminate\Http\RedirectResponse redirectGuest(string $path, int $status = 302, array $headers = [], bool | null $secure = null)
+ * @method static \Illuminate\Http\RedirectResponse redirectToIntended(string $default = '/', int $status = 302, array $headers = [], bool | null $secure = null)
+ *
* @see \Illuminate\Contracts\Routing\ResponseFactory
*/
class Response extends Facade
namespace Illuminate\Support\Facades;
/**
- * @method static \Illuminate\Routing\Route get(string $uri, \Closure|array|string $action)
- * @method static \Illuminate\Routing\Route post(string $uri, \Closure|array|string $action)
- * @method static \Illuminate\Routing\Route put(string $uri, \Closure|array|string $action)
- * @method static \Illuminate\Routing\Route delete(string $uri, \Closure|array|string $action)
- * @method static \Illuminate\Routing\Route patch(string $uri, \Closure|array|string $action)
- * @method static \Illuminate\Routing\Route options(string $uri, \Closure|array|string $action)
- * @method static \Illuminate\Routing\Route any(string $uri, \Closure|array|string $action)
- * @method static \Illuminate\Routing\Route match(array|string $methods, string $uri, \Closure|array|string $action)
- * @method static void resource(string $name, string $controller, array $options = [])
- * @method static void apiResource(string $name, string $controller, array $options = [])
- * @method static void group(array $attributes, \Closure $callback)
- * @method static \Illuminate\Routing\Route middleware(array|string|null $middleware)
- * @method static \Illuminate\Routing\Route substituteBindings(\Illuminate\Routing\Route $route)
- * @method static void substituteImplicitBindings(\Illuminate\Routing\Route $route)
+ * @method static \Illuminate\Routing\Route get(string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\Route post(string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\Route put(string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\Route delete(string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\Route patch(string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\Route options(string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\Route any(string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\Route match(array|string $methods, string $uri, \Closure|array|string|null $action = null)
+ * @method static \Illuminate\Routing\RouteRegistrar prefix(string $prefix)
+ * @method static \Illuminate\Routing\PendingResourceRegistration resource(string $name, string $controller, array $options = [])
+ * @method static \Illuminate\Routing\PendingResourceRegistration apiResource(string $name, string $controller, array $options = [])
+ * @method static \Illuminate\Routing\RouteRegistrar middleware(array|string|null $middleware)
+ * @method static \Illuminate\Routing\Route substituteBindings(\Illuminate\Support\Facades\Route $route)
+ * @method static void substituteImplicitBindings(\Illuminate\Support\Facades\Route $route)
+ * @method static \Illuminate\Routing\RouteRegistrar as(string $value)
+ * @method static \Illuminate\Routing\RouteRegistrar domain(string $value)
+ * @method static \Illuminate\Routing\RouteRegistrar name(string $value)
+ * @method static \Illuminate\Routing\RouteRegistrar namespace(string $value)
+ * @method static \Illuminate\Routing\Router|\Illuminate\Routing\RouteRegistrar group(array|\Closure|string $attributes, \Closure|string $routes)
+ * @method static \Illuminate\Routing\Route redirect(string $uri, string $destination, int $status = 301)
+ * @method static \Illuminate\Routing\Route view(string $uri, string $view, array $data = [])
+ * @method static void bind(string $key, string|callable $binder)
+ * @method static \Illuminate\Routing\Route current()
+ * @method static string|null currentRouteName()
+ * @method static string|null currentRouteAction()
*
* @see \Illuminate\Routing\Router
*/
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Database\Schema\Builder create(string $table, \Closure $callback)
+ * @method static \Illuminate\Database\Schema\Builder drop(string $table)
+ * @method static \Illuminate\Database\Schema\Builder dropIfExists(string $table)
+ * @method static \Illuminate\Database\Schema\Builder table(string $table, \Closure $callback)
+ * @method static void defaultStringLength(int $length)
+ *
* @see \Illuminate\Database\Schema\Builder
*/
class Schema extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static string getName()
+ * @method static string getId()
+ * @method static void setId(string $id)
+ * @method static bool start()
+ * @method static bool save()
+ * @method static array all()
+ * @method static bool exists(string|array $key)
+ * @method static bool has(string|array $key)
+ * @method static mixed get(string $key, $default = null)
+ * @method static void put(string|array $key, $value = null)
+ * @method static string token()
+ * @method static mixed remove(string $key)
+ * @method static void forget(string|array $keys)
+ * @method static void flush()
+ * @method static bool migrate(bool $destroy = false)
+ * @method static bool isStarted()
+ * @method static string|null previousUrl()
+ * @method static void setPreviousUrl(string $url)
+ * @method static \SessionHandlerInterface getHandler()
+ * @method static bool handlerNeedsRequest()
+ * @method static void setRequestOnHandler(\Illuminate\Http\Request $request)
+ *
* @see \Illuminate\Session\SessionManager
* @see \Illuminate\Session\Store
*/
use Illuminate\Filesystem\Filesystem;
/**
+ * @method static \Illuminate\Contracts\Filesystem\Filesystem disk(string $name = null)
+ *
* @see \Illuminate\Filesystem\FilesystemManager
*/
class Storage extends Facade
{
/**
- * Replace the given disk with a local, testing disk.
+ * Replace the given disk with a local testing disk.
+ *
+ * @param string|null $disk
*
- * @param string $disk
* @return void
*/
- public static function fake($disk)
+ public static function fake($disk = null)
{
+ $disk = $disk ?: self::$app['config']->get('filesystems.default');
+
(new Filesystem)->cleanDirectory(
$root = storage_path('framework/testing/disks/'.$disk)
);
static::set($disk, self::createLocalDriver(['root' => $root]));
}
+ /**
+ * Replace the given disk with a persistent local testing disk.
+ *
+ * @param string|null $disk
+ * @return void
+ */
+ public static function persistentFake($disk = null)
+ {
+ $disk = $disk ?: self::$app['config']->get('filesystems.default');
+
+ static::set($disk, self::createLocalDriver([
+ 'root' => storage_path('framework/testing/disks/'.$disk),
+ ]));
+ }
+
/**
* Get the registered name of the component.
*
namespace Illuminate\Support\Facades;
/**
+ * @method static string current()
+ * @method static string to(string $path, $extra = [], bool $secure = null)
+ * @method static string secure(string $path, array $parameters = [])
+ * @method static string asset(string $path, bool $secure = null)
+ * @method static string route(string $name, $parameters = [], bool $absolute = true)
+ * @method static string action(string $action, $parameters = [], bool $absolute = true)
+ * @method static \Illuminate\Contracts\Routing\UrlGenerator setRootControllerNamespace(string $rootNamespace)
+ *
* @see \Illuminate\Routing\UrlGenerator
*/
class URL extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static \Illuminate\Contracts\Validation\Validator make(array $data, array $rules, array $messages = [], array $customAttributes = [])
+ * @method static void extend(string $rule, \Closure | string $extension, string $message = null)
+ * @method static void extendImplicit(string $rule, \Closure | string $extension, string $message = null)
+ * @method static void replacer(string $rule, \Closure | string $replacer)
+ *
* @see \Illuminate\Validation\Factory
*/
class Validator extends Facade
namespace Illuminate\Support\Facades;
/**
+ * @method static bool exists(string $view)
+ * @method static \Illuminate\Contracts\View\View file(string $path, array $data = [], array $mergeData = [])
+ * @method static \Illuminate\Contracts\View\View make(string $view, array $data = [], array $mergeData = [])
+ * @method static mixed share(array | string $key, $value = null)
+ * @method static array composer(array | string $views, \Closure | string $callback)
+ * @method static array creator(array | string $views, \Closure | string $callback)
+ * @method static \Illuminate\Contracts\View\Factory addNamespace(string $namespace, string | array $hints)
+ * @method static \Illuminate\Contracts\View\Factory replaceNamespace(string $namespace, string | array $hints)
+ *
* @see \Illuminate\View\Factory
*/
class View extends Facade
*/
public function offsetExists($offset)
{
- return isset($this->{$offset});
+ return isset($this->attributes[$offset]);
}
/**
*/
public function offsetGet($offset)
{
- return $this->{$offset};
+ return $this->get($offset);
}
/**
*/
public function offsetSet($offset, $value)
{
- $this->{$offset} = $value;
+ $this->attributes[$offset] = $value;
}
/**
*/
public function offsetUnset($offset)
{
- unset($this->{$offset});
+ unset($this->attributes[$offset]);
}
/**
*/
public function __set($key, $value)
{
- $this->attributes[$key] = $value;
+ $this->offsetSet($key, $value);
}
/**
*/
public function __isset($key)
{
- return isset($this->attributes[$key]);
+ return $this->offsetExists($key);
}
/**
*/
public function __unset($key)
{
- unset($this->attributes[$key]);
+ $this->offsetUnset($key);
}
}
namespace Illuminate\Support;
+/**
+ * @mixin \Illuminate\Support\Collection
+ */
class HigherOrderCollectionProxy
{
/**
--- /dev/null
+<?php
+
+namespace Illuminate\Support;
+
+use DateInterval;
+use DateTimeInterface;
+
+trait InteractsWithTime
+{
+ /**
+ * Get the number of seconds until the given DateTime.
+ *
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @return int
+ */
+ protected function secondsUntil($delay)
+ {
+ $delay = $this->parseDateInterval($delay);
+
+ return $delay instanceof DateTimeInterface
+ ? max(0, $delay->getTimestamp() - $this->currentTime())
+ : (int) $delay;
+ }
+
+ /**
+ * Get the "available at" UNIX timestamp.
+ *
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @return int
+ */
+ protected function availableAt($delay = 0)
+ {
+ $delay = $this->parseDateInterval($delay);
+
+ return $delay instanceof DateTimeInterface
+ ? $delay->getTimestamp()
+ : Carbon::now()->addSeconds($delay)->getTimestamp();
+ }
+
+ /**
+ * If the given value is an interval, convert it to a DateTime instance.
+ *
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @return \DateTimeInterface|int
+ */
+ protected function parseDateInterval($delay)
+ {
+ if ($delay instanceof DateInterval) {
+ $delay = Carbon::now()->add($delay);
+ }
+
+ return $delay;
+ }
+
+ /**
+ * Get the current system time as a UNIX timestamp.
+ *
+ * @return int
+ */
+ protected function currentTime()
+ {
+ return Carbon::now()->getTimestamp();
+ }
+}
{
$driver = $driver ?: $this->getDefaultDriver();
+ if (is_null($driver)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Unable to resolve NULL driver for [%s].', static::class
+ ));
+ }
+
// If the given driver has not been created before, we will create the instances
// here and cache it so we can return it next time very quickly. If there is
// already a driver created by this name, we'll just return that instance.
public function __construct(array $messages = [])
{
foreach ($messages as $key => $value) {
- $this->messages[$key] = (array) $value;
+ $this->messages[$key] = $value instanceof Arrayable
+ ? $value->toArray() : (array) $value;
}
}
return ! $this->any();
}
+ /**
+ * Determine if the message bag has any messages.
+ *
+ * @return bool
+ */
+ public function isNotEmpty()
+ {
+ return $this->any();
+ }
+
/**
* Determine if the message bag has any messages.
*
// just pulling an entire group out of the array and not a single item.
$group = $segments[0];
- if (count($segments) == 1) {
- return [null, $group, null];
- }
-
// If there is more than one segment in this group, it means we are pulling
// a specific item out of a group and will need to return this item name
// as well as the group so we know which item to pull from the arrays.
- else {
- $item = implode('.', array_slice($segments, 1));
+ $item = count($segments) === 1
+ ? null
+ : implode('.', array_slice($segments, 1));
- return [null, $group, $item];
- }
+ return [null, $group, $item];
}
/**
--- /dev/null
+<?php
+
+namespace Illuminate\Support;
+
+use ArrayAccess;
+
+class Optional implements ArrayAccess
+{
+ use Traits\Macroable {
+ __call as macroCall;
+ }
+
+ /**
+ * The underlying object.
+ *
+ * @var mixed
+ */
+ protected $value;
+
+ /**
+ * Create a new optional instance.
+ *
+ * @param mixed $value
+ * @return void
+ */
+ public function __construct($value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * Dynamically access a property on the underlying object.
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ if (is_object($this->value)) {
+ return $this->value->{$key} ?? null;
+ }
+ }
+
+ /**
+ * Dynamically check a property exists on the underlying object.
+ *
+ * @param $name
+ * @return bool
+ */
+ public function __isset($name)
+ {
+ if (is_object($this->value)) {
+ return isset($this->value->{$name});
+ }
+
+ if (is_array($this->value) || $this->value instanceof \ArrayObject) {
+ return isset($this->value[$name]);
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine if an item exists at an offset.
+ *
+ * @param mixed $key
+ * @return bool
+ */
+ public function offsetExists($key)
+ {
+ return Arr::accessible($this->value) && Arr::exists($this->value, $key);
+ }
+
+ /**
+ * Get an item at a given offset.
+ *
+ * @param mixed $key
+ * @return mixed
+ */
+ public function offsetGet($key)
+ {
+ return Arr::get($this->value, $key);
+ }
+
+ /**
+ * Set the item at a given offset.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return void
+ */
+ public function offsetSet($key, $value)
+ {
+ if (Arr::accessible($this->value)) {
+ $this->value[$key] = $value;
+ }
+ }
+
+ /**
+ * Unset the item at a given offset.
+ *
+ * @param string $key
+ * @return void
+ */
+ public function offsetUnset($key)
+ {
+ if (Arr::accessible($this->value)) {
+ unset($this->value[$key]);
+ }
+ }
+
+ /**
+ * Dynamically pass a method to the underlying object.
+ *
+ * @param string $method
+ * @param array $parameters
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (static::hasMacro($method)) {
+ return $this->macroCall($method, $parameters);
+ }
+
+ if (is_object($this->value)) {
+ return $this->value->{$method}(...$parameters);
+ }
+ }
+}
public static $uncountable = [
'audio',
'bison',
+ 'cattle',
'chassis',
'compensation',
'coreopsis',
'equipment',
'evidence',
'feedback',
+ 'firmware',
'fish',
'furniture',
'gold',
+ 'hardware',
'information',
'jedi',
+ 'kin',
'knowledge',
'love',
'metadata',
'rice',
'series',
'sheep',
+ 'software',
'species',
'swine',
'traffic',
--- /dev/null
+<?php
+
+namespace Illuminate\Support;
+
+/**
+ * ProcessUtils is a bunch of utility methods.
+ *
+ * This class was originally copied from Symfony 3.
+ */
+class ProcessUtils
+{
+ /**
+ * Escapes a string to be used as a shell argument.
+ *
+ * @param string $argument
+ * @return string
+ */
+ public static function escapeArgument($argument)
+ {
+ // Fix for PHP bug #43784 escapeshellarg removes % from given string
+ // Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
+ // @see https://bugs.php.net/bug.php?id=43784
+ // @see https://bugs.php.net/bug.php?id=49446
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ if ('' === $argument) {
+ return '""';
+ }
+
+ $escapedArgument = '';
+ $quote = false;
+
+ foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
+ if ('"' === $part) {
+ $escapedArgument .= '\\"';
+ } elseif (self::isSurroundedBy($part, '%')) {
+ // Avoid environment variable expansion
+ $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
+ } else {
+ // escape trailing backslash
+ if ('\\' === substr($part, -1)) {
+ $part .= '\\';
+ }
+ $quote = true;
+ $escapedArgument .= $part;
+ }
+ }
+
+ if ($quote) {
+ $escapedArgument = '"'.$escapedArgument.'"';
+ }
+
+ return $escapedArgument;
+ }
+
+ return "'".str_replace("'", "'\\''", $argument)."'";
+ }
+
+ /**
+ * Is the given string surrounded by the given character?
+ *
+ * @param string $arg
+ * @param string $char
+ * @return bool
+ */
+ protected static function isSurroundedBy($arg, $char)
+ {
+ return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
+ }
+}
*
* @var array
*/
- protected static $publishes = [];
+ public static $publishes = [];
/**
* The paths that should be published by group.
*
* @var array
*/
- protected static $publishGroups = [];
+ public static $publishGroups = [];
/**
* Create a new service provider instance.
*
- * @param \Illuminate\Contracts\Foundation\Application $app
+ * @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function __construct($app)
*/
protected function loadViewsFrom($path, $namespace)
{
- if (is_dir($appPath = $this->app->resourcePath().'/views/vendor/'.$namespace)) {
- $this->app['view']->addNamespace($namespace, $appPath);
+ if (is_array($this->app->config['view']['paths'])) {
+ foreach ($this->app->config['view']['paths'] as $viewPath) {
+ if (is_dir($appPath = $viewPath.'/vendor/'.$namespace)) {
+ $this->app['view']->addNamespace($namespace, $appPath);
+ }
+ }
}
$this->app['view']->addNamespace($namespace, $path);
$this->app['translator']->addNamespace($namespace, $path);
}
+ /**
+ * Register a JSON translation file path.
+ *
+ * @param string $path
+ * @return void
+ */
+ protected function loadJsonTranslationsFrom($path)
+ {
+ $this->app['translator']->addJsonPath($path);
+ }
+
/**
* Register a database migration path.
*
}
/**
- * Get the paths for the provdider and group.
+ * Get the paths for the provider and group.
*
* @param string $provider
* @param string $group
return [];
}
+ /**
+ * Get the service providers available for publishing.
+ *
+ * @return array
+ */
+ public static function publishableProviders()
+ {
+ return array_keys(static::$publishes);
+ }
+
+ /**
+ * Get the groups available for publishing.
+ *
+ * @return array
+ */
+ public static function publishableGroups()
+ {
+ return array_keys(static::$publishGroups);
+ }
+
/**
* Register the package's custom Artisan commands.
*
{
return $this->defer;
}
-
- /**
- * Get a list of files that should be compiled for the package.
- *
- * @deprecated
- *
- * @return array
- */
- public static function compiles()
- {
- return [];
- }
}
namespace Illuminate\Support;
+use Ramsey\Uuid\Uuid;
+use Ramsey\Uuid\UuidFactory;
use Illuminate\Support\Traits\Macroable;
+use Ramsey\Uuid\Generator\CombGenerator;
+use Ramsey\Uuid\Codec\TimestampFirstCombCodec;
class Str
{
*/
public static function after($subject, $search)
{
- if ($search == '') {
- return $subject;
- }
-
- $pos = strpos($subject, $search);
-
- if ($pos === false) {
- return $subject;
- }
-
- return substr($subject, $pos + strlen($search));
+ return $search === '' ? $subject : array_reverse(explode($search, $subject, 2))[0];
}
/**
* Transliterate a UTF-8 value to ASCII.
*
* @param string $value
+ * @param string $language
* @return string
*/
- public static function ascii($value)
+ public static function ascii($value, $language = 'en')
{
+ $languageSpecific = static::languageSpecificCharsArray($language);
+
+ if (! is_null($languageSpecific)) {
+ $value = str_replace($languageSpecific[0], $languageSpecific[1], $value);
+ }
+
foreach (static::charsArray() as $key => $val) {
$value = str_replace($val, $key, $value);
}
return preg_replace('/[^\x20-\x7E]/u', '', $value);
}
+ /**
+ * Get the portion of a string before a given value.
+ *
+ * @param string $subject
+ * @param string $search
+ * @return string
+ */
+ public static function before($subject, $search)
+ {
+ return $search === '' ? $subject : explode($search, $subject)[0];
+ }
+
/**
* Convert a value to camel case.
*
public static function contains($haystack, $needles)
{
foreach ((array) $needles as $needle) {
- if ($needle != '' && mb_strpos($haystack, $needle) !== false) {
+ if ($needle !== '' && mb_strpos($haystack, $needle) !== false) {
return true;
}
}
/**
* Determine if a given string matches a given pattern.
*
- * @param string $pattern
+ * @param string|array $pattern
* @param string $value
* @return bool
*/
public static function is($pattern, $value)
{
- if ($pattern == $value) {
- return true;
+ $patterns = Arr::wrap($pattern);
+
+ if (empty($patterns)) {
+ return false;
}
- $pattern = preg_quote($pattern, '#');
+ foreach ($patterns as $pattern) {
+ // If the given value is an exact match we can of course return true right
+ // from the beginning. Otherwise, we will translate asterisks and do an
+ // actual pattern match against the two strings to see if they match.
+ if ($pattern == $value) {
+ return true;
+ }
+
+ $pattern = preg_quote($pattern, '#');
+
+ // Asterisks are translated into zero-or-more regular expression wildcards
+ // to make it convenient to check if the strings starts with the given
+ // pattern such as "library/*", making any string check convenient.
+ $pattern = str_replace('\*', '.*', $pattern);
- // Asterisks are translated into zero-or-more regular expression wildcards
- // to make it convenient to check if the strings starts with the given
- // pattern such as "library/*", making any string check convenient.
- $pattern = str_replace('\*', '.*', $pattern);
+ if (preg_match('#^'.$pattern.'\z#u', $value) === 1) {
+ return true;
+ }
+ }
- return (bool) preg_match('#^'.$pattern.'\z#u', $value);
+ return false;
}
/**
return $string;
}
- /**
- * Generate a "random" alpha-numeric string.
- *
- * Should not be considered sufficient for cryptography, etc.
- *
- * @deprecated since version 5.3. Use the "random" method directly.
- *
- * @param int $length
- * @return string
- */
- public static function quickRandom($length = 16)
- {
- if (PHP_MAJOR_VERSION > 5) {
- return static::random($length);
- }
-
- $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-
- return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
- }
-
/**
* Replace a given value in the string sequentially with an array.
*
return $subject;
}
+ /**
+ * Begin a string with a single instance of a given value.
+ *
+ * @param string $value
+ * @param string $prefix
+ * @return string
+ */
+ public static function start($value, $prefix)
+ {
+ $quoted = preg_quote($prefix, '/');
+
+ return $prefix.preg_replace('/^(?:'.$quoted.')+/u', '', $value);
+ }
+
/**
* Convert the given string to upper-case.
*
*
* @param string $title
* @param string $separator
+ * @param string $language
* @return string
*/
- public static function slug($title, $separator = '-')
+ public static function slug($title, $separator = '-', $language = 'en')
{
- $title = static::ascii($title);
+ $title = static::ascii($title, $language);
// Convert all dashes/underscores into separator
$flip = $separator == '-' ? '_' : '-';
$title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);
+ // Replace @ with the word 'at'
+ $title = str_replace('@', $separator.'at'.$separator, $title);
+
// Remove all characters that are not the separator, letters, numbers, or whitespace.
$title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title));
}
if (! ctype_lower($value)) {
- $value = preg_replace('/\s+/u', '', $value);
+ $value = preg_replace('/\s+/u', '', ucwords($value));
$value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
}
public static function startsWith($haystack, $needles)
{
foreach ((array) $needles as $needle) {
- if ($needle != '' && substr($haystack, 0, strlen($needle)) === (string) $needle) {
+ if ($needle !== '' && substr($haystack, 0, strlen($needle)) === (string) $needle) {
return true;
}
}
return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
}
+ /**
+ * Generate a UUID (version 4).
+ *
+ * @return \Ramsey\Uuid\UuidInterface
+ */
+ public static function uuid()
+ {
+ return Uuid::uuid4();
+ }
+
+ /**
+ * Generate a time-ordered UUID (version 4).
+ *
+ * @return \Ramsey\Uuid\UuidInterface
+ */
+ public static function orderedUuid()
+ {
+ $factory = new UuidFactory;
+
+ $factory->setRandomGenerator(new CombGenerator(
+ $factory->getRandomGenerator(),
+ $factory->getNumberConverter()
+ ));
+
+ $factory->setCodec(new TimestampFirstCombCodec(
+ $factory->getUuidBuilder()
+ ));
+
+ return $factory->uuid4();
+ }
+
/**
* Returns the replacements for the ascii method.
*
* Note: Adapted from Stringy\Stringy.
*
- * @see https://github.com/danielstjules/Stringy/blob/2.3.1/LICENSE.txt
+ * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt
*
* @return array
*/
}
return $charsArray = [
- '0' => ['°', '₀', '۰'],
- '1' => ['¹', '₁', '۱'],
- '2' => ['²', '₂', '۲'],
- '3' => ['³', '₃', '۳'],
- '4' => ['⁴', '₄', '۴', '٤'],
- '5' => ['⁵', '₅', '۵', '٥'],
- '6' => ['⁶', '₆', '۶', '٦'],
- '7' => ['⁷', '₇', '۷'],
- '8' => ['⁸', '₈', '۸'],
- '9' => ['⁹', '₉', '۹'],
- 'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا'],
- 'b' => ['б', 'β', 'Ъ', 'Ь', 'ب', 'ဗ', 'ბ'],
- 'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
- 'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ'],
- 'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ'],
- 'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ'],
- 'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ'],
- 'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ'],
- 'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ'],
- 'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج'],
- 'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک'],
- 'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'],
- 'm' => ['м', 'μ', 'م', 'မ', 'მ'],
- 'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ'],
- 'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ'],
- 'p' => ['п', 'π', 'ပ', 'პ', 'پ'],
- 'q' => ['ყ'],
- 'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ'],
- 's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს'],
- 't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ'],
- 'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ'],
- 'v' => ['в', 'ვ', 'ϐ'],
- 'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ'],
- 'x' => ['χ', 'ξ'],
- 'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ'],
- 'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ'],
+ '0' => ['°', '₀', '۰', '0'],
+ '1' => ['¹', '₁', '۱', '1'],
+ '2' => ['²', '₂', '۲', '2'],
+ '3' => ['³', '₃', '۳', '3'],
+ '4' => ['⁴', '₄', '۴', '٤', '4'],
+ '5' => ['⁵', '₅', '۵', '٥', '5'],
+ '6' => ['⁶', '₆', '۶', '٦', '6'],
+ '7' => ['⁷', '₇', '۷', '7'],
+ '8' => ['⁸', '₈', '۸', '8'],
+ '9' => ['⁹', '₉', '۹', '9'],
+ 'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا', 'a', 'ä'],
+ 'b' => ['б', 'β', 'ب', 'ဗ', 'ბ', 'b'],
+ 'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ', 'c'],
+ 'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ', 'd'],
+ 'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ', 'e'],
+ 'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ', 'f'],
+ 'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ', 'g'],
+ 'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ', 'h'],
+ 'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ', 'ی', 'i'],
+ 'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج', 'j'],
+ 'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک', 'k'],
+ 'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ', 'l'],
+ 'm' => ['м', 'μ', 'م', 'မ', 'მ', 'm'],
+ 'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ', 'n'],
+ 'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ', 'o', 'ö'],
+ 'p' => ['п', 'π', 'ပ', 'პ', 'پ', 'p'],
+ 'q' => ['ყ', 'q'],
+ 'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ', 'r'],
+ 's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს', 's'],
+ 't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ', 't'],
+ 'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ', 'u', 'ў', 'ü'],
+ 'v' => ['в', 'ვ', 'ϐ', 'v'],
+ 'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ', 'w'],
+ 'x' => ['χ', 'ξ', 'x'],
+ 'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ', 'y'],
+ 'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ', 'z'],
'aa' => ['ع', 'आ', 'آ'],
- 'ae' => ['ä', 'æ', 'ǽ'],
+ 'ae' => ['æ', 'ǽ'],
'ai' => ['ऐ'],
- 'at' => ['@'],
'ch' => ['ч', 'ჩ', 'ჭ', 'چ'],
'dj' => ['ђ', 'đ'],
'dz' => ['џ', 'ძ'],
'yu' => ['ю'],
'zh' => ['ж', 'ჟ', 'ژ'],
'(c)' => ['©'],
- 'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ'],
- 'B' => ['Б', 'Β', 'ब'],
- 'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
- 'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'],
- 'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə'],
- 'F' => ['Ф', 'Φ'],
- 'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
- 'H' => ['Η', 'Ή', 'Ħ'],
- 'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ'],
- 'K' => ['К', 'Κ'],
- 'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल'],
- 'M' => ['М', 'Μ'],
- 'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'],
- 'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ'],
- 'P' => ['П', 'Π'],
- 'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'],
- 'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
- 'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
- 'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ'],
- 'V' => ['В'],
- 'W' => ['Ω', 'Ώ', 'Ŵ'],
- 'X' => ['Χ', 'Ξ'],
- 'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ'],
- 'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
- 'AE' => ['Ä', 'Æ', 'Ǽ'],
- 'CH' => ['Ч'],
- 'DJ' => ['Ђ'],
- 'DZ' => ['Џ'],
- 'GX' => ['Ĝ'],
- 'HX' => ['Ĥ'],
- 'IJ' => ['IJ'],
- 'JX' => ['Ĵ'],
- 'KH' => ['Х'],
- 'LJ' => ['Љ'],
- 'NJ' => ['Њ'],
- 'OE' => ['Ö', 'Œ'],
- 'PS' => ['Ψ'],
- 'SH' => ['Ш'],
- 'SHCH' => ['Щ'],
- 'SS' => ['ẞ'],
- 'TH' => ['Þ'],
- 'TS' => ['Ц'],
- 'UE' => ['Ü'],
- 'YA' => ['Я'],
- 'YU' => ['Ю'],
- 'ZH' => ['Ж'],
- ' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80"],
+ 'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ', 'A', 'Ä'],
+ 'B' => ['Б', 'Β', 'ब', 'B'],
+ 'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ', 'C'],
+ 'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ', 'D'],
+ 'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə', 'E'],
+ 'F' => ['Ф', 'Φ', 'F'],
+ 'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ', 'G'],
+ 'H' => ['Η', 'Ή', 'Ħ', 'H'],
+ 'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ', 'I'],
+ 'J' => ['J'],
+ 'K' => ['К', 'Κ', 'K'],
+ 'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल', 'L'],
+ 'M' => ['М', 'Μ', 'M'],
+ 'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν', 'N'],
+ 'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ', 'O', 'Ö'],
+ 'P' => ['П', 'Π', 'P'],
+ 'Q' => ['Q'],
+ 'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ', 'R'],
+ 'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ', 'S'],
+ 'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ', 'T'],
+ 'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ', 'U', 'Ў', 'Ü'],
+ 'V' => ['В', 'V'],
+ 'W' => ['Ω', 'Ώ', 'Ŵ', 'W'],
+ 'X' => ['Χ', 'Ξ', 'X'],
+ 'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ', 'Y'],
+ 'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ', 'Z'],
+ 'AE' => ['Æ', 'Ǽ'],
+ 'Ch' => ['Ч'],
+ 'Dj' => ['Ђ'],
+ 'Dz' => ['Џ'],
+ 'Gx' => ['Ĝ'],
+ 'Hx' => ['Ĥ'],
+ 'Ij' => ['IJ'],
+ 'Jx' => ['Ĵ'],
+ 'Kh' => ['Х'],
+ 'Lj' => ['Љ'],
+ 'Nj' => ['Њ'],
+ 'Oe' => ['Œ'],
+ 'Ps' => ['Ψ'],
+ 'Sh' => ['Ш'],
+ 'Shch' => ['Щ'],
+ 'Ss' => ['ẞ'],
+ 'Th' => ['Þ'],
+ 'Ts' => ['Ц'],
+ 'Ya' => ['Я'],
+ 'Yu' => ['Ю'],
+ 'Zh' => ['Ж'],
+ ' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80", "\xEF\xBE\xA0"],
];
}
+
+ /**
+ * Returns the language specific replacements for the ascii method.
+ *
+ * Note: Adapted from Stringy\Stringy.
+ *
+ * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt
+ *
+ * @param string $language
+ * @return array|null
+ */
+ protected static function languageSpecificCharsArray($language)
+ {
+ static $languageSpecific;
+
+ if (! isset($languageSpecific)) {
+ $languageSpecific = [
+ 'bg' => [
+ ['х', 'Х', 'щ', 'Щ', 'ъ', 'Ъ', 'ь', 'Ь'],
+ ['h', 'H', 'sht', 'SHT', 'a', 'А', 'y', 'Y'],
+ ],
+ 'de' => [
+ ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'],
+ ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'],
+ ],
+ ];
+ }
+
+ return $languageSpecific[$language] ?? null;
+ }
}
* Assert if a job was dispatched based on a truth-test callback.
*
* @param string $command
- * @param callable|null $callback
+ * @param callable|int|null $callback
* @return void
*/
public function assertDispatched($command, $callback = null)
{
+ if (is_numeric($callback)) {
+ return $this->assertDispatchedTimes($command, $callback);
+ }
+
PHPUnit::assertTrue(
$this->dispatched($command, $callback)->count() > 0,
"The expected [{$command}] job was not dispatched."
);
}
+ /**
+ * Assert if a job was pushed a number of times.
+ *
+ * @param string $command
+ * @param int $times
+ * @return void
+ */
+ protected function assertDispatchedTimes($command, $times = 1)
+ {
+ PHPUnit::assertTrue(
+ ($count = $this->dispatched($command)->count()) === $times,
+ "The expected [{$command}] job was pushed {$count} times instead of {$times} times."
+ );
+ }
+
/**
* Determine if a job was dispatched based on a truth-test callback.
*
{
//
}
+
+ /**
+ * Determine if the given command has a handler.
+ *
+ * @param mixed $command
+ * @return bool
+ */
+ public function hasCommandHandler($command)
+ {
+ return false;
+ }
+
+ /**
+ * Retrieve the handler for a command.
+ *
+ * @param mixed $command
+ * @return mixed
+ */
+ public function getCommandHandler($command)
+ {
+ return false;
+ }
+
+ /**
+ * Map a command to a handler.
+ *
+ * @param array $map
+ * @return $this
+ */
+ public function map(array $map)
+ {
+ return $this;
+ }
}
namespace Illuminate\Support\Testing\Fakes;
+use Illuminate\Support\Arr;
use PHPUnit\Framework\Assert as PHPUnit;
use Illuminate\Contracts\Events\Dispatcher;
class EventFake implements Dispatcher
{
/**
- * All of the events that have been dispatched keyed by type.
+ * The original event dispatcher.
+ *
+ * @var \Illuminate\Contracts\Events\Dispatcher
+ */
+ protected $dispatcher;
+
+ /**
+ * The event types that should be intercepted instead of dispatched.
+ *
+ * @var array
+ */
+ protected $eventsToFake;
+
+ /**
+ * All of the events that have been intercepted keyed by type.
*
* @var array
*/
protected $events = [];
+ /**
+ * Create a new event fake instance.
+ *
+ * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
+ * @param array|string $eventsToFake
+ * @return void
+ */
+ public function __construct(Dispatcher $dispatcher, $eventsToFake = [])
+ {
+ $this->dispatcher = $dispatcher;
+
+ $this->eventsToFake = Arr::wrap($eventsToFake);
+ }
+
/**
* Assert if an event was dispatched based on a truth-test callback.
*
* @param string $event
- * @param callable|null $callback
+ * @param callable|int|null $callback
* @return void
*/
public function assertDispatched($event, $callback = null)
{
+ if (is_int($callback)) {
+ return $this->assertDispatchedTimes($event, $callback);
+ }
+
PHPUnit::assertTrue(
$this->dispatched($event, $callback)->count() > 0,
"The expected [{$event}] event was not dispatched."
);
}
+ /**
+ * Assert if a event was dispatched a number of times.
+ *
+ * @param string $event
+ * @param int $times
+ * @return void
+ */
+ public function assertDispatchedTimes($event, $times = 1)
+ {
+ PHPUnit::assertTrue(
+ ($count = $this->dispatched($event)->count()) === $times,
+ "The expected [{$event}] event was dispatched {$count} times instead of {$times} times."
+ );
+ }
+
/**
* Determine if an event was dispatched based on a truth-test callback.
*
{
$name = is_object($event) ? get_class($event) : (string) $event;
- $this->events[$name][] = func_get_args();
+ if ($this->shouldFakeEvent($name)) {
+ $this->events[$name][] = func_get_args();
+ } else {
+ $this->dispatcher->dispatch($event, $payload, $halt);
+ }
+ }
+
+ /**
+ * Determine if an event should be faked or actually dispatched.
+ *
+ * @param string $eventName
+ * @return bool
+ */
+ protected function shouldFakeEvent($eventName)
+ {
+ return empty($this->eventsToFake) || in_array($eventName, $this->eventsToFake);
}
/**
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Contracts\Mail\Mailable;
use PHPUnit\Framework\Assert as PHPUnit;
+use Illuminate\Contracts\Queue\ShouldQueue;
class MailFake implements Mailer
{
*/
protected $mailables = [];
+ /**
+ * All of the mailables that have been queued.
+ *
+ * @var array
+ */
+ protected $queuedMailables = [];
+
/**
* Assert if a mailable was sent based on a truth-test callback.
*
* @param string $mailable
- * @param callable|null $callback
+ * @param callable|int|null $callback
* @return void
*/
public function assertSent($mailable, $callback = null)
{
+ if (is_numeric($callback)) {
+ return $this->assertSentTimes($mailable, $callback);
+ }
+
PHPUnit::assertTrue(
$this->sent($mailable, $callback)->count() > 0,
"The expected [{$mailable}] mailable was not sent."
);
}
+ /**
+ * Assert if a mailable was sent a number of times.
+ *
+ * @param string $mailable
+ * @param int $times
+ * @return void
+ */
+ protected function assertSentTimes($mailable, $times = 1)
+ {
+ PHPUnit::assertTrue(
+ ($count = $this->sent($mailable)->count()) === $times,
+ "The expected [{$mailable}] mailable was sent {$count} times instead of {$times} times."
+ );
+ }
+
/**
* Determine if a mailable was not sent based on a truth-test callback.
*
PHPUnit::assertEmpty($this->mailables, 'Mailables were sent unexpectedly.');
}
+ /**
+ * Assert if a mailable was queued based on a truth-test callback.
+ *
+ * @param string $mailable
+ * @param callable|int|null $callback
+ * @return void
+ */
+ public function assertQueued($mailable, $callback = null)
+ {
+ if (is_numeric($callback)) {
+ return $this->assertQueuedTimes($mailable, $callback);
+ }
+
+ PHPUnit::assertTrue(
+ $this->queued($mailable, $callback)->count() > 0,
+ "The expected [{$mailable}] mailable was not queued."
+ );
+ }
+
+ /**
+ * Assert if a mailable was queued a number of times.
+ *
+ * @param string $mailable
+ * @param int $times
+ * @return void
+ */
+ protected function assertQueuedTimes($mailable, $times = 1)
+ {
+ PHPUnit::assertTrue(
+ ($count = $this->queued($mailable)->count()) === $times,
+ "The expected [{$mailable}] mailable was queued {$count} times instead of {$times} times."
+ );
+ }
+
+ /**
+ * Determine if a mailable was not queued based on a truth-test callback.
+ *
+ * @param string $mailable
+ * @param callable|null $callback
+ * @return void
+ */
+ public function assertNotQueued($mailable, $callback = null)
+ {
+ PHPUnit::assertTrue(
+ $this->queued($mailable, $callback)->count() === 0,
+ "The unexpected [{$mailable}] mailable was queued."
+ );
+ }
+
+ /**
+ * Assert that no mailables were queued.
+ *
+ * @return void
+ */
+ public function assertNothingQueued()
+ {
+ PHPUnit::assertEmpty($this->queuedMailables, 'Mailables were queued unexpectedly.');
+ }
+
/**
* Get all of the mailables matching a truth-test callback.
*
return $this->mailablesOf($mailable)->count() > 0;
}
+ /**
+ * Get all of the queued mailables matching a truth-test callback.
+ *
+ * @param string $mailable
+ * @param callable|null $callback
+ * @return \Illuminate\Support\Collection
+ */
+ public function queued($mailable, $callback = null)
+ {
+ if (! $this->hasQueued($mailable)) {
+ return collect();
+ }
+
+ $callback = $callback ?: function () {
+ return true;
+ };
+
+ return $this->queuedMailablesOf($mailable)->filter(function ($mailable) use ($callback) {
+ return $callback($mailable);
+ });
+ }
+
+ /**
+ * Determine if the given mailable has been queued.
+ *
+ * @param string $mailable
+ * @return bool
+ */
+ public function hasQueued($mailable)
+ {
+ return $this->queuedMailablesOf($mailable)->count() > 0;
+ }
+
/**
* Get all of the mailed mailables for a given type.
*
});
}
+ /**
+ * Get all of the mailed mailables for a given type.
+ *
+ * @param string $type
+ * @return \Illuminate\Support\Collection
+ */
+ protected function queuedMailablesOf($type)
+ {
+ return collect($this->queuedMailables)->filter(function ($mailable) use ($type) {
+ return $mailable instanceof $type;
+ });
+ }
+
/**
* Begin the process of mailing a mailable class instance.
*
return;
}
+ if ($view instanceof ShouldQueue) {
+ return $this->queue($view, $data, $callback);
+ }
+
$this->mailables[] = $view;
}
* Queue a new e-mail message for sending.
*
* @param string|array $view
- * @param array $data
- * @param \Closure|string $callback
* @param string|null $queue
* @return mixed
*/
- public function queue($view, array $data = [], $callback = null, $queue = null)
+ public function queue($view, $queue = null)
{
- $this->send($view);
+ if (! $view instanceof Mailable) {
+ return;
+ }
+
+ $this->queuedMailables[] = $view;
}
/**
use Illuminate\Support\Collection;
use PHPUnit\Framework\Assert as PHPUnit;
use Illuminate\Contracts\Notifications\Factory as NotificationFactory;
+use Illuminate\Contracts\Notifications\Dispatcher as NotificationDispatcher;
-class NotificationFake implements NotificationFactory
+class NotificationFake implements NotificationFactory, NotificationDispatcher
{
/**
* All of the notifications that have been sent.
return;
}
+ if (is_numeric($callback)) {
+ return $this->assertSentToTimes($notifiable, $notification, $callback);
+ }
+
PHPUnit::assertTrue(
$this->sent($notifiable, $notification, $callback)->count() > 0,
"The expected [{$notification}] notification was not sent."
);
}
+ /**
+ * Assert if a notification was sent a number of times.
+ *
+ * @param mixed $notifiable
+ * @param string $notification
+ * @param int $times
+ * @return void
+ */
+ public function assertSentToTimes($notifiable, $notification, $times = 1)
+ {
+ PHPUnit::assertTrue(
+ ($count = $this->sent($notifiable, $notification)->count()) === $times,
+ "The expected [{$notification}] notification was sent {$count} times instead of {$times} times."
+ );
+ }
+
/**
* Determine if a notification was sent based on a truth-test callback.
*
);
}
+ /**
+ * Assert that no notifications were sent.
+ *
+ * @return void
+ */
+ public function assertNothingSent()
+ {
+ PHPUnit::assertEmpty($this->notifications, 'Notifications were sent unexpectedly.');
+ }
+
/**
* Get all of the notifications matching a truth-test callback.
*
}
foreach ($notifiables as $notifiable) {
- $notification->id = Uuid::uuid4()->toString();
+ if (! $notification->id) {
+ $notification->id = Uuid::uuid4()->toString();
+ }
$this->notifications[get_class($notifiable)][$notifiable->getKey()][get_class($notification)][] = [
'notification' => $notification,
'channels' => $notification->via($notifiable),
+ 'notifiable' => $notifiable,
];
}
}
/**
* Send a new mailable message instance.
*
- * @param Mailable $mailable
+ * @param \Illuminate\Mail\Mailable $mailable
* @return mixed
*/
public function send(Mailable $mailable)
/**
* Send a mailable message immediately.
*
- * @param Mailable $mailable
+ * @param \Illuminate\Mail\Mailable $mailable
* @return mixed
*/
public function sendNow(Mailable $mailable)
/**
* Push the given mailable onto the queue.
*
- * @param Mailable $mailable
+ * @param \Illuminate\Mail\Mailable $mailable
* @return mixed
*/
public function queue(Mailable $mailable)
{
- return $this->sendNow($mailable);
+ return $this->mailer->queue($this->fill($mailable));
}
}
* Assert if a job was pushed based on a truth-test callback.
*
* @param string $job
- * @param callable|null $callback
+ * @param callable|int|null $callback
* @return void
*/
public function assertPushed($job, $callback = null)
{
+ if (is_numeric($callback)) {
+ return $this->assertPushedTimes($job, $callback);
+ }
+
PHPUnit::assertTrue(
$this->pushed($job, $callback)->count() > 0,
"The expected [{$job}] job was not pushed."
);
}
+ /**
+ * Assert if a job was pushed a number of times.
+ *
+ * @param string $job
+ * @param int $times
+ * @return void
+ */
+ protected function assertPushedTimes($job, $times = 1)
+ {
+ PHPUnit::assertTrue(
+ ($count = $this->pushed($job)->count()) === $times,
+ "The expected [{$job}] job was pushed {$count} times instead of {$times} times."
+ );
+ }
+
/**
* Assert if a job was pushed based on a truth-test callback.
*
});
}
+ /**
+ * Assert if a job was pushed with chained jobs based on a truth-test callback.
+ *
+ * @param string $job
+ * @param array $expectedChain
+ * @param callable|null $callback
+ * @return void
+ */
+ public function assertPushedWithChain($job, $expectedChain = [], $callback = null)
+ {
+ PHPUnit::assertTrue(
+ $this->pushed($job, $callback)->isNotEmpty(),
+ "The expected [{$job}] job was not pushed."
+ );
+
+ PHPUnit::assertTrue(
+ collect($expectedChain)->isNotEmpty(),
+ 'The expected chain can not be empty.'
+ );
+
+ $this->isChainOfObjects($expectedChain)
+ ? $this->assertPushedWithChainOfObjects($job, $expectedChain, $callback)
+ : $this->assertPushedWithChainOfClasses($job, $expectedChain, $callback);
+ }
+
+ /**
+ * Assert if a job was pushed with chained jobs based on a truth-test callback.
+ *
+ * @param string $job
+ * @param array $expectedChain
+ * @param callable|null $callback
+ * @return void
+ */
+ protected function assertPushedWithChainOfObjects($job, $expectedChain, $callback)
+ {
+ $chain = collect($expectedChain)->map(function ($job) {
+ return serialize($job);
+ })->all();
+
+ PHPUnit::assertTrue(
+ $this->pushed($job, $callback)->filter(function ($job) use ($chain) {
+ return $job->chained == $chain;
+ })->isNotEmpty(),
+ 'The expected chain was not pushed.'
+ );
+ }
+
+ /**
+ * Assert if a job was pushed with chained jobs based on a truth-test callback.
+ *
+ * @param string $job
+ * @param array $expectedChain
+ * @param callable|null $callback
+ * @return void
+ */
+ protected function assertPushedWithChainOfClasses($job, $expectedChain, $callback)
+ {
+ $matching = $this->pushed($job, $callback)->map->chained->map(function ($chain) {
+ return collect($chain)->map(function ($job) {
+ return get_class(unserialize($job));
+ });
+ })->filter(function ($chain) use ($expectedChain) {
+ return $chain->all() === $expectedChain;
+ });
+
+ PHPUnit::assertTrue(
+ $matching->isNotEmpty(), 'The expected chain was not pushed.'
+ );
+ }
+
+ /**
+ * Determine if the given chain is entirely composed of objects.
+ *
+ * @param array $chain
+ * @return bool
+ */
+ protected function isChainOfObjects($chain)
+ {
+ return collect($chain)->count() == collect($chain)
+ ->filter(function ($job) {
+ return is_object($job);
+ })->count();
+ }
+
/**
* Determine if a job was pushed based on a truth-test callback.
*
);
}
+ /**
+ * Assert that no jobs were pushed.
+ *
+ * @return void
+ */
+ public function assertNothingPushed()
+ {
+ PHPUnit::assertEmpty($this->jobs, 'Jobs were pushed unexpectedly.');
+ }
+
/**
* Get all of the jobs matching a truth-test callback.
*
*/
public function size($queue = null)
{
- return 0;
+ return count($this->jobs);
}
/**
*/
public function bulk($jobs, $data = '', $queue = null)
{
- foreach ($this->jobs as $job) {
- $this->push($job);
+ foreach ($jobs as $job) {
+ $this->push($job, $data, $queue);
}
}
--- /dev/null
+<?php
+
+namespace Illuminate\Support\Traits;
+
+trait Localizable
+{
+ /**
+ * Run the callback with the given locale.
+ *
+ * @param string $locale
+ * @param \Illuminate\Contracts\Translation\Translator $translator
+ * @param \Closure $callback
+ * @return bool
+ */
+ public function withLocale($locale, $translator, $callback)
+ {
+ if (! $locale || ! $translator) {
+ return $callback();
+ }
+
+ $original = $translator->getLocale();
+
+ try {
+ $translator->setLocale($locale);
+
+ return $callback();
+ } finally {
+ $translator->setLocale($original);
+ }
+ }
+}
namespace Illuminate\Support\Traits;
use Closure;
+use ReflectionClass;
+use ReflectionMethod;
use BadMethodCallException;
trait Macroable
/**
* Register a custom macro.
*
- * @param string $name
- * @param callable $macro
+ * @param string $name
+ * @param object|callable $macro
+ *
* @return void
*/
- public static function macro($name, callable $macro)
+ public static function macro($name, $macro)
{
static::$macros[$name] = $macro;
}
+ /**
+ * Mix another object into the class.
+ *
+ * @param object $mixin
+ * @return void
+ * @throws \ReflectionException
+ */
+ public static function mixin($mixin)
+ {
+ $methods = (new ReflectionClass($mixin))->getMethods(
+ ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
+ );
+
+ foreach ($methods as $method) {
+ $method->setAccessible(true);
+
+ static::macro($method->name, $method->invoke($mixin));
+ }
+ }
+
/**
* Checks if macro is registered.
*
public static function __callStatic($method, $parameters)
{
if (! static::hasMacro($method)) {
- throw new BadMethodCallException("Method {$method} does not exist.");
+ throw new BadMethodCallException(sprintf(
+ 'Method %s::%s does not exist.', static::class, $method
+ ));
}
if (static::$macros[$method] instanceof Closure) {
public function __call($method, $parameters)
{
if (! static::hasMacro($method)) {
- throw new BadMethodCallException("Method {$method} does not exist.");
+ throw new BadMethodCallException(sprintf(
+ 'Method %s::%s does not exist.', static::class, $method
+ ));
}
- if (static::$macros[$method] instanceof Closure) {
- return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters);
+ $macro = static::$macros[$method];
+
+ if ($macro instanceof Closure) {
+ return call_user_func_array($macro->bindTo($this, static::class), $parameters);
}
- return call_user_func_array(static::$macros[$method], $parameters);
+ return call_user_func_array($macro, $parameters);
}
}
use Countable;
use Illuminate\Contracts\Support\MessageBag as MessageBagContract;
+/**
+ * @mixin \Illuminate\Contracts\Support\MessageBag
+ */
class ViewErrorBag implements Countable
{
/**
{
$this->put($key, $value);
}
+
+ /**
+ * Convert the default bag to its string representation.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string) $this->getBag('default');
+ }
}
}
],
"require": {
- "php": ">=5.6.4",
+ "php": "^7.1.3",
"ext-mbstring": "*",
- "doctrine/inflector": "~1.0",
- "illuminate/contracts": "5.4.*",
- "paragonie/random_compat": "~1.4|~2.0"
+ "doctrine/inflector": "~1.1",
+ "illuminate/contracts": "5.6.*",
+ "nesbot/carbon": "^1.24.1"
},
- "replace": {
- "tightenco/collect": "self.version"
+ "conflict": {
+ "tightenco/collect": "<5.5.33"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"suggest": {
- "illuminate/filesystem": "Required to use the composer class (5.2.*).",
- "symfony/process": "Required to use the composer class (~3.2).",
- "symfony/var-dumper": "Required to use the dd function (~3.2)."
+ "illuminate/filesystem": "Required to use the composer class (5.6.*).",
+ "symfony/process": "Required to use the composer class (~4.0).",
+ "symfony/var-dumper": "Required to use the dd function (~4.0)."
},
"config": {
"sort-packages": true
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
+use Illuminate\Support\Optional;
use Illuminate\Support\Collection;
use Illuminate\Support\Debug\Dumper;
use Illuminate\Contracts\Support\Htmlable;
if (! function_exists('array_except')) {
/**
- * Get all of the given array except for a specified array of items.
+ * Get all of the given array except for a specified array of keys.
*
* @param array $array
* @param array|string $keys
}
}
+if (! function_exists('array_random')) {
+ /**
+ * Get a random value from an array.
+ *
+ * @param array $array
+ * @param int|null $num
+ * @return mixed
+ */
+ function array_random($array, $num = null)
+ {
+ return Arr::random($array, $num);
+ }
+}
+
if (! function_exists('array_set')) {
/**
* Set an array item to a given value using "dot" notation.
* Sort the array by the given callback or attribute name.
*
* @param array $array
- * @param callable|string $callback
+ * @param callable|string|null $callback
* @return array
*/
- function array_sort($array, $callback)
+ function array_sort($array, $callback = null)
{
return Arr::sort($array, $callback);
}
}
}
+if (! function_exists('blank')) {
+ /**
+ * Determine if the given value is "blank".
+ *
+ * @param mixed $value
+ * @return bool
+ */
+ function blank($value)
+ {
+ if (is_null($value)) {
+ return true;
+ }
+
+ if (is_string($value)) {
+ return trim($value) === '';
+ }
+
+ if (is_numeric($value) || is_bool($value)) {
+ return false;
+ }
+
+ if ($value instanceof Countable) {
+ return count($value) === 0;
+ }
+
+ return empty($value);
+ }
+}
+
if (! function_exists('camel_case')) {
/**
* Convert a value to camel case.
$results = [];
- foreach (array_merge([$class => $class], class_parents($class)) as $class) {
+ foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) {
$results += trait_uses_recursive($class);
}
/**
* Dump the passed variables and end the script.
*
- * @param mixed
+ * @param mixed $args
* @return void
*/
function dd(...$args)
* Escape HTML special characters in a string.
*
* @param \Illuminate\Contracts\Support\Htmlable|string $value
+ * @param bool $doubleEncode
* @return string
*/
- function e($value)
+ function e($value, $doubleEncode = true)
{
if ($value instanceof Htmlable) {
return $value->toHtml();
}
- return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', false);
+ return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', $doubleEncode);
}
}
return;
}
- if (strlen($value) > 1 && Str::startsWith($value, '"') && Str::endsWith($value, '"')) {
+ if (($valueLength = strlen($value)) > 1 && $value[0] === '"' && $value[$valueLength - 1] === '"') {
return substr($value, 1, -1);
}
}
}
+if (! function_exists('filled')) {
+ /**
+ * Determine if a value is "filled".
+ *
+ * @param mixed $value
+ * @return bool
+ */
+ function filled($value)
+ {
+ return ! blank($value);
+ }
+}
+
if (! function_exists('head')) {
/**
* Get the first element of an array. Useful for method chaining.
}
}
+if (! function_exists('optional')) {
+ /**
+ * Provide access to optional objects.
+ *
+ * @param mixed $value
+ * @param callable|null $callback
+ * @return mixed
+ */
+ function optional($value = null, callable $callback = null)
+ {
+ if (is_null($callback)) {
+ return new Optional($value);
+ } elseif (! is_null($value)) {
+ return $callback($value);
+ }
+ }
+}
+
if (! function_exists('preg_replace_array')) {
/**
* Replace a given pattern with each value in the array in sequentially.
}
}
+if (! function_exists('str_before')) {
+ /**
+ * Get the portion of a string before a given value.
+ *
+ * @param string $subject
+ * @param string $search
+ * @return string
+ */
+ function str_before($subject, $search)
+ {
+ return Str::before($subject, $search);
+ }
+}
+
if (! function_exists('str_contains')) {
/**
* Determine if a given string contains a given substring.
/**
* Determine if a given string matches a given pattern.
*
- * @param string $pattern
+ * @param string|array $pattern
* @param string $value
* @return bool
*/
*
* @param string $title
* @param string $separator
+ * @param string $language
+ * @return string
+ */
+ function str_slug($title, $separator = '-', $language = 'en')
+ {
+ return Str::slug($title, $separator, $language);
+ }
+}
+
+if (! function_exists('str_start')) {
+ /**
+ * Begin a string with a single instance of a given value.
+ *
+ * @param string $value
+ * @param string $prefix
* @return string
*/
- function str_slug($title, $separator = '-')
+ function str_start($value, $prefix)
{
- return Str::slug($title, $separator);
+ return Str::start($value, $prefix);
}
}
}
}
+if (! function_exists('throw_if')) {
+ /**
+ * Throw the given exception if the given condition is true.
+ *
+ * @param mixed $condition
+ * @param \Throwable|string $exception
+ * @param array ...$parameters
+ * @return mixed
+ * @throws \Throwable
+ */
+ function throw_if($condition, $exception, ...$parameters)
+ {
+ if ($condition) {
+ throw (is_string($exception) ? new $exception(...$parameters) : $exception);
+ }
+
+ return $condition;
+ }
+}
+
+if (! function_exists('throw_unless')) {
+ /**
+ * Throw the given exception unless the given condition is true.
+ *
+ * @param mixed $condition
+ * @param \Throwable|string $exception
+ * @param array ...$parameters
+ * @return mixed
+ * @throws \Throwable
+ */
+ function throw_unless($condition, $exception, ...$parameters)
+ {
+ if (! $condition) {
+ throw (is_string($exception) ? new $exception(...$parameters) : $exception);
+ }
+
+ return $condition;
+ }
+}
+
if (! function_exists('title_case')) {
/**
* Convert a value to title case.
}
}
+if (! function_exists('transform')) {
+ /**
+ * Transform the given value if it is present.
+ *
+ * @param mixed $value
+ * @param callable $callback
+ * @param mixed $default
+ * @return mixed|null
+ */
+ function transform($value, callable $callback, $default = null)
+ {
+ if (filled($value)) {
+ return $callback($value);
+ }
+
+ if (is_callable($default)) {
+ return $default($value);
+ }
+
+ return $default;
+ }
+}
+
if (! function_exists('value')) {
/**
* Return the default value of the given value.
if (! function_exists('with')) {
/**
- * Return the given object. Useful for chaining.
+ * Return the given value, optionally passed through the given callback.
*
- * @param mixed $object
+ * @param mixed $value
+ * @param callable|null $callback
* @return mixed
*/
- function with($object)
+ function with($value, callable $callback = null)
{
- return $object;
+ return is_null($callback) ? $value : $callback($value);
}
}
Concerns\CompilesComponents,
Concerns\CompilesConditionals,
Concerns\CompilesEchos,
+ Concerns\CompilesHelpers,
Concerns\CompilesIncludes,
Concerns\CompilesInjections,
+ Concerns\CompilesJson,
Concerns\CompilesLayouts,
Concerns\CompilesLoops,
Concerns\CompilesRawPhp,
/**
* All custom "directive" handlers.
*
- * This was implemented as a more usable "extend" in 5.1.
- *
* @var array
*/
protected $customDirectives = [];
+ /**
+ * All custom "condition" handlers.
+ *
+ * @var array
+ */
+ protected $conditions = [];
+
/**
* The file currently being compiled.
*
protected $footer = [];
/**
- * Placeholder to temporary mark the position of verbatim blocks.
- *
- * @var string
- */
- protected $verbatimPlaceholder = '@__verbatim__@';
-
- /**
- * Array to temporary store the verbatim blocks found in the template.
+ * Array to temporary store the raw blocks found in the template.
*
* @var array
*/
- protected $verbatimBlocks = [];
+ protected $rawBlocks = [];
/**
* Compile the view at the given path.
*/
public function compileString($value)
{
- $result = '';
-
if (strpos($value, '@verbatim') !== false) {
$value = $this->storeVerbatimBlocks($value);
}
$this->footer = [];
+ if (strpos($value, '@php') !== false) {
+ $value = $this->storePhpBlocks($value);
+ }
+
+ $result = '';
+
// Here we will loop through all of the tokens returned by the Zend lexer and
// parse each one into the corresponding valid PHP. We will then have this
// template as the correctly rendered PHP that can be rendered natively.
$result .= is_array($token) ? $this->parseToken($token) : $token;
}
- if (! empty($this->verbatimBlocks)) {
- $result = $this->restoreVerbatimBlocks($result);
+ if (! empty($this->rawBlocks)) {
+ $result = $this->restoreRawContent($result);
}
// If there are any footer lines that need to get added to a template we will
protected function storeVerbatimBlocks($value)
{
return preg_replace_callback('/(?<!@)@verbatim(.*?)@endverbatim/s', function ($matches) {
- $this->verbatimBlocks[] = $matches[1];
+ return $this->storeRawBlock($matches[1]);
+ }, $value);
+ }
- return $this->verbatimPlaceholder;
+ /**
+ * Store the PHP blocks and replace them with a temporary placeholder.
+ *
+ * @param string $value
+ * @return string
+ */
+ protected function storePhpBlocks($value)
+ {
+ return preg_replace_callback('/(?<!@)@php(.*?)@endphp/s', function ($matches) {
+ return $this->storeRawBlock("<?php{$matches[1]}?>");
}, $value);
}
+ /**
+ * Store a raw block and return a unique raw placeholder.
+ *
+ * @param string $value
+ * @return string
+ */
+ protected function storeRawBlock($value)
+ {
+ return $this->getRawPlaceholder(
+ array_push($this->rawBlocks, $value) - 1
+ );
+ }
+
/**
* Replace the raw placeholders with the original code stored in the raw blocks.
*
* @param string $result
* @return string
*/
- protected function restoreVerbatimBlocks($result)
+ protected function restoreRawContent($result)
{
- $result = preg_replace_callback('/'.preg_quote($this->verbatimPlaceholder).'/', function () {
- return array_shift($this->verbatimBlocks);
+ $result = preg_replace_callback('/'.$this->getRawPlaceholder('(\d+)').'/', function ($matches) {
+ return $this->rawBlocks[$matches[1]];
}, $result);
- $this->verbatimBlocks = [];
+ $this->rawBlocks = [];
return $result;
}
+ /**
+ * Get a placeholder to temporary mark the position of raw blocks.
+ *
+ * @param int|string $replace
+ * @return string
+ */
+ protected function getRawPlaceholder($replace)
+ {
+ return str_replace('#', $replace, '@__raw_block_#__@');
+ }
+
/**
* Add the stored footers onto the given content.
*
return $this->extensions;
}
+ /**
+ * Register an "if" statement directive.
+ *
+ * @param string $name
+ * @param callable $callback
+ * @return void
+ */
+ public function if($name, callable $callback)
+ {
+ $this->conditions[$name] = $callback;
+
+ $this->directive($name, function ($expression) use ($name) {
+ return $expression
+ ? "<?php if (\Illuminate\Support\Facades\Blade::check('{$name}', {$expression})): ?>"
+ : "<?php if (\Illuminate\Support\Facades\Blade::check('{$name}')): ?>";
+ });
+
+ $this->directive('else'.$name, function ($expression) use ($name) {
+ return $expression
+ ? "<?php elseif (\Illuminate\Support\Facades\Blade::check('{$name}', {$expression})): ?>"
+ : "<?php elseif (\Illuminate\Support\Facades\Blade::check('{$name}')): ?>";
+ });
+
+ $this->directive('end'.$name, function () {
+ return '<?php endif; ?>';
+ });
+ }
+
+ /**
+ * Check the result of a condition.
+ *
+ * @param string $name
+ * @param array $parameters
+ * @return bool
+ */
+ public function check($name, ...$parameters)
+ {
+ return call_user_func($this->conditions[$name], ...$parameters);
+ }
+
+ /**
+ * Register a component alias directive.
+ *
+ * @param string $path
+ * @param string $alias
+ * @return void
+ */
+ public function component($path, $alias = null)
+ {
+ $alias = $alias ?: array_last(explode('.', $path));
+
+ $this->directive($alias, function ($expression) use ($path) {
+ return $expression
+ ? "<?php \$__env->startComponent('{$path}', {$expression}); ?>"
+ : "<?php \$__env->startComponent('{$path}'); ?>";
+ });
+
+ $this->directive('end'.$alias, function ($expression) {
+ return '<?php echo $__env->renderComponent(); ?>';
+ });
+ }
+
+ /**
+ * Register an include alias directive.
+ *
+ * @param string $path
+ * @param string $alias
+ * @return void
+ */
+ public function include($path, $alias = null)
+ {
+ $alias = $alias ?: array_last(explode('.', $path));
+
+ $this->directive($alias, function ($expression) use ($path) {
+ $expression = $this->stripParentheses($expression) ?: '[]';
+
+ return "<?php echo \$__env->make('{$path}', {$expression}, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
+ });
+ }
+
/**
* Register a handler for custom directives.
*
{
$this->echoFormat = $format;
}
+
+ /**
+ * Set the "echo" format to double encode entities.
+ *
+ * @return void
+ */
+ public function withDoubleEncoding()
+ {
+ $this->setEchoFormat('e(%s, true)');
+ }
+
+ /**
+ * Set the "echo" format to not double encode entities.
+ *
+ * @return void
+ */
+ public function withoutDoubleEncoding()
+ {
+ $this->setEchoFormat('e(%s, false)');
+ }
}
trait CompilesConditionals
{
+ /**
+ * Identifier for the first case in switch statement.
+ *
+ * @var bool
+ */
+ protected $firstCaseInSwitch = true;
+
+ /**
+ * Compile the if-auth statements into valid PHP.
+ *
+ * @param string|null $guard
+ * @return string
+ */
+ protected function compileAuth($guard = null)
+ {
+ $guard = is_null($guard) ? '()' : $guard;
+
+ return "<?php if(auth()->guard{$guard}->check()): ?>";
+ }
+
+ /**
+ * Compile the else-auth statements into valid PHP.
+ *
+ * @param string|null $guard
+ * @return string
+ */
+ protected function compileElseAuth($guard = null)
+ {
+ $guard = is_null($guard) ? '()' : $guard;
+
+ return "<?php elseif(auth()->guard{$guard}->check()): ?>";
+ }
+
+ /**
+ * Compile the end-auth statements into valid PHP.
+ *
+ * @return string
+ */
+ protected function compileEndAuth()
+ {
+ return '<?php endif; ?>';
+ }
+
+ /**
+ * Compile the if-guest statements into valid PHP.
+ *
+ * @param string|null $guard
+ * @return string
+ */
+ protected function compileGuest($guard = null)
+ {
+ $guard = is_null($guard) ? '()' : $guard;
+
+ return "<?php if(auth()->guard{$guard}->guest()): ?>";
+ }
+
+ /**
+ * Compile the else-guest statements into valid PHP.
+ *
+ * @param string|null $guard
+ * @return string
+ */
+ protected function compileElseGuest($guard = null)
+ {
+ $guard = is_null($guard) ? '()' : $guard;
+
+ return "<?php elseif(auth()->guard{$guard}->guest()): ?>";
+ }
+
+ /**
+ * Compile the end-guest statements into valid PHP.
+ *
+ * @return string
+ */
+ protected function compileEndGuest()
+ {
+ return '<?php endif; ?>';
+ }
+
/**
* Compile the has-section statements into valid PHP.
*
{
return '<?php endif; ?>';
}
+
+ /**
+ * Compile the switch statements into valid PHP.
+ *
+ * @param string $expression
+ * @return string
+ */
+ protected function compileSwitch($expression)
+ {
+ $this->firstCaseInSwitch = true;
+
+ return "<?php switch{$expression}:";
+ }
+
+ /**
+ * Compile the case statements into valid PHP.
+ *
+ * @param string $expression
+ * @return string
+ */
+ protected function compileCase($expression)
+ {
+ if ($this->firstCaseInSwitch) {
+ $this->firstCaseInSwitch = false;
+
+ return "case {$expression}: ?>";
+ }
+
+ return "<?php case {$expression}: ?>";
+ }
+
+ /**
+ * Compile the default statements in switch case into valid PHP.
+ *
+ * @return string
+ */
+ protected function compileDefault()
+ {
+ return '<?php default: ?>';
+ }
+
+ /**
+ * Compile the end switch statements into valid PHP.
+ *
+ * @return string
+ */
+ protected function compileEndSwitch()
+ {
+ return '<?php endswitch; ?>';
+ }
}
*/
public function compileEchoDefaults($value)
{
- return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/s', 'isset($1) ? $1 : $2', $value);
+ return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/si', 'isset($1) ? $1 : $2', $value);
}
}
--- /dev/null
+<?php
+
+namespace Illuminate\View\Compilers\Concerns;
+
+trait CompilesHelpers
+{
+ /**
+ * Compile the CSRF statements into valid PHP.
+ *
+ * @return string
+ */
+ protected function compileCsrf()
+ {
+ return '<?php echo csrf_field(); ?>';
+ }
+
+ /**
+ * Compile the "dd" statements into valid PHP.
+ *
+ * @param string $arguments
+ * @return string
+ */
+ protected function compileDd($arguments)
+ {
+ return "<?php dd{$arguments}; ?>";
+ }
+
+ /**
+ * Compile the "dump" statements into valid PHP.
+ *
+ * @param string $arguments
+ * @return string
+ */
+ protected function compileDump($arguments)
+ {
+ return "<?php dump{$arguments}; ?>";
+ }
+
+ /**
+ * Compile the method statements into valid PHP.
+ *
+ * @param string $method
+ * @return string
+ */
+ protected function compileMethod($method)
+ {
+ return "<?php echo method_field{$method}; ?>";
+ }
+}
/**
* Compile the include-when statements into valid PHP.
*
- * @param string $expression
+ * @param string $expression
* @return string
*/
protected function compileIncludeWhen($expression)
return "<?php echo \$__env->renderWhen($expression, array_except(get_defined_vars(), array('__data', '__path'))); ?>";
}
+
+ /**
+ * Compile the include-first statements into valid PHP.
+ *
+ * @param string $expression
+ * @return string
+ */
+ protected function compileIncludeFirst($expression)
+ {
+ $expression = $this->stripParentheses($expression);
+
+ return "<?php echo \$__env->first({$expression}, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
+ }
}
--- /dev/null
+<?php
+
+namespace Illuminate\View\Compilers\Concerns;
+
+trait CompilesJson
+{
+ /**
+ * The default JSON encoding options.
+ *
+ * @var int
+ */
+ private $encodingOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT;
+
+ /**
+ * Compile the JSON statement into valid PHP.
+ *
+ * @param string $expression
+ * @return string
+ */
+ protected function compileJson($expression)
+ {
+ $parts = explode(',', $this->stripParentheses($expression));
+
+ $options = isset($parts[1]) ? trim($parts[1]) : $this->encodingOptions;
+
+ $depth = isset($parts[2]) ? trim($parts[2]) : 512;
+
+ return "<?php echo json_encode($parts[0], $options, $depth) ?>";
+ }
+}
*/
protected function compilePhp($expression)
{
- return $expression ? "<?php {$expression}; ?>" : '<?php ';
- }
+ if ($expression) {
+ return "<?php {$expression}; ?>";
+ }
- /**
- * Compile end-php statements into valid PHP.
- *
- * @return string
- */
- protected function compileEndphp()
- {
- return ' ?>';
+ return '@php';
}
/**
return '<?php $__env->startTranslation(); ?>';
} elseif ($expression[1] === '[') {
return "<?php \$__env->startTranslation{$expression}; ?>";
- } else {
- return "<?php echo app('translator')->getFromJson{$expression}; ?>";
}
+
+ return "<?php echo app('translator')->getFromJson{$expression}; ?>";
}
/**
*/
public function callComposer(ViewContract $view)
{
- $this->events->fire('composing: '.$view->name(), [$view]);
+ $this->events->dispatch('composing: '.$view->name(), [$view]);
}
/**
*/
public function callCreator(ViewContract $view)
{
- $this->events->fire('creating: '.$view->name(), [$view]);
+ $this->events->dispatch('creating: '.$view->name(), [$view]);
}
}
namespace Illuminate\View\Concerns;
use InvalidArgumentException;
+use Illuminate\Contracts\View\View;
trait ManagesLayouts
{
/**
* The parent placeholder for the request.
*
- * @var string
+ * @var mixed
*/
protected static $parentPlaceholder = [];
$this->sectionStack[] = $section;
}
} else {
- $this->extendSection($section, e($content));
+ $this->extendSection($section, $content instanceof View ? $content : e($content));
}
}
*/
public function inject($section, $content)
{
- return $this->startSection($section, $content);
+ $this->startSection($section, $content);
}
/**
*/
public function yieldContent($section, $default = '')
{
- $sectionContent = $default;
+ $sectionContent = $default instanceof View ? $default : e($default);
if (isset($this->sections[$section])) {
$sectionContent = $this->sections[$section];
*/
public function getSection($name, $default = null)
{
- return isset($this->getSections()[$name]) ? $this->getSections()[$name] : $default;
+ return $this->getSections()[$name] ?? $default;
}
/**
$this->loopsStack[] = [
'iteration' => 0,
'index' => 0,
- 'remaining' => isset($length) ? $length : null,
+ 'remaining' => $length ?? null,
'count' => $length,
'first' => true,
'last' => isset($length) ? $length == 1 : null,
+++ /dev/null
-<?php
-
-namespace Illuminate\View\Engines;
-
-interface EngineInterface
-{
- /**
- * Get the evaluated contents of the view.
- *
- * @param string $path
- * @param array $data
- * @return string
- */
- public function get($path, array $data = []);
-}
}
/**
- * Resolver an engine instance by name.
+ * Resolve an engine instance by name.
*
* @param string $engine
- * @return \Illuminate\View\Engines\EngineInterface
+ * @return \Illuminate\Contracts\View\Engine
* @throws \InvalidArgumentException
*/
public function resolve($engine)
return $this->resolved[$engine] = call_user_func($this->resolvers[$engine]);
}
- throw new InvalidArgumentException("Engine $engine not found.");
+ throw new InvalidArgumentException("Engine [{$engine}] not found.");
}
}
namespace Illuminate\View\Engines;
-class FileEngine implements EngineInterface
+use Illuminate\Contracts\View\Engine;
+
+class FileEngine implements Engine
{
/**
* Get the evaluated contents of the view.
use Exception;
use Throwable;
+use Illuminate\Contracts\View\Engine;
use Symfony\Component\Debug\Exception\FatalThrowableError;
-class PhpEngine implements EngineInterface
+class PhpEngine implements Engine
{
/**
* Get the evaluated contents of the view.
});
}
+ /**
+ * Get the first view that actually exists from the given list.
+ *
+ * @param array $views
+ * @param array $data
+ * @param array $mergeData
+ * @return \Illuminate\Contracts\View\View
+ */
+ public function first(array $views, $data = [], $mergeData = [])
+ {
+ $view = collect($views)->first(function ($view) {
+ return $this->exists($view);
+ });
+
+ if (! $view) {
+ throw new InvalidArgumentException('None of the views in the given array exist.');
+ }
+
+ return $this->make($view, $data, $mergeData);
+ }
+
/**
* Get the rendered content of the view based on a given condition.
*
* Get the appropriate view engine for the given path.
*
* @param string $path
- * @return \Illuminate\View\Engines\EngineInterface
+ * @return \Illuminate\Contracts\View\Engine
*
* @throws \InvalidArgumentException
*/
public function getEngineFromPath($path)
{
if (! $extension = $this->getExtension($path)) {
- throw new InvalidArgumentException("Unrecognized extension in file: $path");
+ throw new InvalidArgumentException("Unrecognized extension in file: {$path}");
}
$engine = $this->extensions[$extension];
$segments = explode(static::HINT_PATH_DELIMITER, $name);
if (count($segments) != 2) {
- throw new InvalidArgumentException("View [$name] has an invalid name.");
+ throw new InvalidArgumentException("View [{$name}] has an invalid name.");
}
if (! isset($this->hints[$segments[0]])) {
}
}
- throw new InvalidArgumentException("View [$name] not found.");
+ throw new InvalidArgumentException("View [{$name}] not found.");
}
/**
use BadMethodCallException;
use Illuminate\Support\Str;
use Illuminate\Support\MessageBag;
+use Illuminate\Contracts\View\Engine;
+use Illuminate\Support\Traits\Macroable;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Renderable;
-use Illuminate\View\Engines\EngineInterface;
use Illuminate\Contracts\Support\MessageProvider;
use Illuminate\Contracts\View\View as ViewContract;
class View implements ArrayAccess, ViewContract
{
+ use Macroable {
+ __call as macroCall;
+ }
+
/**
* The view factory instance.
*
/**
* The engine implementation.
*
- * @var \Illuminate\View\Engines\EngineInterface
+ * @var \Illuminate\Contracts\View\Engine
*/
protected $engine;
* Create a new view instance.
*
* @param \Illuminate\View\Factory $factory
- * @param \Illuminate\View\Engines\EngineInterface $engine
+ * @param \Illuminate\Contracts\View\Engine $engine
* @param string $view
* @param string $path
* @param mixed $data
* @return void
*/
- public function __construct(Factory $factory, EngineInterface $engine, $view, $path, $data = [])
+ public function __construct(Factory $factory, Engine $engine, $view, $path, $data = [])
{
$this->view = $view;
$this->path = $path;
/**
* Get the sections of the rendered view.
*
- * @return array
+ * @return string
*/
public function renderSections()
{
/**
* Get the view's rendering engine.
*
- * @return \Illuminate\View\Engines\EngineInterface
+ * @return \Illuminate\Contracts\View\Engine
*/
public function getEngine()
{
*/
public function __call($method, $parameters)
{
+ if (static::hasMacro($method)) {
+ return $this->macroCall($method, $parameters);
+ }
+
if (! Str::startsWith($method, 'with')) {
- throw new BadMethodCallException("Method [$method] does not exist on view.");
+ throw new BadMethodCallException(sprintf(
+ 'Method %s::%s does not exist.', static::class, $method
+ ));
}
- return $this->with(Str::snake(substr($method, 4)), $parameters[0]);
+ return $this->with(Str::camel(substr($method, 4)), $parameters[0]);
}
/**
$finder = $app['view.finder'];
- $env = new Factory($resolver, $finder, $app['events']);
+ $factory = $this->createFactory($resolver, $finder, $app['events']);
// We will also set the container instance on this view environment since the
// view composers may be classes registered in the container, which allows
// for great testable, flexible composers for the application developer.
- $env->setContainer($app);
+ $factory->setContainer($app);
- $env->share('app', $app);
+ $factory->share('app', $app);
- return $env;
+ return $factory;
});
}
+ /**
+ * Create a new Factory Instance.
+ *
+ * @param \Illuminate\View\Engines\EngineResolver $resolver
+ * @param \Illuminate\View\ViewFinderInterface $finder
+ * @param \Illuminate\Contracts\Events\Dispatcher $events
+ * @return \Illuminate\View\Factory
+ */
+ protected function createFactory($resolver, $finder, $events)
+ {
+ return new Factory($resolver, $finder, $events);
+ }
+
/**
* Register the view finder implementation.
*
}
],
"require": {
- "php": ">=5.6.4",
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/events": "5.4.*",
- "illuminate/filesystem": "5.4.*",
- "illuminate/support": "5.4.*",
- "symfony/debug": "~3.2"
+ "php": "^7.1.3",
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/events": "5.6.*",
+ "illuminate/filesystem": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "symfony/debug": "~4.0"
},
"autoload": {
"psr-4": {
},
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"config": {
$icon_path_rel = RelPath::getRelativePath($icon_path_abs, get_svg_path());
// 6. Final icon path without extension expected
- $icon_imgpath_noext = pathinfo($icon_path_rel, PATHINFO_FILENAME);
+ $icon_imgpath_noext = substr($icon_path_rel, 0, strrpos($icon_path_rel, '.'));
return $icon_imgpath_noext;
}
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
-$rules = [
+$rules = array(
'@PSR2' => true,
- 'array_syntax' => [
+ 'array_syntax' => array(
'syntax' => 'long',
- ],
- 'binary_operator_spaces' => [
+ ),
+ 'binary_operator_spaces' => array(
'align_double_arrow' => false,
'align_equals' => false,
- ],
+ ),
'blank_line_before_return' => true,
'cast_spaces' => true,
- 'concat_space' => [
+ 'concat_space' => array(
'spacing' => 'none',
- ],
+ ),
'ereg_to_preg' => true,
'method_separation' => true,
'no_blank_lines_after_phpdoc' => true,
'phpdoc_indent' => true,
'phpdoc_inline_tag' => true,
'phpdoc_no_access' => true,
- 'phpdoc_no_alias_tag' => [
+ 'phpdoc_no_alias_tag' => array(
'type' => 'var',
- ],
+ ),
'phpdoc_no_package' => true,
'phpdoc_order' => true,
'phpdoc_scalar' => true,
'trailing_comma_in_multiline_array' => true,
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
-];
+ 'line_ending' => true,
+ 'blank_line_after_namespace' => true,
+ 'no_unused_imports' => true,
+);
return Config::create()->setRules($rules)
->setFinder(Finder::create()->in(__DIR__))
->setUsingCache(true)
- ->setRiskyAllowed(true);
\ No newline at end of file
+ ->setRiskyAllowed(true);
--- /dev/null
+<?php
+
+chdir(__DIR__);
+$currentBranch = 'master';
+if (preg_match('/On branch ([^\n]+)\n/', shell_exec('git status'), $match)) {
+ $currentBranch = $match[1];
+}
+shell_exec('git fetch --all --tags --prune');
+$remotes = explode("\n", trim(shell_exec('git remote')));
+$tagsCommand = count($remotes)
+ ? 'git ls-remote --tags '.(in_array('upstream', $remotes) ? 'upstream' : (in_array('origin', $remotes) ? 'origin' : $remotes[0]))
+ : 'git tag';
+$tags = array_map(function ($ref) {
+ $ref = explode('refs/tags/', $ref);
+
+ return isset($ref[1]) ? $ref[1] : $ref[0];
+}, array_filter(explode("\n", trim(shell_exec($tagsCommand))), function ($ref) {
+ return substr($ref, -3) !== '^{}';
+}));
+usort($tags, 'version_compare');
+
+$tag = isset($argv[1]) && !in_array($argv[1], array('last', 'latest')) ? $argv[1] : end($tags);
+
+if (strtolower($tag) !== 'all') {
+ if (!in_array($tag, $tags)) {
+ echo "Tag must be one of remote tags available:\n";
+ foreach ($tags as $_tag) {
+ echo " - $_tag\n";
+ }
+ echo "\"$tag\" does not match.\n";
+
+ exit(1);
+ }
+
+ $tags = array($tag);
+}
+
+foreach ($tags as $tag) {
+ $archive = "Carbon-$tag.zip";
+ if (isset($argv[2]) && $argv[2] === 'missing' && file_exists($archive)) {
+ continue;
+ }
+
+ $branch = "build-$tag";
+ shell_exec('git stash');
+ shell_exec("git branch -d $branch");
+ shell_exec("git checkout tags/$tag -b $branch");
+ shell_exec('composer config platform.php 5.3.9');
+ shell_exec('composer update --no-interaction --no-dev --optimize-autoloader');
+ $zip = new ZipArchive();
+
+ $zip->open($archive, ZipArchive::CREATE | ZipArchive::OVERWRITE);
+
+ foreach (array('src', 'vendor', 'Carbon') as $directory) {
+ if (is_dir($directory)) {
+ $directory = realpath($directory);
+ $base = dirname($directory);
+
+ $files = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($directory),
+ RecursiveIteratorIterator::LEAVES_ONLY
+ );
+
+ foreach ($files as $name => $file) {
+ if (!$file->isDir()) {
+ $filePath = $file->getRealPath();
+
+ $zip->addFile($filePath, substr($filePath, strlen($base) + 1));
+ }
+ }
+ }
+ }
+
+ $autoload = 'autoload.php';
+ file_put_contents($autoload, "<?php\n\n/**\n * @version $tag\n */\n\nrequire __DIR__.'/vendor/autoload.php';\n");
+ $zip->addFile($autoload, $autoload);
+ $zip->close();
+ unlink($autoload);
+
+ shell_exec('git checkout .');
+ shell_exec("git checkout $currentBranch");
+ shell_exec("git branch -d $branch");
+ shell_exec('git stash pop');
+ shell_exec('composer update --no-interaction');
+}
+
+exit(0);
}
],
"require": {
- "php": ">=5.3.0",
- "symfony/translation": "~2.6 || ~3.0"
+ "php": ">=5.3.9",
+ "symfony/translation": "~2.6 || ~3.0 || ~4.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2",
- "phpunit/phpunit": "~4.0 || ~5.0"
+ "phpunit/phpunit": "^4.8.35 || ^5.7"
},
"autoload": {
"psr-4": {
- "Carbon\\": "src/Carbon/"
+ "": "src/"
}
},
"autoload-dev": {
"Tests\\": "tests/"
}
},
- "extra": {
- "branch-alias": {
- "dev-master": "1.23-dev"
- }
- },
"config": {
"sort-packages": true
},
"scripts": {
- "test": "./vendor/bin/phpunit; ./vendor/bin/php-cs-fixer fix -v --diff --dry-run;",
- "phpunit": "./vendor/bin/phpunit;",
- "phpcs": "./vendor/bin/php-cs-fixer fix -v --diff --dry-run;"
+ "test": [
+ "@phpunit",
+ "@phpcs"
+ ],
+ "phpunit": "phpunit --verbose --coverage-clover=coverage.xml",
+ "phpcs": "php-cs-fixer fix -v --diff --dry-run",
+ "phpstan": "phpstan analyse --configuration phpstan.neon --level 3 src tests"
}
}
[](https://styleci.io/repos/5724990)
[](https://codecov.io/github/briannesbitt/Carbon?branch=master)
[](https://php-eye.com/package/nesbot/carbon)
+[](https://github.com/phpstan/phpstan)
A simple PHP API extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com)
printf("Right now in Vancouver is %s", Carbon::now('America/Vancouver')); //implicit __toString()
$tomorrow = Carbon::now()->addDay();
$lastWeek = Carbon::now()->subWeek();
-$nextSummerOlympics = Carbon::createFromDate(2012)->addYears(4);
+$nextSummerOlympics = Carbon::createFromDate(2016)->addYears(4);
$officialDate = Carbon::now()->toRfc2822String();
$noonTodayLondonTime = Carbon::createFromTime(12, 0, 0, 'Europe/London');
-$worldWillEnd = Carbon::createFromDate(2012, 12, 21, 'GMT');
+$internetWillBlowUpOn = Carbon::create(2038, 01, 19, 3, 14, 7, 'GMT');
-// Don't really want to die so mock now
+// Don't really want this to happen so mock now
Carbon::setTestNow(Carbon::createFromDate(2000, 1, 1));
// comparisons are always done in UTC
-if (Carbon::now()->gte($worldWillEnd)) {
+if (Carbon::now()->gte($internetWillBlowUpOn)) {
die();
}
```
<a name="install-nocomposer"/>
+
### Without Composer
Why are you not using [composer](http://getcomposer.org/)? Download [Carbon.php](https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Carbon.php) from the repo and save the file into your project path somewhere.
## Docs
-[http://carbon.nesbot.com/docs](http://carbon.nesbot.com/docs)
\ No newline at end of file
+[http://carbon.nesbot.com/docs](http://carbon.nesbot.com/docs)
use Closure;
use DatePeriod;
use DateTime;
+use DateTimeInterface;
use DateTimeZone;
use InvalidArgumentException;
-use Symfony\Component\Translation\Loader\ArrayLoader;
-use Symfony\Component\Translation\Translator;
+use JsonSerializable;
use Symfony\Component\Translation\TranslatorInterface;
/**
* @property \DateTimeZone $tz alias of timezone
* @property-read int $micro
* @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
+ * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
* @property-read int $dayOfYear 0 through 365
* @property-read int $weekOfMonth 1 through 5
+ * @property-read int $weekNumberInMonth 1 through 5
* @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
* @property-read int $daysInMonth number of days in the given month
* @property-read int $age does a diffInYears() with default parameters
* @property-read string $timezoneName
* @property-read string $tzName
*/
-class Carbon extends DateTime
+class Carbon extends DateTime implements JsonSerializable
{
+ const NO_ZERO_DIFF = 01;
+ const JUST_NOW = 02;
+ const ONE_DAY_WORDS = 04;
+ const TWO_DAY_WORDS = 010;
+
/**
* The day constants.
*/
self::SATURDAY => 'Saturday',
);
- /**
- * Terms used to detect if a time passed is a relative date.
- *
- * This is here for testing purposes.
- *
- * @var array
- */
- protected static $relativeKeywords = array(
- '+',
- '-',
- 'ago',
- 'first',
- 'last',
- 'next',
- 'this',
- 'today',
- 'tomorrow',
- 'yesterday',
- );
-
/**
* Number of X in Y.
*/
const MINUTES_PER_HOUR = 60;
const SECONDS_PER_MINUTE = 60;
+ /**
+ * RFC7231 DateTime format.
+ *
+ * @var string
+ */
+ const RFC7231_FORMAT = 'D, d M Y H:i:s \G\M\T';
+
/**
* Default format to use for __toString method when type juggling occurs.
*
*/
const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s';
+ /**
+ * Format for converting mocked time, includes microseconds.
+ *
+ * @var string
+ */
+ const MOCK_DATETIME_FORMAT = 'Y-m-d H:i:s.u';
+
+ /**
+ * Customizable PHP_INT_SIZE override.
+ *
+ * @var int
+ */
+ public static $PHPIntSize = PHP_INT_SIZE;
+
/**
* Format to use for __toString method when type juggling occurs.
*
self::SUNDAY,
);
+ /**
+ * Midday/noon hour.
+ *
+ * @var int
+ */
+ protected static $midDayAt = 12;
+
+ /**
+ * Format regex patterns.
+ *
+ * @var array
+ */
+ protected static $regexFormats = array(
+ 'd' => '(3[01]|[12][0-9]|0[1-9])',
+ 'D' => '([a-zA-Z]{3})',
+ 'j' => '([123][0-9]|[1-9])',
+ 'l' => '([a-zA-Z]{2,})',
+ 'N' => '([1-7])',
+ 'S' => '([a-zA-Z]{2})',
+ 'w' => '([0-6])',
+ 'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])',
+ 'W' => '(5[012]|[1-4][0-9]|[1-9])',
+ 'F' => '([a-zA-Z]{2,})',
+ 'm' => '(1[012]|0[1-9])',
+ 'M' => '([a-zA-Z]{3})',
+ 'n' => '(1[012]|[1-9])',
+ 't' => '(2[89]|3[01])',
+ 'L' => '(0|1)',
+ 'o' => '([1-9][0-9]{0,4})',
+ 'Y' => '([1-9][0-9]{0,4})',
+ 'y' => '([0-9]{2})',
+ 'a' => '(am|pm)',
+ 'A' => '(AM|PM)',
+ 'B' => '([0-9]{3})',
+ 'g' => '(1[012]|[1-9])',
+ 'G' => '(2[0-3]|1?[0-9])',
+ 'h' => '(1[012]|0[1-9])',
+ 'H' => '(2[0-3]|[01][0-9])',
+ 'i' => '([0-5][0-9])',
+ 's' => '([0-5][0-9])',
+ 'u' => '([0-9]{1,6})',
+ 'v' => '([0-9]{1,3})',
+ 'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\/[a-zA-Z]*)',
+ 'I' => '(0|1)',
+ 'O' => '([\+\-](1[012]|0[0-9])[0134][05])',
+ 'P' => '([\+\-](1[012]|0[0-9]):[0134][05])',
+ 'T' => '([a-zA-Z]{1,5})',
+ 'Z' => '(-?[1-5]?[0-9]{1,4})',
+ 'U' => '([0-9]*)',
+
+ // The formats below are combinations of the above formats.
+ 'c' => '(([1-9][0-9]{0,4})\-(1[012]|0[1-9])\-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[\+\-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP
+ 'r' => '(([a-zA-Z]{3}), ([123][0-9]|[1-9]) ([a-zA-Z]{3}) ([1-9][0-9]{0,4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [\+\-](1[012]|0[0-9])([0134][05]))', // D, j M Y H:i:s O
+ );
+
/**
* A test Carbon instance to be returned when now instances are created.
*
*/
protected static $lastErrors;
+ /**
+ * The custom Carbon JSON serializer.
+ *
+ * @var callable|null
+ */
+ protected static $serializer;
+
+ /**
+ * The registered string macros.
+ *
+ * @var array
+ */
+ protected static $localMacros = array();
+
/**
* Will UTF8 encoding be used to print localized date/time ?
*
*/
protected static $utf8 = false;
- /*
+ /**
+ * Add microseconds to now on PHP < 7.1 and 7.1.3. true by default.
+ *
+ * @var bool
+ */
+ protected static $microsecondsFallback = true;
+
+ /**
* Indicates if months should be calculated with overflow.
*
* @var bool
*/
protected static $monthsOverflow = true;
+ /**
+ * Indicates if years should be calculated with overflow.
+ *
+ * @var bool
+ */
+ protected static $yearsOverflow = true;
+
+ /**
+ * Options for diffForHumans().
+ *
+ * @var int
+ */
+ protected static $humanDiffOptions = self::NO_ZERO_DIFF;
+
+ /**
+ * @param int $humanDiffOptions
+ */
+ public static function setHumanDiffOptions($humanDiffOptions)
+ {
+ static::$humanDiffOptions = $humanDiffOptions;
+ }
+
+ /**
+ * @param int $humanDiffOption
+ */
+ public static function enableHumanDiffOption($humanDiffOption)
+ {
+ static::$humanDiffOptions = static::getHumanDiffOptions() | $humanDiffOption;
+ }
+
+ /**
+ * @param int $humanDiffOption
+ */
+ public static function disableHumanDiffOption($humanDiffOption)
+ {
+ static::$humanDiffOptions = static::getHumanDiffOptions() & ~$humanDiffOption;
+ }
+
+ /**
+ * @return int
+ */
+ public static function getHumanDiffOptions()
+ {
+ return static::$humanDiffOptions;
+ }
+
+ /**
+ * Add microseconds to now on PHP < 7.1 and 7.1.3 if set to true,
+ * let microseconds to 0 on those PHP versions if false.
+ *
+ * @param bool $microsecondsFallback
+ */
+ public static function useMicrosecondsFallback($microsecondsFallback = true)
+ {
+ static::$microsecondsFallback = $microsecondsFallback;
+ }
+
+ /**
+ * Return true if microseconds fallback on PHP < 7.1 and 7.1.3 is
+ * enabled. false if disabled.
+ *
+ * @return bool
+ */
+ public static function isMicrosecondsFallbackEnabled()
+ {
+ return static::$microsecondsFallback;
+ }
+
/**
* Indicates if months should be calculated with overflow.
*
return static::$monthsOverflow;
}
+ /**
+ * Indicates if years should be calculated with overflow.
+ *
+ * @param bool $yearsOverflow
+ *
+ * @return void
+ */
+ public static function useYearsOverflow($yearsOverflow = true)
+ {
+ static::$yearsOverflow = $yearsOverflow;
+ }
+
+ /**
+ * Reset the month overflow behavior.
+ *
+ * @return void
+ */
+ public static function resetYearsOverflow()
+ {
+ static::$yearsOverflow = true;
+ }
+
+ /**
+ * Get the month overflow behavior.
+ *
+ * @return bool
+ */
+ public static function shouldOverflowYears()
+ {
+ return static::$yearsOverflow;
+ }
+
/**
* Creates a DateTimeZone from a string, DateTimeZone or integer offset.
*
{
// If the class has a test now set and we are trying to create a now()
// instance then override as required
- if (static::hasTestNow() && (empty($time) || $time === 'now' || static::hasRelativeKeywords($time))) {
+ $isNow = empty($time) || $time === 'now';
+ if (static::hasTestNow() && ($isNow || static::hasRelativeKeywords($time))) {
$testInstance = clone static::getTestNow();
- if (static::hasRelativeKeywords($time)) {
- $testInstance->modify($time);
- }
//shift the time according to the given time zone
if ($tz !== null && $tz !== static::getTestNow()->getTimezone()) {
$tz = $testInstance->getTimezone();
}
- $time = $testInstance->toDateTimeString();
+ if (static::hasRelativeKeywords($time)) {
+ $testInstance->modify($time);
+ }
+
+ $time = $testInstance->format(static::MOCK_DATETIME_FORMAT);
}
- parent::__construct($time, static::safeCreateDateTimeZone($tz));
+ $timezone = static::safeCreateDateTimeZone($tz);
+ // @codeCoverageIgnoreStart
+ if ($isNow && !isset($testInstance) && static::isMicrosecondsFallbackEnabled() && (
+ version_compare(PHP_VERSION, '7.1.0-dev', '<')
+ ||
+ version_compare(PHP_VERSION, '7.1.3-dev', '>=') && version_compare(PHP_VERSION, '7.1.4-dev', '<')
+ )
+ ) {
+ // Get microseconds from microtime() if "now" asked and PHP < 7.1 and PHP 7.1.3 if fallback enabled.
+ list($microTime, $timeStamp) = explode(' ', microtime());
+ $dateTime = new DateTime('now', $timezone);
+ $dateTime->setTimestamp($timeStamp); // Use the timestamp returned by microtime as now can happen in the next second
+ $time = $dateTime->format(static::DEFAULT_TO_STRING_FORMAT).substr($microTime, 1, 7);
+ }
+ // @codeCoverageIgnoreEnd
+
+ // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
+ if (strpos((string) .1, '.') === false) {
+ $locale = setlocale(LC_NUMERIC, '0');
+ setlocale(LC_NUMERIC, 'C');
+ }
+ parent::__construct($time, $timezone);
+ if (isset($locale)) {
+ setlocale(LC_NUMERIC, $locale);
+ }
+ static::setLastErrors(parent::getLastErrors());
}
/**
* Create a Carbon instance from a DateTime one.
*
- * @param \DateTime $dt
+ * @param \DateTime|\DateTimeInterface $date
*
* @return static
*/
- public static function instance(DateTime $dt)
+ public static function instance($date)
{
- if ($dt instanceof static) {
- return clone $dt;
+ if ($date instanceof static) {
+ return clone $date;
}
- return new static($dt->format('Y-m-d H:i:s.u'), $dt->getTimezone());
+ static::expectDateTime($date);
+
+ return new static($date->format('Y-m-d H:i:s.u'), $date->getTimezone());
}
/**
*/
public static function today($tz = null)
{
- return static::now($tz)->startOfDay();
+ return static::parse('today', $tz);
}
/**
*/
public static function tomorrow($tz = null)
{
- return static::today($tz)->addDay();
+ return static::parse('tomorrow', $tz);
}
/**
*/
public static function yesterday($tz = null)
{
- return static::today($tz)->subDay();
+ return static::parse('yesterday', $tz);
}
/**
*/
public static function maxValue()
{
- if (PHP_INT_SIZE === 4) {
- // 32 bit (and additionally Windows 64 bit)
- return static::createFromTimestamp(PHP_INT_MAX);
+ if (self::$PHPIntSize === 4) {
+ // 32 bit
+ return static::createFromTimestamp(PHP_INT_MAX); // @codeCoverageIgnore
}
// 64 bit
*/
public static function minValue()
{
- if (PHP_INT_SIZE === 4) {
- // 32 bit (and additionally Windows 64 bit)
- return static::createFromTimestamp(~PHP_INT_MAX);
+ if (self::$PHPIntSize === 4) {
+ // 32 bit
+ return static::createFromTimestamp(~PHP_INT_MAX); // @codeCoverageIgnore
}
// 64 bit
* @param int|null $second
* @param \DateTimeZone|string|null $tz
*
+ * @throws \InvalidArgumentException
+ *
* @return static
*/
public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
{
- $now = static::hasTestNow() ? static::getTestNow()->getTimestamp() : time();
+ $now = static::hasTestNow() ? static::getTestNow() : static::now($tz);
$defaults = array_combine(array(
'year',
'hour',
'minute',
'second',
- ), explode('-', date('Y-n-j-G-i-s', $now)));
+ ), explode('-', $now->format('Y-n-j-G-i-s')));
$year = $year === null ? $defaults['year'] : $year;
$month = $month === null ? $defaults['month'] : $month;
* @param int|null $second
* @param \DateTimeZone|string|null $tz
*
- * @throws \Carbon\Exceptions\InvalidDateException
+ * @throws \Carbon\Exceptions\InvalidDateException|\InvalidArgumentException
*
* @return static
*/
}
}
- $instance = static::create($year, $month, 1, $hour, $minute, $second, $tz);
+ $instance = static::create($year, $month, $day, $hour, $minute, $second, $tz);
- if ($day !== null && $day > $instance->daysInMonth) {
- throw new InvalidDateException('day', $day);
+ foreach (array_reverse($fields) as $field => $range) {
+ if ($$field !== null && (!is_int($$field) || $$field !== $instance->$field)) {
+ throw new InvalidDateException($field, $$field);
+ }
}
- return $instance->day($day);
+ return $instance;
}
/**
* @param int|null $day
* @param \DateTimeZone|string|null $tz
*
+ * @throws \InvalidArgumentException
+ *
* @return static
*/
public static function createFromDate($year = null, $month = null, $day = null, $tz = null)
return static::create($year, $month, $day, null, null, null, $tz);
}
+ /**
+ * Create a Carbon instance from just a date. The time portion is set to midnight.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null)
+ {
+ return static::create($year, $month, $day, 0, 0, 0, $tz);
+ }
+
/**
* Create a Carbon instance from just a time. The date portion is set to today.
*
* @param int|null $second
* @param \DateTimeZone|string|null $tz
*
+ * @throws \InvalidArgumentException
+ *
* @return static
*/
public static function createFromTime($hour = null, $minute = null, $second = null, $tz = null)
}
/**
- * Create a Carbon instance from a specific format.
+ * Create a Carbon instance from a time string. The date portion is set to today.
*
- * @param string $format
* @param string $time
* @param \DateTimeZone|string|null $tz
*
*
* @return static
*/
+ public static function createFromTimeString($time, $tz = null)
+ {
+ return static::today($tz)->setTimeFromTimeString($time);
+ }
+
+ /**
+ * Create a Carbon instance from a specific format.
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return static
+ */
public static function createFromFormat($format, $time, $tz = null)
{
if ($tz !== null) {
- $dt = parent::createFromFormat($format, $time, static::safeCreateDateTimeZone($tz));
+ $date = parent::createFromFormat($format, $time, static::safeCreateDateTimeZone($tz));
} else {
- $dt = parent::createFromFormat($format, $time);
+ $date = parent::createFromFormat($format, $time);
}
- static::setLastErrors($lastErrors = parent::getLastErrors());
+ $lastErrors = parent::getLastErrors();
+
+ if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
+ $instance = static::instance($date);
+ $instance::setLastErrors($lastErrors);
- if ($dt instanceof DateTime) {
- return static::instance($dt);
+ return $instance;
}
throw new InvalidArgumentException(implode(PHP_EOL, $lastErrors['errors']));
*/
public static function createFromTimestamp($timestamp, $tz = null)
{
- return static::now($tz)->setTimestamp($timestamp);
+ return static::today($tz)->setTimestamp($timestamp);
+ }
+
+ /**
+ * Create a Carbon instance from a timestamp in milliseconds.
+ *
+ * @param int $timestamp
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createFromTimestampMs($timestamp, $tz = null)
+ {
+ return static::createFromFormat('U.u', sprintf('%F', $timestamp / 1000))
+ ->setTimezone($tz);
}
/**
return clone $this;
}
+ /**
+ * Returns a present instance in the same timezone.
+ *
+ * @return static
+ */
+ public function nowWithSameTz()
+ {
+ return static::now($this->getTimezone());
+ }
+
+ /**
+ * Throws an exception if the given object is not a DateTime and does not implement DateTimeInterface.
+ *
+ * @param mixed $date
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected static function expectDateTime($date)
+ {
+ if (!$date instanceof DateTime && !$date instanceof DateTimeInterface) {
+ throw new InvalidArgumentException(
+ 'Expected null, string, DateTime or DateTimeInterface, '.
+ (is_object($date) ? get_class($date) : gettype($date)).' given'
+ );
+ }
+ }
+
+ /**
+ * Return the Carbon instance passed through, a now instance in the same timezone
+ * if null given or parse the input if string given.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ protected function resolveCarbon($date = null)
+ {
+ if (!$date) {
+ return $this->nowWithSameTz();
+ }
+
+ if (is_string($date)) {
+ return static::parse($date, $this->getTimezone());
+ }
+
+ static::expectDateTime($date);
+
+ return $date instanceof self ? $date : static::instance($date);
+ }
+
///////////////////////////////////////////////////////////////////
///////////////////////// GETTERS AND SETTERS /////////////////////
///////////////////////////////////////////////////////////////////
*/
public function __get($name)
{
+ static $formats = array(
+ 'year' => 'Y',
+ 'yearIso' => 'o',
+ 'month' => 'n',
+ 'day' => 'j',
+ 'hour' => 'G',
+ 'minute' => 'i',
+ 'second' => 's',
+ 'micro' => 'u',
+ 'dayOfWeek' => 'w',
+ 'dayOfWeekIso' => 'N',
+ 'dayOfYear' => 'z',
+ 'weekOfYear' => 'W',
+ 'daysInMonth' => 't',
+ 'timestamp' => 'U',
+ );
+
switch (true) {
- case array_key_exists($name, $formats = array(
- 'year' => 'Y',
- 'yearIso' => 'o',
- 'month' => 'n',
- 'day' => 'j',
- 'hour' => 'G',
- 'minute' => 'i',
- 'second' => 's',
- 'micro' => 'u',
- 'dayOfWeek' => 'w',
- 'dayOfYear' => 'z',
- 'weekOfYear' => 'W',
- 'daysInMonth' => 't',
- 'timestamp' => 'U',
- )):
+ case isset($formats[$name]):
return (int) $this->format($formats[$name]);
case $name === 'weekOfMonth':
return (int) ceil($this->day / static::DAYS_PER_WEEK);
+ case $name === 'weekNumberInMonth':
+ return (int) ceil(($this->day + $this->copy()->startOfMonth()->dayOfWeek - 1) / static::DAYS_PER_WEEK);
+
case $name === 'age':
return $this->diffInYears();
* @param string|int|\DateTimeZone $value
*
* @throws \InvalidArgumentException
+ *
+ * @return void
*/
public function __set($name, $value)
{
*/
public function setTimeFromTimeString($time)
{
- $time = explode(':', $time);
-
- $hour = $time[0];
- $minute = isset($time[1]) ? $time[1] : 0;
- $second = isset($time[2]) ? $time[2] : 0;
+ if (strpos($time, ':') === false) {
+ $time .= ':0';
+ }
- return $this->setTime($hour, $minute, $second);
+ return $this->modify($time);
}
/**
*/
public function setTimezone($value)
{
- return parent::setTimezone(static::safeCreateDateTimeZone($value));
+ parent::setTimezone(static::safeCreateDateTimeZone($value));
+ // https://bugs.php.net/bug.php?id=72338
+ // just workaround on this bug
+ $this->getTimestamp();
+
+ return $this;
+ }
+
+ /**
+ * Set the year, month, and date for this instance to that of the passed instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface $date
+ *
+ * @return static
+ */
+ public function setDateFrom($date)
+ {
+ $date = static::instance($date);
+
+ $this->setDate($date->year, $date->month, $date->day);
+
+ return $this;
+ }
+
+ /**
+ * Set the hour, day, and time for this instance to that of the passed instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface $date
+ *
+ * @return static
+ */
+ public function setTimeFrom($date)
+ {
+ $date = static::instance($date);
+
+ $this->setTime($date->hour, $date->minute, $date->second);
+
+ return $this;
+ }
+
+ /**
+ * Get the days of the week
+ *
+ * @return array
+ */
+ public static function getDays()
+ {
+ return static::$days;
}
///////////////////////////////////////////////////////////////////
/**
* Set the first day of week
*
- * @param int
+ * @param int $day week start day
+ *
+ * @return void
*/
public static function setWeekStartsAt($day)
{
/**
* Set the last day of week
*
- * @param int
+ * @param int $day
+ *
+ * @return void
*/
public static function setWeekEndsAt($day)
{
/**
* Set weekend days
*
- * @param array
+ * @param array $days
+ *
+ * @return void
*/
public static function setWeekendDays($days)
{
static::$weekendDays = $days;
}
- ///////////////////////////////////////////////////////////////////
- ///////////////////////// TESTING AIDS ////////////////////////////
- ///////////////////////////////////////////////////////////////////
-
/**
- * Set a Carbon instance (real or mock) to be returned when a "now"
- * instance is created. The provided instance will be returned
- * specifically under the following conditions:
- * - A call to the static now() method, ex. Carbon::now()
+ * get midday/noon hour
+ *
+ * @return int
+ */
+ public static function getMidDayAt()
+ {
+ return static::$midDayAt;
+ }
+
+ /**
+ * Set midday/noon hour
+ *
+ * @param int $hour midday hour
+ *
+ * @return void
+ */
+ public static function setMidDayAt($hour)
+ {
+ static::$midDayAt = $hour;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////// TESTING AIDS ////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Set a Carbon instance (real or mock) to be returned when a "now"
+ * instance is created. The provided instance will be returned
+ * specifically under the following conditions:
+ * - A call to the static now() method, ex. Carbon::now()
* - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
* - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
* - When a string containing the desired time is passed to Carbon::parse().
* To clear the test instance call this method using the default
* parameter of null.
*
+ * @param \Carbon\Carbon|null $testNow real or mock Carbon instance
* @param \Carbon\Carbon|string|null $testNow
*/
public static function setTestNow($testNow = null)
}
/**
- * Determine if there is a relative keyword in the time string, this is to
- * create dates relative to now for test instances. e.g.: next tuesday
+ * Determine if a time string will produce a relative date.
*
* @param string $time
*
- * @return bool true if there is a keyword, otherwise false
+ * @return bool true if time match a relative date, false if absolute or invalid time string
*/
public static function hasRelativeKeywords($time)
{
- // skip common format with a '-' in it
- if (preg_match('/\d{4}-\d{1,2}-\d{1,2}/', $time) !== 1) {
- foreach (static::$relativeKeywords as $keyword) {
- if (stripos($time, $keyword) !== false) {
- return true;
- }
- }
+ if (strtotime($time) === false) {
+ return false;
}
- return false;
+ $date1 = new DateTime('2000-01-01T00:00:00Z');
+ $date1->modify($time);
+ $date2 = new DateTime('2001-12-25T00:00:00Z');
+ $date2->modify($time);
+
+ return $date1 != $date2;
}
///////////////////////////////////////////////////////////////////
protected static function translator()
{
if (static::$translator === null) {
- static::$translator = new Translator('en');
- static::$translator->addLoader('array', new ArrayLoader());
- static::setLocale('en');
+ static::$translator = Translator::get();
}
return static::$translator;
* Set the translator instance to use
*
* @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return void
*/
public static function setTranslator(TranslatorInterface $translator)
{
/**
* Set the current translator locale and indicate if the source locale file exists
*
- * @param string $locale
+ * @param string $locale locale ex. en
*
* @return bool
*/
public static function setLocale($locale)
{
- $locale = preg_replace_callback('/\b([a-z]{2})[-_](?:([a-z]{4})[-_])?([a-z]{2})\b/', function ($matches) {
- return $matches[1].'_'.(!empty($matches[2]) ? ucfirst($matches[2]).'_' : '').strtoupper($matches[3]);
- }, strtolower($locale));
-
- if (file_exists($filename = __DIR__.'/Lang/'.$locale.'.php')) {
- static::translator()->setLocale($locale);
- // Ensure the locale has been loaded.
- static::translator()->addResource('array', require $filename, $locale);
-
- return true;
- }
-
- return false;
+ return static::translator()->setLocale($locale) !== false;
}
///////////////////////////////////////////////////////////////////
*/
public function formatLocalized($format)
{
- // Check for Windows to find and replace the %e
- // modifier correctly
+ // Check for Windows to find and replace the %e modifier correctly.
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
- $format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format);
+ $format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format); // @codeCoverageIgnore
}
- $formatted = strftime($format, strtotime($this));
+ $formatted = strftime($format, strtotime($this->toDateTimeString()));
return static::$utf8 ? utf8_encode($formatted) : $formatted;
}
/**
* Reset the format used to the default when type juggling a Carbon instance to a string
+ *
+ * @return void
*/
public static function resetToStringFormat()
{
* Set the default format used when type juggling a Carbon instance to a string
*
* @param string $format
+ *
+ * @return void
*/
public static function setToStringFormat($format)
{
return $this->format(static::RFC822);
}
+ /**
+ * Convert the instance to UTC and return as Zulu ISO8601
+ *
+ * @return string
+ */
+ public function toIso8601ZuluString()
+ {
+ return $this->copy()->setTimezone('UTC')->format('Y-m-d\TH:i:s\Z');
+ }
+
/**
* Format the instance as RFC850
*
return $this->format(static::W3C);
}
+ /**
+ * Format the instance as RFC7231
+ *
+ * @return string
+ */
+ public function toRfc7231String()
+ {
+ return $this->copy()
+ ->setTimezone('GMT')
+ ->format(static::RFC7231_FORMAT);
+ }
+
+ /**
+ * Get default array representation
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return array(
+ 'year' => $this->year,
+ 'month' => $this->month,
+ 'day' => $this->day,
+ 'dayOfWeek' => $this->dayOfWeek,
+ 'dayOfYear' => $this->dayOfYear,
+ 'hour' => $this->hour,
+ 'minute' => $this->minute,
+ 'second' => $this->second,
+ 'micro' => $this->micro,
+ 'timestamp' => $this->timestamp,
+ 'formatted' => $this->format(self::DEFAULT_TO_STRING_FORMAT),
+ 'timezone' => $this->timezone,
+ );
+ }
+
///////////////////////////////////////////////////////////////////
////////////////////////// COMPARISONS ////////////////////////////
///////////////////////////////////////////////////////////////////
/**
* Determines if the instance is equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return bool
*/
- public function eq(Carbon $dt)
+ public function eq($date)
{
- return $this == $dt;
+ return $this == $date;
}
/**
* Determines if the instance is equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see eq()
*
* @return bool
*/
- public function equalTo(Carbon $dt)
+ public function equalTo($date)
{
- return $this->eq($dt);
+ return $this->eq($date);
}
/**
* Determines if the instance is not equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return bool
*/
- public function ne(Carbon $dt)
+ public function ne($date)
{
- return !$this->eq($dt);
+ return !$this->eq($date);
}
/**
* Determines if the instance is not equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see ne()
*
* @return bool
*/
- public function notEqualTo(Carbon $dt)
+ public function notEqualTo($date)
{
- return $this->ne($dt);
+ return $this->ne($date);
}
/**
* Determines if the instance is greater (after) than another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return bool
*/
- public function gt(Carbon $dt)
+ public function gt($date)
{
- return $this > $dt;
+ return $this > $date;
}
/**
* Determines if the instance is greater (after) than another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see gt()
*
* @return bool
*/
- public function greaterThan(Carbon $dt)
+ public function greaterThan($date)
{
- return $this->gt($dt);
+ return $this->gt($date);
}
/**
* Determines if the instance is greater (after) than or equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return bool
*/
- public function gte(Carbon $dt)
+ public function gte($date)
{
- return $this >= $dt;
+ return $this >= $date;
}
/**
* Determines if the instance is greater (after) than or equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see gte()
*
* @return bool
*/
- public function greaterThanOrEqualTo(Carbon $dt)
+ public function greaterThanOrEqualTo($date)
{
- return $this->gte($dt);
+ return $this->gte($date);
}
/**
* Determines if the instance is less (before) than another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return bool
*/
- public function lt(Carbon $dt)
+ public function lt($date)
{
- return $this < $dt;
+ return $this < $date;
}
/**
* Determines if the instance is less (before) than another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see lt()
*
* @return bool
*/
- public function lessThan(Carbon $dt)
+ public function lessThan($date)
{
- return $this->lt($dt);
+ return $this->lt($date);
}
/**
* Determines if the instance is less (before) or equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return bool
*/
- public function lte(Carbon $dt)
+ public function lte($date)
{
- return $this <= $dt;
+ return $this <= $date;
}
/**
* Determines if the instance is less (before) or equal to another
*
- * @param Carbon $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see lte()
*
* @return bool
*/
- public function lessThanOrEqualTo(Carbon $dt)
+ public function lessThanOrEqualTo($date)
{
- return $this->lte($dt);
+ return $this->lte($date);
}
/**
* Determines if the instance is between two others
*
- * @param Carbon $dt1
- * @param Carbon $dt2
- * @param bool $equal Indicates if a > and < comparison should be used or <= or >=
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ * @param bool $equal Indicates if a > and < comparison should be used or <= or >=
*
* @return bool
*/
- public function between(Carbon $dt1, Carbon $dt2, $equal = true)
+ public function between($date1, $date2, $equal = true)
{
- if ($dt1->gt($dt2)) {
- $temp = $dt1;
- $dt1 = $dt2;
- $dt2 = $temp;
+ if ($date1->gt($date2)) {
+ $temp = $date1;
+ $date1 = $date2;
+ $date2 = $temp;
}
if ($equal) {
- return $this->gte($dt1) && $this->lte($dt2);
+ return $this->gte($date1) && $this->lte($date2);
}
- return $this->gt($dt1) && $this->lt($dt2);
+ return $this->gt($date1) && $this->lt($date2);
}
/**
* Get the closest date from the instance.
*
- * @param Carbon $dt1
- * @param Carbon $dt2
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
*
* @return static
*/
- public function closest(Carbon $dt1, Carbon $dt2)
+ public function closest($date1, $date2)
{
- return $this->diffInSeconds($dt1) < $this->diffInSeconds($dt2) ? $dt1 : $dt2;
+ return $this->diffInSeconds($date1) < $this->diffInSeconds($date2) ? $date1 : $date2;
}
/**
* Get the farthest date from the instance.
*
- * @param Carbon $dt1
- * @param Carbon $dt2
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
*
* @return static
*/
- public function farthest(Carbon $dt1, Carbon $dt2)
+ public function farthest($date1, $date2)
{
- return $this->diffInSeconds($dt1) > $this->diffInSeconds($dt2) ? $dt1 : $dt2;
+ return $this->diffInSeconds($date1) > $this->diffInSeconds($date2) ? $date1 : $date2;
}
/**
* Get the minimum instance between a given instance (default now) and the current instance.
*
- * @param \Carbon\Carbon|null $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return static
*/
- public function min(Carbon $dt = null)
+ public function min($date = null)
{
- $dt = $dt ?: static::now($this->getTimezone());
+ $date = $this->resolveCarbon($date);
- return $this->lt($dt) ? $this : $dt;
+ return $this->lt($date) ? $this : $date;
}
/**
* Get the minimum instance between a given instance (default now) and the current instance.
*
- * @param \Carbon\Carbon|null $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see min()
*
* @return static
*/
- public function minimum(Carbon $dt = null)
+ public function minimum($date = null)
{
- return $this->min($dt);
+ return $this->min($date);
}
/**
* Get the maximum instance between a given instance (default now) and the current instance.
*
- * @param \Carbon\Carbon|null $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return static
*/
- public function max(Carbon $dt = null)
+ public function max($date = null)
{
- $dt = $dt ?: static::now($this->getTimezone());
+ $date = $this->resolveCarbon($date);
- return $this->gt($dt) ? $this : $dt;
+ return $this->gt($date) ? $this : $date;
}
/**
* Get the maximum instance between a given instance (default now) and the current instance.
*
- * @param \Carbon\Carbon|null $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @see max()
*
* @return static
*/
- public function maximum(Carbon $dt = null)
+ public function maximum($date = null)
{
- return $this->max($dt);
+ return $this->max($date);
}
/**
*/
public function isToday()
{
- return $this->toDateString() === static::now($this->getTimezone())->toDateString();
+ return $this->toDateString() === $this->nowWithSameTz()->toDateString();
}
/**
*/
public function isNextWeek()
{
- return $this->weekOfYear === static::now($this->getTimezone())->addWeek()->weekOfYear;
+ return $this->weekOfYear === $this->nowWithSameTz()->addWeek()->weekOfYear;
}
/**
*/
public function isLastWeek()
{
- return $this->weekOfYear === static::now($this->getTimezone())->subWeek()->weekOfYear;
+ return $this->weekOfYear === $this->nowWithSameTz()->subWeek()->weekOfYear;
+ }
+
+ /**
+ * Determines if the instance is within the next quarter
+ *
+ * @return bool
+ */
+ public function isNextQuarter()
+ {
+ return $this->quarter === $this->nowWithSameTz()->addQuarter()->quarter;
+ }
+
+ /**
+ * Determines if the instance is within the last quarter
+ *
+ * @return bool
+ */
+ public function isLastQuarter()
+ {
+ return $this->quarter === $this->nowWithSameTz()->subQuarter()->quarter;
}
/**
*/
public function isNextMonth()
{
- return $this->month === static::now($this->getTimezone())->addMonthNoOverflow()->month;
+ return $this->month === $this->nowWithSameTz()->addMonthNoOverflow()->month;
}
/**
*/
public function isLastMonth()
{
- return $this->month === static::now($this->getTimezone())->subMonthNoOverflow()->month;
+ return $this->month === $this->nowWithSameTz()->subMonthNoOverflow()->month;
}
/**
*/
public function isNextYear()
{
- return $this->year === static::now($this->getTimezone())->addYear()->year;
+ return $this->year === $this->nowWithSameTz()->addYear()->year;
}
/**
*/
public function isLastYear()
{
- return $this->year === static::now($this->getTimezone())->subYear()->year;
+ return $this->year === $this->nowWithSameTz()->subYear()->year;
}
/**
*/
public function isFuture()
{
- return $this->gt(static::now($this->getTimezone()));
+ return $this->gt($this->nowWithSameTz());
}
/**
*/
public function isPast()
{
- return $this->lt(static::now($this->getTimezone()));
+ return $this->lt($this->nowWithSameTz());
}
/**
return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53;
}
- /*
+ /**
* Compares the formatted values of the two dates.
*
- * @param string $format The date formats to compare.
- * @param \Carbon\Carbon|null $dt The instance to compare with or null to use current day.
+ * @param string $format The date formats to compare.
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ *
+ * @throws \InvalidArgumentException
*
* @return bool
*/
- public function isSameAs($format, Carbon $dt = null)
+ public function isSameAs($format, $date = null)
{
- $dt = $dt ?: static::now($this->tz);
+ $date = $date ?: static::now($this->tz);
+
+ static::expectDateTime($date);
- return $this->format($format) === $dt->format($format);
+ return $this->format($format) === $date->format($format);
}
/**
/**
* Checks if the passed in date is in the same year as the instance year.
*
- * @param \Carbon\Carbon|null $dt The instance to compare with or null to use current day.
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ *
+ * @return bool
+ */
+ public function isSameYear($date = null)
+ {
+ return $this->isSameAs('Y', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current month
+ *
+ * @return bool
+ */
+ public function isCurrentQuarter()
+ {
+ return $this->isSameQuarter();
+ }
+
+ /**
+ * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
*
* @return bool
*/
- public function isSameYear(Carbon $dt = null)
+ public function isSameQuarter($date = null, $ofSameYear = false)
{
- return $this->isSameAs('Y', $dt);
+ $date = $date ? static::instance($date) : static::now($this->tz);
+
+ static::expectDateTime($date);
+
+ return $this->quarter === $date->quarter && (!$ofSameYear || $this->isSameYear($date));
}
/**
}
/**
- * Checks if the passed in date is in the same month as the instance month (and year if needed).
+ * Checks if the passed in date is in the same month as the instance´s month.
+ *
+ * Note that this defaults to only comparing the month while ignoring the year.
+ * To test if it is the same exact month of the same year, pass in true as the second parameter.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isSameMonth($date = null, $ofSameYear = false)
+ {
+ return $this->isSameAs($ofSameYear ? 'Y-m' : 'm', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current day.
+ *
+ * @return bool
+ */
+ public function isCurrentDay()
+ {
+ return $this->isSameDay();
+ }
+
+ /**
+ * Checks if the passed in date is the same exact day as the instance´s day.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameDay($date = null)
+ {
+ return $this->isSameAs('Y-m-d', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current hour.
+ *
+ * @return bool
+ */
+ public function isCurrentHour()
+ {
+ return $this->isSameHour();
+ }
+
+ /**
+ * Checks if the passed in date is the same exact hour as the instance´s hour.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameHour($date = null)
+ {
+ return $this->isSameAs('Y-m-d H', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current minute.
+ *
+ * @return bool
+ */
+ public function isCurrentMinute()
+ {
+ return $this->isSameMinute();
+ }
+
+ /**
+ * Checks if the passed in date is the same exact minute as the instance´s minute.
*
- * @param \Carbon\Carbon|null $dt The instance to compare with or null to use current day.
- * @param bool $ofSameYear Check if it is the same month in the same year.
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameMinute($date = null)
+ {
+ return $this->isSameAs('Y-m-d H:i', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current second.
*
* @return bool
*/
- public function isSameMonth(Carbon $dt = null, $ofSameYear = false)
+ public function isCurrentSecond()
{
- $format = $ofSameYear ? 'Y-m' : 'm';
+ return $this->isSameSecond();
+ }
- return $this->isSameAs($format, $dt);
+ /**
+ * Checks if the passed in date is the same exact second as the instance´s second.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameSecond($date = null)
+ {
+ return $this->isSameAs('Y-m-d H:i:s', $date);
}
/**
- * Checks if the passed in date is the same day as the instance current day.
+ * Checks if this day is a specific day of the week.
*
- * @param \Carbon\Carbon $dt
+ * @param int $dayOfWeek
*
* @return bool
*/
- public function isSameDay(Carbon $dt)
+ public function isDayOfWeek($dayOfWeek)
{
- return $this->toDateString() === $dt->toDateString();
+ return $this->dayOfWeek === $dayOfWeek;
}
/**
return $this->dayOfWeek === static::SATURDAY;
}
- ///////////////////////////////////////////////////////////////////
- /////////////////// ADDITIONS AND SUBTRACTIONS ////////////////////
- ///////////////////////////////////////////////////////////////////
-
/**
- * Add years to the instance. Positive $value travel forward while
- * negative $value travel into the past.
+ * Check if its the birthday. Compares the date/month values of the two dates.
*
- * @param int $value
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
*
- * @return static
+ * @return bool
*/
- public function addYears($value)
+ public function isBirthday($date = null)
{
- return $this->modify((int) $value.' year');
+ return $this->isSameAs('md', $date);
}
/**
- * Add a year to the instance
- *
- * @param int $value
+ * Check if today is the last day of the Month
*
- * @return static
+ * @return bool
*/
- public function addYear($value = 1)
+ public function isLastOfMonth()
{
- return $this->addYears($value);
+ return $this->day === $this->daysInMonth;
}
/**
- * Remove a year from the instance
+ * Checks if the (date)time string is in a given format.
*
- * @param int $value
+ * @param string $date
+ * @param string $format
*
- * @return static
+ * @return bool
*/
- public function subYear($value = 1)
+ public static function hasFormat($date, $format)
{
- return $this->subYears($value);
+ try {
+ // Try to create a DateTime object. Throws an InvalidArgumentException if the provided time string
+ // doesn't match the format in any way.
+ static::createFromFormat($format, $date);
+
+ // createFromFormat() is known to handle edge cases silently.
+ // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format.
+ // To ensure we're really testing against our desired format, perform an additional regex validation.
+ $regex = strtr(
+ preg_quote($format, '/'),
+ static::$regexFormats
+ );
+
+ return (bool) preg_match('/^'.$regex.'$/', $date);
+ } catch (InvalidArgumentException $e) {
+ }
+
+ return false;
}
+ ///////////////////////////////////////////////////////////////////
+ /////////////////// ADDITIONS AND SUBTRACTIONS ////////////////////
+ ///////////////////////////////////////////////////////////////////
+
/**
- * Remove years from the instance.
+ * Add centuries to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
*
* @param int $value
*
* @return static
*/
- public function subYears($value)
+ public function addCenturies($value)
{
- return $this->addYears(-1 * $value);
+ return $this->addYears(static::YEARS_PER_CENTURY * $value);
}
/**
- * Add quarters to the instance. Positive $value travels forward while
- * negative $value travels into the past.
+ * Add a century to the instance
*
* @param int $value
*
* @return static
*/
- public function addQuarters($value)
+ public function addCentury($value = 1)
{
- return $this->addMonths(static::MONTHS_PER_QUARTER * $value);
+ return $this->addCenturies($value);
}
/**
- * Add a quarter to the instance
+ * Remove centuries from the instance
*
* @param int $value
*
* @return static
*/
- public function addQuarter($value = 1)
+ public function subCenturies($value)
{
- return $this->addQuarters($value);
+ return $this->addCenturies(-1 * $value);
}
/**
- * Remove a quarter from the instance
+ * Remove a century from the instance
*
* @param int $value
*
* @return static
*/
- public function subQuarter($value = 1)
+ public function subCentury($value = 1)
{
- return $this->subQuarters($value);
+ return $this->subCenturies($value);
}
/**
- * Remove quarters from the instance
+ * Add years to the instance. Positive $value travel forward while
+ * negative $value travel into the past.
*
* @param int $value
*
* @return static
*/
- public function subQuarters($value)
+ public function addYears($value)
{
- return $this->addQuarters(-1 * $value);
+ if ($this->shouldOverflowYears()) {
+ return $this->addYearsWithOverflow($value);
+ }
+
+ return $this->addYearsNoOverflow($value);
}
/**
- * Add centuries to the instance. Positive $value travels forward while
- * negative $value travels into the past.
+ * Add a year to the instance
*
* @param int $value
*
* @return static
*/
- public function addCenturies($value)
+ public function addYear($value = 1)
{
- return $this->addYears(static::YEARS_PER_CENTURY * $value);
+ return $this->addYears($value);
}
/**
- * Add a century to the instance
+ * Add years to the instance with no overflow of months
+ * Positive $value travel forward while
+ * negative $value travel into the past.
*
* @param int $value
*
* @return static
*/
- public function addCentury($value = 1)
+ public function addYearsNoOverflow($value)
{
- return $this->addCenturies($value);
+ return $this->addMonthsNoOverflow($value * static::MONTHS_PER_YEAR);
}
/**
- * Remove a century from the instance
+ * Add year with overflow months set to false
*
* @param int $value
*
* @return static
*/
- public function subCentury($value = 1)
+ public function addYearNoOverflow($value = 1)
{
- return $this->subCenturies($value);
+ return $this->addYearsNoOverflow($value);
}
/**
- * Remove centuries from the instance
+ * Add years to the instance.
+ * Positive $value travel forward while
+ * negative $value travel into the past.
*
* @param int $value
*
* @return static
*/
- public function subCenturies($value)
+ public function addYearsWithOverflow($value)
{
- return $this->addCenturies(-1 * $value);
+ return $this->modify((int) $value.' year');
}
/**
- * Add months to the instance. Positive $value travels forward while
- * negative $value travels into the past.
+ * Add year with overflow.
*
* @param int $value
*
* @return static
*/
- public function addMonths($value)
+ public function addYearWithOverflow($value = 1)
{
- if (static::shouldOverflowMonths()) {
- return $this->addMonthsWithOverflow($value);
- }
-
- return $this->addMonthsNoOverflow($value);
+ return $this->addYearsWithOverflow($value);
}
/**
- * Add a month to the instance
+ * Remove years from the instance.
*
* @param int $value
*
* @return static
*/
- public function addMonth($value = 1)
+ public function subYears($value)
{
- return $this->addMonths($value);
+ return $this->addYears(-1 * $value);
}
/**
- * Remove a month from the instance
+ * Remove a year from the instance
*
* @param int $value
*
* @return static
*/
- public function subMonth($value = 1)
+ public function subYear($value = 1)
{
- return $this->subMonths($value);
+ return $this->subYears($value);
+ }
+
+ /**
+ * Remove years from the instance with no month overflow.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearsNoOverflow($value)
+ {
+ return $this->subMonthsNoOverflow($value * static::MONTHS_PER_YEAR);
+ }
+
+ /**
+ * Remove year from the instance with no month overflow
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearNoOverflow($value = 1)
+ {
+ return $this->subYearsNoOverflow($value);
+ }
+
+ /**
+ * Remove years from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearsWithOverflow($value)
+ {
+ return $this->subMonthsWithOverflow($value * static::MONTHS_PER_YEAR);
+ }
+
+ /**
+ * Remove year from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearWithOverflow($value = 1)
+ {
+ return $this->subYearsWithOverflow($value);
+ }
+
+ /**
+ * Add quarters to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addQuarters($value)
+ {
+ return $this->addMonths(static::MONTHS_PER_QUARTER * $value);
+ }
+
+ /**
+ * Add a quarter to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addQuarter($value = 1)
+ {
+ return $this->addQuarters($value);
+ }
+
+ /**
+ * Remove quarters from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subQuarters($value)
+ {
+ return $this->addQuarters(-1 * $value);
+ }
+
+ /**
+ * Remove a quarter from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subQuarter($value = 1)
+ {
+ return $this->subQuarters($value);
+ }
+
+ /**
+ * Add months to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonths($value)
+ {
+ if (static::shouldOverflowMonths()) {
+ return $this->addMonthsWithOverflow($value);
+ }
+
+ return $this->addMonthsNoOverflow($value);
+ }
+
+ /**
+ * Add a month to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonth($value = 1)
+ {
+ return $this->addMonths($value);
}
/**
return $this->addMonths(-1 * $value);
}
+ /**
+ * Remove a month from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMonth($value = 1)
+ {
+ return $this->subMonths($value);
+ }
+
/**
* Add months to the instance. Positive $value travels forward while
* negative $value travels into the past.
}
/**
- * Remove a month from the instance
+ * Remove months from the instance
*
* @param int $value
*
* @return static
*/
- public function subMonthWithOverflow($value = 1)
+ public function subMonthsWithOverflow($value)
{
- return $this->subMonthsWithOverflow($value);
+ return $this->addMonthsWithOverflow(-1 * $value);
}
/**
- * Remove months from the instance
+ * Remove a month from the instance
*
* @param int $value
*
* @return static
*/
- public function subMonthsWithOverflow($value)
+ public function subMonthWithOverflow($value = 1)
{
- return $this->addMonthsWithOverflow(-1 * $value);
+ return $this->subMonthsWithOverflow($value);
}
/**
}
/**
- * Remove a month with no overflow from the instance
+ * Remove months with no overflow from the instance
*
* @param int $value
*
* @return static
*/
- public function subMonthNoOverflow($value = 1)
+ public function subMonthsNoOverflow($value)
{
- return $this->subMonthsNoOverflow($value);
+ return $this->addMonthsNoOverflow(-1 * $value);
}
/**
- * Remove months with no overflow from the instance
+ * Remove a month with no overflow from the instance
*
* @param int $value
*
* @return static
*/
- public function subMonthsNoOverflow($value)
+ public function subMonthNoOverflow($value = 1)
{
- return $this->addMonthsNoOverflow(-1 * $value);
+ return $this->subMonthsNoOverflow($value);
}
/**
}
/**
- * Remove a day from the instance
+ * Remove days from the instance
*
* @param int $value
*
* @return static
*/
- public function subDay($value = 1)
+ public function subDays($value)
{
- return $this->subDays($value);
+ return $this->addDays(-1 * $value);
}
/**
- * Remove days from the instance
+ * Remove a day from the instance
*
* @param int $value
*
* @return static
*/
- public function subDays($value)
+ public function subDay($value = 1)
{
- return $this->addDays(-1 * $value);
+ return $this->subDays($value);
}
/**
*/
public function addWeekdays($value)
{
- // fix for https://bugs.php.net/bug.php?id=54909
+ // Fix for weekday bug https://bugs.php.net/bug.php?id=54909
$t = $this->toTimeString();
$this->modify((int) $value.' weekday');
return $this->addWeekdays($value);
}
+ /**
+ * Remove weekdays from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subWeekdays($value)
+ {
+ return $this->addWeekdays(-1 * $value);
+ }
+
/**
* Remove a weekday from the instance
*
}
/**
- * Remove weekdays from the instance
+ * Add weeks to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
*
* @param int $value
*
* @return static
*/
- public function subWeekdays($value)
+ public function addWeeks($value)
{
- return $this->addWeekdays(-1 * $value);
+ return $this->modify((int) $value.' week');
}
/**
- * Add weeks to the instance. Positive $value travels forward while
+ * Add a week to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addWeek($value = 1)
+ {
+ return $this->addWeeks($value);
+ }
+
+ /**
+ * Remove weeks to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subWeeks($value)
+ {
+ return $this->addWeeks(-1 * $value);
+ }
+
+ /**
+ * Remove a week from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subWeek($value = 1)
+ {
+ return $this->subWeeks($value);
+ }
+
+ /**
+ * Add hours to the instance. Positive $value travels forward while
* negative $value travels into the past.
*
* @param int $value
*
* @return static
*/
- public function addWeeks($value)
+ public function addHours($value)
+ {
+ return $this->modify((int) $value.' hour');
+ }
+
+ /**
+ * Add hours to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealHours($value)
+ {
+ return $this->addRealMinutes($value * static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Add an hour to the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addHour($value = 1)
+ {
+ return $this->addHours($value);
+ }
+
+ /**
+ * Add an hour to the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealHour($value = 1)
+ {
+ return $this->addRealHours($value);
+ }
+
+ /**
+ * Remove hours from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subHours($value)
+ {
+ return $this->addHours(-1 * $value);
+ }
+
+ /**
+ * Remove hours from the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealHours($value)
+ {
+ return $this->addRealHours(-1 * $value);
+ }
+
+ /**
+ * Remove an hour from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subHour($value = 1)
+ {
+ return $this->subHours($value);
+ }
+
+ /**
+ * Remove an hour from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealHour($value = 1)
+ {
+ return $this->subRealHours($value);
+ }
+
+ /**
+ * Add minutes to the instance using timestamp. Positive $value
+ * travels forward while negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMinutes($value)
{
- return $this->modify((int) $value.' week');
+ return $this->modify((int) $value.' minute');
}
/**
- * Add a week to the instance
+ * Add minutes to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
*
* @param int $value
*
* @return static
*/
- public function addWeek($value = 1)
+ public function addRealMinutes($value)
{
- return $this->addWeeks($value);
+ return $this->addRealSeconds($value * static::SECONDS_PER_MINUTE);
}
/**
- * Remove a week from the instance
+ * Add a minute to the instance.
*
* @param int $value
*
* @return static
*/
- public function subWeek($value = 1)
+ public function addMinute($value = 1)
{
- return $this->subWeeks($value);
+ return $this->addMinutes($value);
}
/**
- * Remove weeks to the instance
+ * Add a minute to the instance using timestamp.
*
* @param int $value
*
* @return static
*/
- public function subWeeks($value)
+ public function addRealMinute($value = 1)
{
- return $this->addWeeks(-1 * $value);
+ return $this->addRealMinutes($value);
}
/**
- * Add hours to the instance. Positive $value travels forward while
- * negative $value travels into the past.
+ * Remove a minute from the instance.
*
* @param int $value
*
* @return static
*/
- public function addHours($value)
+ public function subMinute($value = 1)
{
- return $this->modify((int) $value.' hour');
+ return $this->subMinutes($value);
}
/**
- * Add an hour to the instance
+ * Remove a minute from the instance using timestamp.
*
* @param int $value
*
* @return static
*/
- public function addHour($value = 1)
+ public function subRealMinute($value = 1)
{
- return $this->addHours($value);
+ return $this->addRealMinutes(-1 * $value);
}
/**
- * Remove an hour from the instance
+ * Remove minutes from the instance.
*
* @param int $value
*
* @return static
*/
- public function subHour($value = 1)
+ public function subMinutes($value)
{
- return $this->subHours($value);
+ return $this->addMinutes(-1 * $value);
}
/**
- * Remove hours from the instance
+ * Remove a minute from the instance using timestamp.
*
* @param int $value
*
* @return static
*/
- public function subHours($value)
+ public function subRealMinutes($value = 1)
{
- return $this->addHours(-1 * $value);
+ return $this->subRealMinute($value);
}
/**
- * Add minutes to the instance. Positive $value travels forward while
+ * Add seconds to the instance. Positive $value travels forward while
* negative $value travels into the past.
*
* @param int $value
*
* @return static
*/
- public function addMinutes($value)
+ public function addSeconds($value)
{
- return $this->modify((int) $value.' minute');
+ return $this->modify((int) $value.' second');
}
/**
- * Add a minute to the instance
+ * Add seconds to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
*
* @param int $value
*
* @return static
*/
- public function addMinute($value = 1)
+ public function addRealSeconds($value)
{
- return $this->addMinutes($value);
+ return $this->setTimestamp($this->getTimestamp() + $value);
}
/**
- * Remove a minute from the instance
+ * Add a second to the instance.
*
* @param int $value
*
* @return static
*/
- public function subMinute($value = 1)
+ public function addSecond($value = 1)
{
- return $this->subMinutes($value);
+ return $this->addSeconds($value);
}
/**
- * Remove minutes from the instance
+ * Add a second to the instance using timestamp.
*
* @param int $value
*
* @return static
*/
- public function subMinutes($value)
+ public function addRealSecond($value = 1)
{
- return $this->addMinutes(-1 * $value);
+ return $this->addRealSeconds($value);
}
/**
- * Add seconds to the instance. Positive $value travels forward while
- * negative $value travels into the past.
+ * Remove seconds from the instance.
*
* @param int $value
*
* @return static
*/
- public function addSeconds($value)
+ public function subSeconds($value)
{
- return $this->modify((int) $value.' second');
+ return $this->addSeconds(-1 * $value);
}
/**
- * Add a second to the instance
+ * Remove seconds from the instance using timestamp.
*
* @param int $value
*
* @return static
*/
- public function addSecond($value = 1)
+ public function subRealSeconds($value)
{
- return $this->addSeconds($value);
+ return $this->addRealSeconds(-1 * $value);
}
/**
}
/**
- * Remove seconds from the instance
+ * Remove a second from the instance using timestamp.
*
* @param int $value
*
* @return static
*/
- public function subSeconds($value)
+ public function subRealSecond($value = 1)
{
- return $this->addSeconds(-1 * $value);
+ return $this->subRealSeconds($value);
}
///////////////////////////////////////////////////////////////////
/////////////////////////// DIFFERENCES ///////////////////////////
///////////////////////////////////////////////////////////////////
+ /**
+ * Get the difference as a CarbonInterval instance
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return CarbonInterval
+ */
+ public function diffAsCarbonInterval($date = null, $absolute = true)
+ {
+ return CarbonInterval::instance($this->diff($this->resolveCarbon($date), $absolute));
+ }
+
/**
* Get the difference in years
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInYears(Carbon $dt = null, $abs = true)
+ public function diffInYears($date = null, $absolute = true)
{
- $dt = $dt ?: static::now($this->getTimezone());
-
- return (int) $this->diff($dt, $abs)->format('%r%y');
+ return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%y');
}
/**
* Get the difference in months
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInMonths(Carbon $dt = null, $abs = true)
+ public function diffInMonths($date = null, $absolute = true)
{
- $dt = $dt ?: static::now($this->getTimezone());
+ $date = $this->resolveCarbon($date);
- return $this->diffInYears($dt, $abs) * static::MONTHS_PER_YEAR + (int) $this->diff($dt, $abs)->format('%r%m');
+ return $this->diffInYears($date, $absolute) * static::MONTHS_PER_YEAR + (int) $this->diff($date, $absolute)->format('%r%m');
}
/**
* Get the difference in weeks
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInWeeks(Carbon $dt = null, $abs = true)
+ public function diffInWeeks($date = null, $absolute = true)
{
- return (int) ($this->diffInDays($dt, $abs) / static::DAYS_PER_WEEK);
+ return (int) ($this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK);
}
/**
* Get the difference in days
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInDays(Carbon $dt = null, $abs = true)
+ public function diffInDays($date = null, $absolute = true)
{
- $dt = $dt ?: static::now($this->getTimezone());
-
- return (int) $this->diff($dt, $abs)->format('%r%a');
+ return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%a');
}
/**
* Get the difference in days using a filter closure
*
- * @param Closure $callback
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param Closure $callback
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInDaysFiltered(Closure $callback, Carbon $dt = null, $abs = true)
+ public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true)
{
- return $this->diffFiltered(CarbonInterval::day(), $callback, $dt, $abs);
+ return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute);
}
/**
* Get the difference in hours using a filter closure
*
- * @param Closure $callback
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param Closure $callback
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInHoursFiltered(Closure $callback, Carbon $dt = null, $abs = true)
+ public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true)
{
- return $this->diffFiltered(CarbonInterval::hour(), $callback, $dt, $abs);
+ return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute);
}
/**
* Get the difference by the given interval using a filter closure
*
- * @param CarbonInterval $ci An interval to traverse by
- * @param Closure $callback
- * @param Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param CarbonInterval $ci An interval to traverse by
+ * @param Closure $callback
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffFiltered(CarbonInterval $ci, Closure $callback, Carbon $dt = null, $abs = true)
+ public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true)
{
$start = $this;
- $end = $dt ?: static::now($this->getTimezone());
+ $end = $this->resolveCarbon($date);
$inverse = false;
if ($end < $start) {
}
$period = new DatePeriod($start, $ci, $end);
- $vals = array_filter(iterator_to_array($period), function (DateTime $date) use ($callback) {
+ $values = array_filter(iterator_to_array($period), function ($date) use ($callback) {
return call_user_func($callback, Carbon::instance($date));
});
- $diff = count($vals);
+ $diff = count($values);
- return $inverse && !$abs ? -$diff : $diff;
+ return $inverse && !$absolute ? -$diff : $diff;
}
/**
* Get the difference in weekdays
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInWeekdays(Carbon $dt = null, $abs = true)
+ public function diffInWeekdays($date = null, $absolute = true)
{
return $this->diffInDaysFiltered(function (Carbon $date) {
return $date->isWeekday();
- }, $dt, $abs);
+ }, $date, $absolute);
}
/**
* Get the difference in weekend days using a filter
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInWeekendDays(Carbon $dt = null, $abs = true)
+ public function diffInWeekendDays($date = null, $absolute = true)
{
return $this->diffInDaysFiltered(function (Carbon $date) {
return $date->isWeekend();
- }, $dt, $abs);
+ }, $date, $absolute);
+ }
+
+ /**
+ * Get the difference in hours.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInHours($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Get the difference in hours using timestamps.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealHours($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Get the difference in minutes.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMinutes($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
}
/**
- * Get the difference in hours
+ * Get the difference in minutes using timestamps.
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInHours(Carbon $dt = null, $abs = true)
+ public function diffInRealMinutes($date = null, $absolute = true)
{
- return (int) ($this->diffInSeconds($dt, $abs) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
+ return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
}
/**
- * Get the difference in minutes
+ * Get the difference in seconds.
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInMinutes(Carbon $dt = null, $abs = true)
+ public function diffInSeconds($date = null, $absolute = true)
{
- return (int) ($this->diffInSeconds($dt, $abs) / static::SECONDS_PER_MINUTE);
+ $diff = $this->diff($this->resolveCarbon($date));
+ $value = $diff->days * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE +
+ $diff->h * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE +
+ $diff->i * static::SECONDS_PER_MINUTE +
+ $diff->s;
+
+ return $absolute || !$diff->invert ? $value : -$value;
}
/**
- * Get the difference in seconds
+ * Get the difference in seconds using timestamps.
*
- * @param \Carbon\Carbon|null $dt
- * @param bool $abs Get the absolute of the difference
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
*
* @return int
*/
- public function diffInSeconds(Carbon $dt = null, $abs = true)
+ public function diffInRealSeconds($date = null, $absolute = true)
{
- $dt = $dt ?: static::now($this->getTimezone());
- $value = $dt->getTimestamp() - $this->getTimestamp();
+ $date = $this->resolveCarbon($date);
+ $value = $date->getTimestamp() - $this->getTimestamp();
- return $abs ? abs($value) : $value;
+ return $absolute ? abs($value) : $value;
}
/**
}
/**
- * The number of seconds until 23:23:59.
+ * The number of seconds until 23:59:59.
*
* @return int
*/
* @param Carbon|null $other
* @param bool $absolute removes time difference modifiers ago, after, etc
* @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
*
* @return string
*/
- public function diffForHumans(Carbon $other = null, $absolute = false, $short = false)
+ public function diffForHumans($other = null, $absolute = false, $short = false, $parts = 1)
{
$isNow = $other === null;
+ $interval = array();
+
+ $parts = min(6, max(1, (int) $parts));
+ $count = 1;
+ $unit = $short ? 's' : 'second';
if ($isNow) {
- $other = static::now($this->getTimezone());
+ $other = $this->nowWithSameTz();
+ } elseif (!$other instanceof DateTime && !$other instanceof DateTimeInterface) {
+ $other = static::parse($other);
}
$diffInterval = $this->diff($other);
- switch (true) {
- case $diffInterval->y > 0:
- $unit = $short ? 'y' : 'year';
- $count = $diffInterval->y;
- break;
-
- case $diffInterval->m > 0:
- $unit = $short ? 'm' : 'month';
- $count = $diffInterval->m;
- break;
+ $diffIntervalArray = array(
+ array('value' => $diffInterval->y, 'unit' => 'year', 'unitShort' => 'y'),
+ array('value' => $diffInterval->m, 'unit' => 'month', 'unitShort' => 'm'),
+ array('value' => $diffInterval->d, 'unit' => 'day', 'unitShort' => 'd'),
+ array('value' => $diffInterval->h, 'unit' => 'hour', 'unitShort' => 'h'),
+ array('value' => $diffInterval->i, 'unit' => 'minute', 'unitShort' => 'min'),
+ array('value' => $diffInterval->s, 'unit' => 'second', 'unitShort' => 's'),
+ );
- case $diffInterval->d > 0:
- $unit = $short ? 'd' : 'day';
- $count = $diffInterval->d;
+ foreach ($diffIntervalArray as $diffIntervalData) {
+ if ($diffIntervalData['value'] > 0) {
+ $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
+ $count = $diffIntervalData['value'];
- if ($count >= static::DAYS_PER_WEEK) {
+ if ($diffIntervalData['unit'] === 'day' && $count >= static::DAYS_PER_WEEK) {
$unit = $short ? 'w' : 'week';
$count = (int) ($count / static::DAYS_PER_WEEK);
- }
- break;
- case $diffInterval->h > 0:
- $unit = $short ? 'h' : 'hour';
- $count = $diffInterval->h;
- break;
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
- case $diffInterval->i > 0:
- $unit = $short ? 'min' : 'minute';
- $count = $diffInterval->i;
- break;
+ // get the count days excluding weeks (might be zero)
+ $numOfDaysCount = (int) ($diffIntervalData['value'] - ($count * static::DAYS_PER_WEEK));
- default:
- $count = $diffInterval->s;
- $unit = $short ? 's' : 'second';
+ if ($numOfDaysCount > 0 && count($interval) < $parts) {
+ $unit = $short ? 'd' : 'day';
+ $count = $numOfDaysCount;
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
+ }
+ } else {
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
+ }
+ }
+
+ // break the loop after we get the required number of parts in array
+ if (count($interval) >= $parts) {
break;
+ }
}
- if ($count === 0) {
- $count = 1;
+ if (count($interval) === 0) {
+ if ($isNow && static::getHumanDiffOptions() & self::JUST_NOW) {
+ $key = 'diff_now';
+ $translation = static::translator()->trans($key);
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+ $count = static::getHumanDiffOptions() & self::NO_ZERO_DIFF ? 1 : 0;
+ $unit = $short ? 's' : 'second';
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
}
- $time = static::translator()->transChoice($unit, $count, array(':count' => $count));
+ // join the interval parts by a space
+ $time = implode(' ', $interval);
+
+ unset($diffIntervalArray, $interval);
if ($absolute) {
return $time;
$transId = $isNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
- // Some langs have special pluralization for past and future tense.
- $tryKeyExists = $unit.'_'.$transId;
- if ($tryKeyExists !== static::translator()->transChoice($tryKeyExists, $count)) {
- $time = static::translator()->transChoice($tryKeyExists, $count, array(':count' => $count));
+ if ($parts === 1) {
+ if ($isNow && $unit === 'day') {
+ if ($count === 1 && static::getHumanDiffOptions() & self::ONE_DAY_WORDS) {
+ $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
+ $translation = static::translator()->trans($key);
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+ if ($count === 2 && static::getHumanDiffOptions() & self::TWO_DAY_WORDS) {
+ $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
+ $translation = static::translator()->trans($key);
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+ }
+ // Some langs have special pluralization for past and future tense.
+ $key = $unit.'_'.$transId;
+ $count = isset($count) ? $count : 1;
+ if ($key !== static::translator()->transChoice($key, $count)) {
+ $time = static::translator()->transChoice($key, $count, array(':count' => $count));
+ }
}
return static::translator()->trans($transId, array(':time' => $time));
///////////////////////////////////////////////////////////////////
/**
- * Resets the time to 00:00:00
+ * Resets the time to 00:00:00 start of day
*
* @return static
*/
public function startOfDay()
{
- return $this->setTime(0, 0, 0);
+ return $this->modify('00:00:00.000000');
}
/**
- * Resets the time to 23:59:59
+ * Resets the time to 23:59:59 end of day
*
* @return static
*/
public function endOfDay()
{
- return $this->setTime(23, 59, 59);
+ return $this->modify('23.59.59.999999');
}
/**
*/
public function startOfMonth()
{
- return $this->setDateTime($this->year, $this->month, 1, 0, 0, 0);
+ return $this->setDate($this->year, $this->month, 1)->startOfDay();
}
/**
*/
public function endOfMonth()
{
- return $this->setDateTime($this->year, $this->month, $this->daysInMonth, 23, 59, 59);
+ return $this->setDate($this->year, $this->month, $this->daysInMonth)->endOfDay();
}
/**
{
$month = ($this->quarter - 1) * static::MONTHS_PER_QUARTER + 1;
- return $this->setDateTime($this->year, $month, 1, 0, 0, 0);
+ return $this->setDate($this->year, $month, 1)->startOfDay();
}
/**
*/
public function startOfYear()
{
- return $this->setDateTime($this->year, 1, 1, 0, 0, 0);
+ return $this->setDate($this->year, 1, 1)->startOfDay();
}
/**
*/
public function endOfYear()
{
- return $this->setDateTime($this->year, 12, 31, 23, 59, 59);
+ return $this->setDate($this->year, 12, 31)->endOfDay();
}
/**
{
$year = $this->year - $this->year % static::YEARS_PER_DECADE;
- return $this->setDateTime($year, 1, 1, 0, 0, 0);
+ return $this->setDate($year, 1, 1)->startOfDay();
}
/**
{
$year = $this->year - $this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1;
- return $this->setDateTime($year, 12, 31, 23, 59, 59);
+ return $this->setDate($year, 12, 31)->endOfDay();
}
/**
{
$year = $this->year - ($this->year - 1) % static::YEARS_PER_CENTURY;
- return $this->setDateTime($year, 1, 1, 0, 0, 0);
+ return $this->setDate($year, 1, 1)->startOfDay();
}
/**
{
$year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY;
- return $this->setDateTime($year, 12, 31, 23, 59, 59);
+ return $this->setDate($year, 12, 31)->endOfDay();
}
/**
return $this->endOfDay();
}
+ /**
+ * Modify to start of current hour, minutes and seconds become 0
+ *
+ * @return static
+ */
+ public function startOfHour()
+ {
+ return $this->setTime($this->hour, 0, 0);
+ }
+
+ /**
+ * Modify to end of current hour, minutes and seconds become 59
+ *
+ * @return static
+ */
+ public function endOfHour()
+ {
+ return $this->setTime($this->hour, 59, 59);
+ }
+
+ /**
+ * Modify to start of current minute, seconds become 0
+ *
+ * @return static
+ */
+ public function startOfMinute()
+ {
+ return $this->setTime($this->hour, $this->minute, 0);
+ }
+
+ /**
+ * Modify to end of current minute, seconds become 59
+ *
+ * @return static
+ */
+ public function endOfMinute()
+ {
+ return $this->setTime($this->hour, $this->minute, 59);
+ }
+
+ /**
+ * Modify to midday, default to self::$midDayAt
+ *
+ * @return static
+ */
+ public function midDay()
+ {
+ return $this->setTime(self::$midDayAt, 0, 0);
+ }
+
/**
* Modify to the next occurrence of a given day of the week.
* If no dayOfWeek is provided, modify to the next occurrence
* @param bool $weekday
* @param bool $forward
*
- * @return static
+ * @return $this
*/
private function nextOrPreviousDay($weekday = true, $forward = true)
{
/**
* Go backward to the previous weekday.
*
- * @return static
+ * @return $this
*/
public function previousWeekday()
{
/**
* Go forward to the next weekend day.
*
- * @return static
+ * @return $this
*/
public function nextWeekendDay()
{
/**
* Go backward to the previous weekend day.
*
- * @return static
+ * @return $this
*/
public function previousWeekendDay()
{
*/
public function nthOfMonth($nth, $dayOfWeek)
{
- $dt = $this->copy()->firstOfMonth();
- $check = $dt->format('Y-m');
- $dt->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+ $date = $this->copy()->firstOfMonth();
+ $check = $date->format('Y-m');
+ $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
- return $dt->format('Y-m') === $check ? $this->modify($dt) : false;
+ return $date->format('Y-m') === $check ? $this->modify($date) : false;
}
/**
* first day of the current quarter. Use the supplied constants
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int|null $dayOfWeek
+ * @param int|null $dayOfWeek day of the week default null
*
* @return static
*/
* last day of the current quarter. Use the supplied constants
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int|null $dayOfWeek
+ * @param int|null $dayOfWeek day of the week default null
*
* @return static
*/
*/
public function nthOfQuarter($nth, $dayOfWeek)
{
- $dt = $this->copy()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
- $lastMonth = $dt->month;
- $year = $dt->year;
- $dt->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+ $date = $this->copy()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
+ $lastMonth = $date->month;
+ $year = $date->year;
+ $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
- return ($lastMonth < $dt->month || $year !== $dt->year) ? false : $this->modify($dt);
+ return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify($date);
}
/**
* first day of the current year. Use the supplied constants
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int|null $dayOfWeek
+ * @param int|null $dayOfWeek day of the week default null
*
* @return static
*/
* last day of the current year. Use the supplied constants
* to indicate the desired dayOfWeek, ex. static::MONDAY.
*
- * @param int|null $dayOfWeek
+ * @param int|null $dayOfWeek day of the week default null
*
* @return static
*/
*/
public function nthOfYear($nth, $dayOfWeek)
{
- $dt = $this->copy()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+ $date = $this->copy()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
- return $this->year === $dt->year ? $this->modify($dt) : false;
+ return $this->year === $date->year ? $this->modify($date) : false;
}
/**
* Modify the current instance to the average of a given instance (default now) and the current instance.
*
- * @param \Carbon\Carbon|null $dt
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date
*
* @return static
*/
- public function average(Carbon $dt = null)
+ public function average($date = null)
{
- $dt = $dt ?: static::now($this->getTimezone());
+ return $this->addSeconds((int) ($this->diffInSeconds($this->resolveCarbon($date), false) / 2));
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////////// SERIALIZATION /////////////////////////
+ ///////////////////////////////////////////////////////////////////
- return $this->addSeconds((int) ($this->diffInSeconds($dt, false) / 2));
+ /**
+ * Return a serialized string of the instance.
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize($this);
}
/**
- * Check if its the birthday. Compares the date/month values of the two dates.
+ * Create an instance from a serialized string.
*
- * @param \Carbon\Carbon|null $dt The instance to compare with or null to use current day.
+ * @param string $value
*
- * @return bool
+ * @throws \InvalidArgumentException
+ *
+ * @return static
*/
- public function isBirthday(Carbon $dt = null)
+ public static function fromSerialized($value)
{
- return $this->isSameAs('md', $dt);
+ $instance = @unserialize($value);
+
+ if (!$instance instanceof static) {
+ throw new InvalidArgumentException('Invalid serialized value.');
+ }
+
+ return $instance;
}
/**
- * Consider the timezone when modifying the instance.
+ * The __set_state handler.
*
- * @param string $modify
+ * @param array $array
*
* @return static
*/
- public function modify($modify)
+ public static function __set_state($array)
+ {
+ return static::instance(parent::__set_state($array));
+ }
+
+ /**
+ * Prepare the object for JSON serialization.
+ *
+ * @return array|string
+ */
+ public function jsonSerialize()
{
- if ($this->local) {
- return parent::modify($modify);
+ if (static::$serializer) {
+ return call_user_func(static::$serializer, $this);
}
- $timezone = $this->getTimezone();
- $this->setTimezone('UTC');
- $instance = parent::modify($modify);
- $this->setTimezone($timezone);
+ $carbon = $this;
- return $instance;
+ return call_user_func(function () use ($carbon) {
+ return get_object_vars($carbon);
+ });
}
/**
- * Return a serialized string of the instance.
+ * JSON serialize all Carbon instances using the given callback.
*
- * @return string
+ * @param callable $callback
+ *
+ * @return void
*/
- public function serialize()
+ public static function serializeUsing($callback)
{
- return serialize($this);
+ static::$serializer = $callback;
}
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////////////// MACRO /////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
/**
- * Create an instance form a serialized string.
+ * Register a custom macro.
*
- * @param string $value
+ * @param string $name
+ * @param object|callable $macro
*
- * @throws \InvalidArgumentException
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$localMacros[$name] = $macro;
+ }
+
+ /**
+ * Mix another object into the class.
*
- * @return static
+ * @param object $mixin
+ *
+ * @throws \ReflectionException
+ *
+ * @return void
*/
- public static function fromSerialized($value)
+ public static function mixin($mixin)
{
- $instance = @unserialize($value);
+ $reflection = new \ReflectionClass($mixin);
+ $methods = $reflection->getMethods(
+ \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED
+ );
- if (!$instance instanceof static) {
- throw new InvalidArgumentException('Invalid serialized value.');
+ foreach ($methods as $method) {
+ $method->setAccessible(true);
+
+ static::macro($method->name, $method->invoke($mixin));
}
+ }
- return $instance;
+ /**
+ * Checks if macro is registered.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$localMacros[$name]);
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @throws \BadMethodCallException
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ if (!static::hasMacro($method)) {
+ throw new \BadMethodCallException("Method $method does not exist.");
+ }
+
+ if (static::$localMacros[$method] instanceof Closure && method_exists('Closure', 'bind')) {
+ return call_user_func_array(Closure::bind(static::$localMacros[$method], null, get_called_class()), $parameters);
+ }
+
+ return call_user_func_array(static::$localMacros[$method], $parameters);
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @throws \BadMethodCallException|\ReflectionException
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (!static::hasMacro($method)) {
+ throw new \BadMethodCallException("Method $method does not exist.");
+ }
+
+ $macro = static::$localMacros[$method];
+
+ $reflexion = new \ReflectionFunction($macro);
+ $reflectionParameters = $reflexion->getParameters();
+ $expectedCount = count($reflectionParameters);
+ $actualCount = count($parameters);
+ if ($expectedCount > $actualCount && $reflectionParameters[$expectedCount - 1]->name === 'self') {
+ for ($i = $actualCount; $i < $expectedCount - 1; $i++) {
+ $parameters[] = $reflectionParameters[$i]->getDefaultValue();
+ }
+ $parameters[] = $this;
+ }
+
+ if ($macro instanceof Closure && method_exists($macro, 'bindTo')) {
+ return call_user_func_array($macro->bindTo($this, get_class($this)), $parameters);
+ }
+
+ return call_user_func_array($macro, $parameters);
}
}
use DateInterval;
use InvalidArgumentException;
-use Symfony\Component\Translation\Loader\ArrayLoader;
-use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\TranslatorInterface;
/**
* @method static CarbonInterval minute($minutes = 1) Alias for minutes()
* @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds.
* @method static CarbonInterval second($seconds = 1) Alias for seconds()
- * @method CarbonInterval years() years($years = 1) Set the years portion of the current interval.
- * @method CarbonInterval year() year($years = 1) Alias for years().
- * @method CarbonInterval months() months($months = 1) Set the months portion of the current interval.
- * @method CarbonInterval month() month($months = 1) Alias for months().
- * @method CarbonInterval weeks() weeks($weeks = 1) Set the weeks portion of the current interval. Will overwrite dayz value.
- * @method CarbonInterval week() week($weeks = 1) Alias for weeks().
- * @method CarbonInterval days() days($days = 1) Set the days portion of the current interval.
- * @method CarbonInterval dayz() dayz($days = 1) Alias for days().
- * @method CarbonInterval day() day($days = 1) Alias for days().
- * @method CarbonInterval hours() hours($hours = 1) Set the hours portion of the current interval.
- * @method CarbonInterval hour() hour($hours = 1) Alias for hours().
- * @method CarbonInterval minutes() minutes($minutes = 1) Set the minutes portion of the current interval.
- * @method CarbonInterval minute() minute($minutes = 1) Alias for minutes().
- * @method CarbonInterval seconds() seconds($seconds = 1) Set the seconds portion of the current interval.
- * @method CarbonInterval second() second($seconds = 1) Alias for seconds().
+ * @method CarbonInterval years($years = 1) Set the years portion of the current interval.
+ * @method CarbonInterval year($years = 1) Alias for years().
+ * @method CarbonInterval months($months = 1) Set the months portion of the current interval.
+ * @method CarbonInterval month($months = 1) Alias for months().
+ * @method CarbonInterval weeks($weeks = 1) Set the weeks portion of the current interval. Will overwrite dayz value.
+ * @method CarbonInterval week($weeks = 1) Alias for weeks().
+ * @method CarbonInterval days($days = 1) Set the days portion of the current interval.
+ * @method CarbonInterval dayz($days = 1) Alias for days().
+ * @method CarbonInterval day($days = 1) Alias for days().
+ * @method CarbonInterval hours($hours = 1) Set the hours portion of the current interval.
+ * @method CarbonInterval hour($hours = 1) Alias for hours().
+ * @method CarbonInterval minutes($minutes = 1) Set the minutes portion of the current interval.
+ * @method CarbonInterval minute($minutes = 1) Alias for minutes().
+ * @method CarbonInterval seconds($seconds = 1) Set the seconds portion of the current interval.
+ * @method CarbonInterval second($seconds = 1) Alias for seconds().
*/
class CarbonInterval extends DateInterval
{
/**
* Before PHP 5.4.20/5.5.4 instead of FALSE days will be set to -99999 when the interval instance
- * was created by DateTime:diff().
+ * was created by DateTime::diff().
*/
const PHP_DAYS_FALSE = -99999;
*/
public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null)
{
- $spec = static::PERIOD_PREFIX;
+ $spec = $years;
- $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
- $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
+ if (!is_string($spec) || floatval($years) || preg_match('/^[0-9.]/', $years)) {
+ $spec = static::PERIOD_PREFIX;
- $specDays = 0;
- $specDays += $weeks > 0 ? $weeks * Carbon::DAYS_PER_WEEK : 0;
- $specDays += $days > 0 ? $days : 0;
+ $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
+ $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
- $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
+ $specDays = 0;
+ $specDays += $weeks > 0 ? $weeks * Carbon::DAYS_PER_WEEK : 0;
+ $specDays += $days > 0 ? $days : 0;
- if ($hours > 0 || $minutes > 0 || $seconds > 0) {
- $spec .= static::PERIOD_TIME_PREFIX;
- $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
- $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
- $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
- }
+ $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
+
+ if ($hours > 0 || $minutes > 0 || $seconds > 0) {
+ $spec .= static::PERIOD_TIME_PREFIX;
+ $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
+ $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
+ $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
+ }
- if ($spec === static::PERIOD_PREFIX) {
- // Allow the zero interval.
- $spec .= '0'.static::PERIOD_YEARS;
+ if ($spec === static::PERIOD_PREFIX) {
+ // Allow the zero interval.
+ $spec .= '0'.static::PERIOD_YEARS;
+ }
}
parent::__construct($spec);
}
}
+ /**
+ * Creates a CarbonInterval from string
+ *
+ * Format:
+ *
+ * Suffix | Unit | Example | DateInterval expression
+ * -------|---------|---------|------------------------
+ * y | years | 1y | P1Y
+ * mo | months | 3mo | P3M
+ * w | weeks | 2w | P2W
+ * d | days | 28d | P28D
+ * h | hours | 4h | PT4H
+ * m | minutes | 12m | PT12M
+ * s | seconds | 59s | PT59S
+ *
+ * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
+ *
+ * Special cases:
+ * - An empty string will return a zero interval
+ * - Fractions are allowed for weeks, days, hours and minutes and will be converted
+ * and rounded to the next smaller value (caution: 0.5w = 4d)
+ *
+ * @param string $intervalDefinition
+ *
+ * @return static
+ */
+ public static function fromString($intervalDefinition)
+ {
+ if (empty($intervalDefinition)) {
+ return new static(0);
+ }
+
+ $years = 0;
+ $months = 0;
+ $weeks = 0;
+ $days = 0;
+ $hours = 0;
+ $minutes = 0;
+ $seconds = 0;
+
+ $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
+ preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
+ while ($match = array_shift($parts)) {
+ list($part, $value, $unit) = $match;
+ $intValue = intval($value);
+ $fraction = floatval($value) - $intValue;
+ switch (strtolower($unit)) {
+ case 'year':
+ case 'years':
+ case 'y':
+ $years += $intValue;
+ break;
+
+ case 'month':
+ case 'months':
+ case 'mo':
+ $months += $intValue;
+ break;
+
+ case 'week':
+ case 'weeks':
+ case 'w':
+ $weeks += $intValue;
+ if ($fraction != 0) {
+ $parts[] = array(null, $fraction * Carbon::DAYS_PER_WEEK, 'd');
+ }
+ break;
+
+ case 'day':
+ case 'days':
+ case 'd':
+ $days += $intValue;
+ if ($fraction != 0) {
+ $parts[] = array(null, $fraction * Carbon::HOURS_PER_DAY, 'h');
+ }
+ break;
+
+ case 'hour':
+ case 'hours':
+ case 'h':
+ $hours += $intValue;
+ if ($fraction != 0) {
+ $parts[] = array(null, $fraction * Carbon::MINUTES_PER_HOUR, 'm');
+ }
+ break;
+
+ case 'minute':
+ case 'minutes':
+ case 'm':
+ $minutes += $intValue;
+ if ($fraction != 0) {
+ $seconds += round($fraction * Carbon::SECONDS_PER_MINUTE);
+ }
+ break;
+
+ case 'second':
+ case 'seconds':
+ case 's':
+ $seconds += $intValue;
+ break;
+
+ default:
+ throw new InvalidArgumentException(
+ sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
+ );
+ }
+ }
+
+ return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds);
+ }
+
/**
* Create a CarbonInterval instance from a DateInterval one. Can not instance
* DateInterval objects created from DateTime::diff() as you can't externally
*
* @param DateInterval $di
*
- * @throws \InvalidArgumentException
- *
* @return static
*/
public static function instance(DateInterval $di)
{
- if (static::wasCreatedFromDiff($di)) {
- throw new InvalidArgumentException('Can not instance a DateInterval object created from DateTime::diff().');
- }
-
- $instance = new static($di->y, $di->m, 0, $di->d, $di->h, $di->i, $di->s);
+ $instance = new static(static::getDateIntervalSpec($di));
$instance->invert = $di->invert;
- $instance->days = $di->days;
return $instance;
}
protected static function translator()
{
if (static::$translator === null) {
- static::$translator = new Translator('en');
- static::$translator->addLoader('array', new ArrayLoader());
- static::setLocale('en');
+ static::$translator = Translator::get();
}
return static::$translator;
*/
public static function setLocale($locale)
{
- static::translator()->setLocale($locale);
-
- // Ensure the locale has been loaded.
- static::translator()->addResource('array', require __DIR__.'/Lang/'.$locale.'.php', $locale);
+ return static::translator()->setLocale($locale) !== false;
}
///////////////////////////////////////////////////////////////////
$parts = array();
foreach ($periods as $unit => $count) {
if ($count > 0) {
- array_push($parts, static::translator()->transChoice($unit, $count, array(':count' => $count)));
+ $parts[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
}
}
}
/**
- * Get the interval_spec string
+ * Multiply current instance given number of times
+ *
+ * @param float $factor
+ *
+ * @return $this
+ */
+ public function times($factor)
+ {
+ if ($factor < 0) {
+ $this->invert = $this->invert ? 0 : 1;
+ $factor = -$factor;
+ }
+
+ $this->years = round($this->years * $factor);
+ $this->months = round($this->months * $factor);
+ $this->dayz = round($this->dayz * $factor);
+ $this->hours = round($this->hours * $factor);
+ $this->minutes = round($this->minutes * $factor);
+ $this->seconds = round($this->seconds * $factor);
+
+ return $this;
+ }
+
+ /**
+ * Get the interval_spec string of a date interval
+ *
+ * @param DateInterval $interval
*
* @return string
*/
- public function spec()
+ public static function getDateIntervalSpec(DateInterval $interval)
{
$date = array_filter(array(
- static::PERIOD_YEARS => $this->y,
- static::PERIOD_MONTHS => $this->m,
- static::PERIOD_DAYS => $this->d,
+ static::PERIOD_YEARS => $interval->y,
+ static::PERIOD_MONTHS => $interval->m,
+ static::PERIOD_DAYS => $interval->d,
));
$time = array_filter(array(
- static::PERIOD_HOURS => $this->h,
- static::PERIOD_MINUTES => $this->i,
- static::PERIOD_SECONDS => $this->s,
+ static::PERIOD_HOURS => $interval->h,
+ static::PERIOD_MINUTES => $interval->i,
+ static::PERIOD_SECONDS => $interval->s,
));
$specString = static::PERIOD_PREFIX;
return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
}
+
+ /**
+ * Get the interval_spec string
+ *
+ * @return string
+ */
+ public function spec()
+ {
+ return static::getDateIntervalSpec($this);
+ }
+
+ /**
+ * Comparing 2 date intervals
+ *
+ * @param DateInterval $a
+ * @param DateInterval $b
+ *
+ * @return int
+ */
+ public static function compareDateIntervals(DateInterval $a, DateInterval $b)
+ {
+ $current = Carbon::now();
+ $passed = $current->copy()->add($b);
+ $current->add($a);
+
+ if ($current < $passed) {
+ return -1;
+ } elseif ($current > $passed) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Comparing with passed interval
+ *
+ * @param DateInterval $interval
+ *
+ * @return int
+ */
+ public function compare(DateInterval $interval)
+ {
+ return static::compareDateIntervals($this, $interval);
+ }
}
*/
return array(
- 'year' => '1 jaar|:count jare',
- 'y' => '1 jaar|:count jare',
- 'month' => '1 maand|:count maande',
- 'm' => '1 maand|:count maande',
- 'week' => '1 week|:count weke',
- 'w' => '1 week|:count weke',
- 'day' => '1 dag|:count dae',
- 'd' => '1 dag|:count dae',
- 'hour' => '1 uur|:count ure',
- 'h' => '1 uur|:count ure',
- 'minute' => '1 minuut|:count minute',
- 'min' => '1 minuut|:count minute',
- 'second' => '1 sekond|:count sekondes',
- 's' => '1 sekond|:count sekondes',
+ 'year' => ':count jaar|:count jare',
+ 'y' => ':count jaar|:count jare',
+ 'month' => ':count maand|:count maande',
+ 'm' => ':count maand|:count maande',
+ 'week' => ':count week|:count weke',
+ 'w' => ':count week|:count weke',
+ 'day' => ':count dag|:count dae',
+ 'd' => ':count dag|:count dae',
+ 'hour' => ':count uur|:count ure',
+ 'h' => ':count uur|:count ure',
+ 'minute' => ':count minuut|:count minute',
+ 'min' => ':count minuut|:count minute',
+ 'second' => ':count sekond|:count sekondes',
+ 's' => ':count sekond|:count sekondes',
'ago' => ':time terug',
'from_now' => ':time van nou af',
'after' => ':time na',
'y' => '{0}سنة|{1}سنة|{2}سنتين|[3,10]:count سنوات|[11,Inf]:count سنة',
'month' => '{0}شهر|{1} شهر|{2}شهرين|[3,10]:count أشهر|[11,Inf]:count شهر',
'm' => '{0}شهر|{1} شهر|{2}شهرين|[3,10]:count أشهر|[11,Inf]:count شهر',
- 'week' => '{0}إسبÙ\88ع|{1}إسبÙ\88ع|{2}إسبÙ\88عÙ\8aÙ\86|[3,10]:count أسابÙ\8aع|[11,Inf]:count Ø¥سبوع',
- 'w' => '{0}إسبÙ\88ع|{1}إسبÙ\88ع|{2}إسبÙ\88عÙ\8aÙ\86|[3,10]:count أسابÙ\8aع|[11,Inf]:count Ø¥سبوع',
+ 'week' => '{0}أسبÙ\88ع|{1}أسبÙ\88ع|{2}أسبÙ\88عÙ\8aÙ\86|[3,10]:count أسابÙ\8aع|[11,Inf]:count Ø£سبوع',
+ 'w' => '{0}أسبÙ\88ع|{1}أسبÙ\88ع|{2}أسبÙ\88عÙ\8aÙ\86|[3,10]:count أسابÙ\8aع|[11,Inf]:count Ø£سبوع',
'day' => '{0}يوم|{1}يوم|{2}يومين|[3,10]:count أيام|[11,Inf] يوم',
'd' => '{0}يوم|{1}يوم|{2}يومين|[3,10]:count أيام|[11,Inf] يوم',
'hour' => '{0}ساعة|{1}ساعة|{2}ساعتين|[3,10]:count ساعات|[11,Inf]:count ساعة',
'second' => '{0}ثانية|{1}ثانية|{2}ثانيتين|[3,10]:count ثوان|[11,Inf]:count ثانية',
's' => '{0}ثانية|{1}ثانية|{2}ثانيتين|[3,10]:count ثوان|[11,Inf]:count ثانية',
'ago' => 'منذ :time',
- 'from_now' => 'من الآن :time',
+ 'from_now' => ':time من الآن',
'after' => 'بعد :time',
'before' => 'قبل :time',
);
--- /dev/null
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '[0,1] سَنَة|{2} سَنَتَيْن|[3,10]:count سَنَوَات|[11,Inf]:count سَنَة',
+ 'y' => '[0,1] سَنَة|{2} سَنَتَيْن|[3,10]:count سَنَوَات|[11,Inf]:count سَنَة',
+ 'month' => '[0,1] شَهْرَ|{2} شَهْرَيْن|[3,10]:count أَشْهُر|[11,Inf]:count شَهْرَ',
+ 'm' => '[0,1] شَهْرَ|{2} شَهْرَيْن|[3,10]:count أَشْهُر|[11,Inf]:count شَهْرَ',
+ 'week' => '[0,1] أُسْبُوع|{2} أُسْبُوعَيْن|[3,10]:count أَسَابِيع|[11,Inf]:count أُسْبُوع',
+ 'w' => '[0,1] أُسْبُوع|{2} أُسْبُوعَيْن|[3,10]:count أَسَابِيع|[11,Inf]:count أُسْبُوع',
+ 'day' => '[0,1] يَوْم|{2} يَوْمَيْن|[3,10]:count أَيَّام|[11,Inf] يَوْم',
+ 'd' => '[0,1] يَوْم|{2} يَوْمَيْن|[3,10]:count أَيَّام|[11,Inf] يَوْم',
+ 'hour' => '[0,1] سَاعَة|{2} سَاعَتَيْن|[3,10]:count سَاعَات|[11,Inf]:count سَاعَة',
+ 'h' => '[0,1] سَاعَة|{2} سَاعَتَيْن|[3,10]:count سَاعَات|[11,Inf]:count سَاعَة',
+ 'minute' => '[0,1] دَقِيقَة|{2} دَقِيقَتَيْن|[3,10]:count دَقَائِق|[11,Inf]:count دَقِيقَة',
+ 'min' => '[0,1] دَقِيقَة|{2} دَقِيقَتَيْن|[3,10]:count دَقَائِق|[11,Inf]:count دَقِيقَة',
+ 'second' => '[0,1] ثَانِيَة|{2} ثَانِيَتَيْن|[3,10]:count ثَوَان|[11,Inf]:count ثَانِيَة',
+ 's' => '[0,1] ثَانِيَة|{2} ثَانِيَتَيْن|[3,10]:count ثَوَان|[11,Inf]:count ثَانِيَة',
+ 'ago' => 'مُنْذُ :time',
+ 'from_now' => 'مِنَ الْآن :time',
+ 'after' => 'بَعْدَ :time',
+ 'before' => 'قَبْلَ :time',
+);
'min' => ':count dəqiqə',
'second' => ':count saniyə',
's' => ':count saniyə',
- 'ago' => ':time öncə',
+ 'ago' => ':time əvvəl',
'from_now' => ':time sonra',
'after' => ':time sonra',
- 'before' => ':time öncə',
+ 'before' => ':time əvvəl',
);
*/
return array(
- 'year' => '1 година|:count години',
- 'y' => '1 година|:count години',
- 'month' => '1 месец|:count месеца',
- 'm' => '1 месец|:count месеца',
- 'week' => '1 седмица|:count седмици',
- 'w' => '1 седмица|:count седмици',
- 'day' => '1 ден|:count дни',
- 'd' => '1 ден|:count дни',
- 'hour' => '1 час|:count часа',
- 'h' => '1 час|:count часа',
- 'minute' => '1 минута|:count минути',
- 'm' => '1 минута|:count минути',
- 'second' => '1 секунда|:count секунди',
- 's' => '1 секунда|:count секунди',
+ 'year' => ':count година|:count години',
+ 'y' => ':count година|:count години',
+ 'month' => ':count месец|:count месеца',
+ 'm' => ':count месец|:count месеца',
+ 'week' => ':count седмица|:count седмици',
+ 'w' => ':count седмица|:count седмици',
+ 'day' => ':count ден|:count дни',
+ 'd' => ':count ден|:count дни',
+ 'hour' => ':count час|:count часа',
+ 'h' => ':count час|:count часа',
+ 'minute' => ':count минута|:count минути',
+ 'min' => ':count минута|:count минути',
+ 'second' => ':count секунда|:count секунди',
+ 's' => ':count секунда|:count секунди',
'ago' => 'преди :time',
'from_now' => ':time от сега',
'after' => 'след :time',
*/
return array(
- 'year' => '1 any|:count anys',
- 'y' => '1 any|:count anys',
- 'month' => '1 mes|:count mesos',
- 'm' => '1 mes|:count mesos',
- 'week' => '1 setmana|:count setmanes',
- 'w' => '1 setmana|:count setmanes',
- 'day' => '1 dia|:count dies',
- 'd' => '1 dia|:count dies',
- 'hour' => '1 hora|:count hores',
- 'h' => '1 hora|:count hores',
- 'minute' => '1 minut|:count minuts',
- 'min' => '1 minut|:count minuts',
- 'second' => '1 segon|:count segons',
- 's' => '1 segon|:count segons',
+ 'year' => ':count any|:count anys',
+ 'y' => ':count any|:count anys',
+ 'month' => ':count mes|:count mesos',
+ 'm' => ':count mes|:count mesos',
+ 'week' => ':count setmana|:count setmanes',
+ 'w' => ':count setmana|:count setmanes',
+ 'day' => ':count dia|:count dies',
+ 'd' => ':count dia|:count dies',
+ 'hour' => ':count hora|:count hores',
+ 'h' => ':count hora|:count hores',
+ 'minute' => ':count minut|:count minuts',
+ 'min' => ':count minut|:count minuts',
+ 'second' => ':count segon|:count segons',
+ 's' => ':count segon|:count segons',
'ago' => 'fa :time',
'from_now' => 'dins de :time',
'after' => ':time després',
*/
return array(
- 'year' => '1 rok|:count roky|:count let',
- 'y' => '1 rok|:count roky|:count let',
- 'month' => '1 měsíc|:count měsíce|:count měsíců',
- 'm' => '1 měsíc|:count měsíce|:count měsíců',
- 'week' => '1 týden|:count týdny|:count týdnů',
- 'w' => '1 týden|:count týdny|:count týdnů',
- 'day' => '1 den|:count dny|:count dní',
- 'd' => '1 den|:count dny|:count dní',
- 'hour' => '1 hodinu|:count hodiny|:count hodin',
- 'h' => '1 hodinu|:count hodiny|:count hodin',
- 'minute' => '1 minutu|:count minuty|:count minut',
- 'min' => '1 minutu|:count minuty|:count minut',
- 'second' => '1 sekundu|:count sekundy|:count sekund',
- 's' => '1 sekundu|:count sekundy|:count sekund',
+ 'year' => ':count rok|:count roky|:count let',
+ 'y' => ':count rok|:count roky|:count let',
+ 'month' => ':count měsíc|:count měsíce|:count měsíců',
+ 'm' => ':count měsíc|:count měsíce|:count měsíců',
+ 'week' => ':count týden|:count týdny|:count týdnů',
+ 'w' => ':count týden|:count týdny|:count týdnů',
+ 'day' => ':count den|:count dny|:count dní',
+ 'd' => ':count den|:count dny|:count dní',
+ 'hour' => ':count hodinu|:count hodiny|:count hodin',
+ 'h' => ':count hodinu|:count hodiny|:count hodin',
+ 'minute' => ':count minutu|:count minuty|:count minut',
+ 'min' => ':count minutu|:count minuty|:count minut',
+ 'second' => ':count sekundu|:count sekundy|:count sekund',
+ 's' => ':count sekundu|:count sekundy|:count sekund',
'ago' => ':time nazpět',
'from_now' => 'za :time',
'after' => ':time později',
--- /dev/null
+<?php
+/*
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array(
+ 'year' => '1 flwyddyn|:count blynedd',
+ 'y' => ':countbl',
+ 'month' => '1 mis|:count fis',
+ 'm' => ':countmi',
+ 'week' => ':count wythnos',
+ 'w' => ':countw',
+ 'day' => ':count diwrnod',
+ 'd' => ':countd',
+ 'hour' => ':count awr',
+ 'h' => ':counth',
+ 'minute' => ':count munud',
+ 'min' => ':countm',
+ 'second' => ':count eiliad',
+ 's' => ':counts',
+ 'ago' => ':time yn ôl',
+ 'from_now' => ':time o hyn ymlaen',
+ 'after' => ':time ar ôl',
+ 'before' => ':time o\'r blaen',
+);
*/
return array(
- 'year' => '1 år|:count år',
- 'y' => '1 år|:count år',
- 'month' => '1 måned|:count måneder',
- 'm' => '1 måned|:count måneder',
- 'week' => '1 uge|:count uger',
- 'w' => '1 uge|:count uger',
- 'day' => '1 dag|:count dage',
- 'd' => '1 dag|:count dage',
- 'hour' => '1 time|:count timer',
- 'h' => '1 time|:count timer',
- 'minute' => '1 minut|:count minutter',
- 'min' => '1 minut|:count minutter',
- 'second' => '1 sekund|:count sekunder',
- 's' => '1 sekund|:count sekunder',
+ 'year' => ':count år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count måned|:count måneder',
+ 'm' => ':count måned|:count måneder',
+ 'week' => ':count uge|:count uger',
+ 'w' => ':count uge|:count uger',
+ 'day' => ':count dag|:count dage',
+ 'd' => ':count dag|:count dage',
+ 'hour' => ':count time|:count timer',
+ 'h' => ':count time|:count timer',
+ 'minute' => ':count minut|:count minutter',
+ 'min' => ':count minut|:count minutter',
+ 'second' => ':count sekund|:count sekunder',
+ 's' => ':count sekund|:count sekunder',
'ago' => ':time siden',
'from_now' => 'om :time',
'after' => ':time efter',
*/
return array(
- 'year' => '1 Jahr|:count Jahre',
- 'y' => '1J|:countJ',
- 'month' => '1 Monat|:count Monate',
- 'm' => '1Mon|:countMon',
- 'week' => '1 Woche|:count Wochen',
- 'w' => '1Wo|:countWo',
- 'day' => '1 Tag|:count Tage',
- 'd' => '1Tg|:countTg',
- 'hour' => '1 Stunde|:count Stunden',
- 'h' => '1Std|:countStd',
- 'minute' => '1 Minute|:count Minuten',
- 'min' => '1Min|:countMin',
- 'second' => '1 Sekunde|:count Sekunden',
- 's' => '1Sek|:countSek',
+ 'year' => ':count Jahr|:count Jahre',
+ 'y' => ':countJ|:countJ',
+ 'month' => ':count Monat|:count Monate',
+ 'm' => ':countMon|:countMon',
+ 'week' => ':count Woche|:count Wochen',
+ 'w' => ':countWo|:countWo',
+ 'day' => ':count Tag|:count Tage',
+ 'd' => ':countTg|:countTg',
+ 'hour' => ':count Stunde|:count Stunden',
+ 'h' => ':countStd|:countStd',
+ 'minute' => ':count Minute|:count Minuten',
+ 'min' => ':countMin|:countMin',
+ 'second' => ':count Sekunde|:count Sekunden',
+ 's' => ':countSek|:countSek',
'ago' => 'vor :time',
'from_now' => 'in :time',
'after' => ':time später',
'before' => ':time zuvor',
- 'year_from_now' => '1 Jahr|:count Jahren',
- 'month_from_now' => '1 Monat|:count Monaten',
- 'week_from_now' => '1 Woche|:count Wochen',
- 'day_from_now' => '1 Tag|:count Tagen',
- 'year_ago' => '1 Jahr|:count Jahren',
- 'month_ago' => '1 Monat|:count Monaten',
- 'week_ago' => '1 Woche|:count Wochen',
- 'day_ago' => '1 Tag|:count Tagen',
+ 'year_from_now' => ':count Jahr|:count Jahren',
+ 'month_from_now' => ':count Monat|:count Monaten',
+ 'week_from_now' => ':count Woche|:count Wochen',
+ 'day_from_now' => ':count Tag|:count Tagen',
+ 'year_ago' => ':count Jahr|:count Jahren',
+ 'month_ago' => ':count Monat|:count Monaten',
+ 'week_ago' => ':count Woche|:count Wochen',
+ 'day_ago' => ':count Tag|:count Tagen',
);
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Carbon package.
+ *
+ * (c) Ahmed Ali <ajaaibu@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
+ 'y' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
+ 'month' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
+ 'm' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
+ 'week' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
+ 'w' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
+ 'day' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
+ 'd' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
+ 'hour' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
+ 'h' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
+ 'minute' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
+ 'min' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
+ 'second' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
+ 's' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
+ 'ago' => ':time ކުރިން',
+ 'from_now' => ':time ފަހުން',
+ 'after' => ':time ފަހުން',
+ 'before' => ':time ކުރި',
+);
*/
return array(
- 'year' => '1 χρόνος|:count χρόνια',
- 'y' => '1 χρόνος|:count χρόνια',
- 'month' => '1 μήνας|:count μήνες',
- 'm' => '1 μήνας|:count μήνες',
- 'week' => '1 εβδομάδα|:count εβδομάδες',
- 'w' => '1 εβδομάδα|:count εβδομάδες',
- 'day' => '1 μέρα|:count μέρες',
- 'd' => '1 μέρα|:count μέρες',
- 'hour' => '1 ώρα|:count ώρες',
- 'h' => '1 ώρα|:count ώρες',
- 'minute' => '1 λεπτό|:count λεπτά',
- 'min' => '1 λεπτό|:count λεπτά',
- 'second' => '1 δευτερόλεπτο|:count δευτερόλεπτα',
- 's' => '1 δευτερόλεπτο|:count δευτερόλεπτα',
- 'ago' => 'Ï\80Ï\81ίν αÏ\80ο :time',
- 'from_now' => 'σε :time απο τώρα',
+ 'year' => ':count χρόνος|:count χρόνια',
+ 'y' => ':count χρόνος|:count χρόνια',
+ 'month' => ':count μήνας|:count μήνες',
+ 'm' => ':count μήνας|:count μήνες',
+ 'week' => ':count εβδομάδα|:count εβδομάδες',
+ 'w' => ':count εβδομάδα|:count εβδομάδες',
+ 'day' => ':count μέρα|:count μέρες',
+ 'd' => ':count μέρα|:count μέρες',
+ 'hour' => ':count ώρα|:count ώρες',
+ 'h' => ':count ώρα|:count ώρες',
+ 'minute' => ':count λεπτό|:count λεπτά',
+ 'min' => ':count λεπτό|:count λεπτά',
+ 'second' => ':count δευτερόλεπτο|:count δευτερόλεπτα',
+ 's' => ':count δευτερόλεπτο|:count δευτερόλεπτα',
+ 'ago' => 'Ï\80Ï\81ιν αÏ\80Ï\8c :time',
+ 'from_now' => 'σε :time από τώρα',
'after' => ':time μετά',
- 'before' => ':time Ï\80Ï\81ίν',
+ 'before' => ':time Ï\80Ï\81ιν',
);
*/
return array(
- 'year' => '1 year|:count years',
- 'y' => '1yr|:countyrs',
- 'month' => '1 month|:count months',
- 'm' => '1mo|:countmos',
- 'week' => '1 week|:count weeks',
- 'w' => '1w|:countw',
- 'day' => '1 day|:count days',
- 'd' => '1d|:countd',
- 'hour' => '1 hour|:count hours',
- 'h' => '1h|:counth',
- 'minute' => '1 minute|:count minutes',
- 'min' => '1m|:countm',
- 'second' => '1 second|:count seconds',
- 's' => '1s|:counts',
+ 'year' => ':count year|:count years',
+ 'y' => ':countyr|:countyrs',
+ 'month' => ':count month|:count months',
+ 'm' => ':countmo|:countmos',
+ 'week' => ':count week|:count weeks',
+ 'w' => ':countw|:countw',
+ 'day' => ':count day|:count days',
+ 'd' => ':countd|:countd',
+ 'hour' => ':count hour|:count hours',
+ 'h' => ':counth|:counth',
+ 'minute' => ':count minute|:count minutes',
+ 'min' => ':countm|:countm',
+ 'second' => ':count second|:count seconds',
+ 's' => ':counts|:counts',
'ago' => ':time ago',
'from_now' => ':time from now',
'after' => ':time after',
'before' => ':time before',
+ 'diff_now' => 'just now',
+ 'diff_yesterday' => 'yesterday',
+ 'diff_tomorrow' => 'tomorrow',
+ 'diff_before_yesterday' => 'before yesterday',
+ 'diff_after_tomorrow' => 'after tomorrow',
);
*/
return array(
- 'year' => '1 jaro|:count jaroj',
- 'y' => '1 jaro|:count jaroj',
- 'month' => '1 monato|:count monatoj',
- 'm' => '1 monato|:count monatoj',
- 'week' => '1 semajno|:count semajnoj',
- 'w' => '1 semajno|:count semajnoj',
- 'day' => '1 tago|:count tagoj',
- 'd' => '1 tago|:count tagoj',
- 'hour' => '1 horo|:count horoj',
- 'h' => '1 horo|:count horoj',
- 'minute' => '1 minuto|:count minutoj',
- 'min' => '1 minuto|:count minutoj',
- 'second' => '1 sekundo|:count sekundoj',
- 's' => '1 sekundo|:count sekundoj',
+ 'year' => ':count jaro|:count jaroj',
+ 'y' => ':count jaro|:count jaroj',
+ 'month' => ':count monato|:count monatoj',
+ 'm' => ':count monato|:count monatoj',
+ 'week' => ':count semajno|:count semajnoj',
+ 'w' => ':count semajno|:count semajnoj',
+ 'day' => ':count tago|:count tagoj',
+ 'd' => ':count tago|:count tagoj',
+ 'hour' => ':count horo|:count horoj',
+ 'h' => ':count horo|:count horoj',
+ 'minute' => ':count minuto|:count minutoj',
+ 'min' => ':count minuto|:count minutoj',
+ 'second' => ':count sekundo|:count sekundoj',
+ 's' => ':count sekundo|:count sekundoj',
'ago' => 'antaŭ :time',
'from_now' => 'je :time',
'after' => ':time poste',
*/
return array(
- 'year' => '1 año|:count años',
- 'y' => '1 año|:count años',
- 'month' => '1 mes|:count meses',
- 'm' => '1 mes|:count meses',
- 'week' => '1 semana|:count semanas',
- 'w' => '1 semana|:count semanas',
- 'day' => '1 día|:count días',
- 'd' => '1 día|:count días',
- 'hour' => '1 hora|:count horas',
- 'h' => '1 hora|:count horas',
- 'minute' => '1 minuto|:count minutos',
- 'min' => '1 minuto|:count minutos',
- 'second' => '1 segundo|:count segundos',
- 's' => '1 segundo|:count segundos',
+ 'year' => ':count año|:count años',
+ 'y' => ':count año|:count años',
+ 'month' => ':count mes|:count meses',
+ 'm' => ':count mes|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'w' => ':count semana|:count semanas',
+ 'day' => ':count día|:count días',
+ 'd' => ':count día|:count días',
+ 'hour' => ':count hora|:count horas',
+ 'h' => ':count hora|:count horas',
+ 'minute' => ':count minuto|:count minutos',
+ 'min' => ':count minuto|:count minutos',
+ 'second' => ':count segundo|:count segundos',
+ 's' => ':count segundo|:count segundos',
'ago' => 'hace :time',
'from_now' => 'dentro de :time',
'after' => ':time después',
*/
return array(
- 'year' => '1 aasta|:count aastat',
- 'y' => '1 aasta|:count aastat',
- 'month' => '1 kuu|:count kuud',
- 'm' => '1 kuu|:count kuud',
- 'week' => '1 nädal|:count nädalat',
- 'w' => '1 nädal|:count nädalat',
- 'day' => '1 päev|:count päeva',
- 'd' => '1 päev|:count päeva',
- 'hour' => '1 tund|:count tundi',
- 'h' => '1 tund|:count tundi',
- 'minute' => '1 minut|:count minutit',
- 'min' => '1 minut|:count minutit',
- 'second' => '1 sekund|:count sekundit',
- 's' => '1 sekund|:count sekundit',
+ 'year' => ':count aasta|:count aastat',
+ 'y' => ':count aasta|:count aastat',
+ 'month' => ':count kuu|:count kuud',
+ 'm' => ':count kuu|:count kuud',
+ 'week' => ':count nädal|:count nädalat',
+ 'w' => ':count nädal|:count nädalat',
+ 'day' => ':count päev|:count päeva',
+ 'd' => ':count päev|:count päeva',
+ 'hour' => ':count tund|:count tundi',
+ 'h' => ':count tund|:count tundi',
+ 'minute' => ':count minut|:count minutit',
+ 'min' => ':count minut|:count minutit',
+ 'second' => ':count sekund|:count sekundit',
+ 's' => ':count sekund|:count sekundit',
'ago' => ':time tagasi',
'from_now' => ':time pärast',
'after' => ':time pärast',
*/
return array(
- 'year' => '1 vuosi|:count vuotta',
- 'y' => '1 vuosi|:count vuotta',
- 'month' => '1 kuukausi|:count kuukautta',
- 'm' => '1 kuukausi|:count kuukautta',
- 'week' => '1 viikko|:count viikkoa',
- 'w' => '1 viikko|:count viikkoa',
- 'day' => '1 päivä|:count päivää',
- 'd' => '1 päivä|:count päivää',
- 'hour' => '1 tunti|:count tuntia',
- 'h' => '1 tunti|:count tuntia',
- 'minute' => '1 minuutti|:count minuuttia',
- 'min' => '1 minuutti|:count minuuttia',
- 'second' => '1 sekunti|:count sekuntia',
- 's' => '1 sekunti|:count sekuntia',
+ 'year' => ':count vuosi|:count vuotta',
+ 'y' => ':count vuosi|:count vuotta',
+ 'month' => ':count kuukausi|:count kuukautta',
+ 'm' => ':count kuukausi|:count kuukautta',
+ 'week' => ':count viikko|:count viikkoa',
+ 'w' => ':count viikko|:count viikkoa',
+ 'day' => ':count päivä|:count päivää',
+ 'd' => ':count päivä|:count päivää',
+ 'hour' => ':count tunti|:count tuntia',
+ 'h' => ':count tunti|:count tuntia',
+ 'minute' => ':count minuutti|:count minuuttia',
+ 'min' => ':count minuutti|:count minuuttia',
+ 'second' => ':count sekunti|:count sekuntia',
+ 's' => ':count sekunti|:count sekuntia',
'ago' => ':time sitten',
'from_now' => ':time tästä hetkestä',
'after' => ':time sen jälkeen',
*/
return array(
- 'year' => '1 ár|:count ár',
- 'y' => '1 ár|:count ár',
- 'month' => '1 mánaður|:count mánaðir',
- 'm' => '1 mánaður|:count mánaðir',
- 'week' => '1 vika|:count vikur',
- 'w' => '1 vika|:count vikur',
- 'day' => '1 dag|:count dagar',
- 'd' => '1 dag|:count dagar',
- 'hour' => '1 tími|:count tímar',
- 'h' => '1 tími|:count tímar',
- 'minute' => '1 minutt|:count minuttir',
- 'min' => '1 minutt|:count minuttir',
- 'second' => '1 sekund|:count sekundir',
- 's' => '1 sekund|:count sekundir',
+ 'year' => ':count ár|:count ár',
+ 'y' => ':count ár|:count ár',
+ 'month' => ':count mánaður|:count mánaðir',
+ 'm' => ':count mánaður|:count mánaðir',
+ 'week' => ':count vika|:count vikur',
+ 'w' => ':count vika|:count vikur',
+ 'day' => ':count dag|:count dagar',
+ 'd' => ':count dag|:count dagar',
+ 'hour' => ':count tími|:count tímar',
+ 'h' => ':count tími|:count tímar',
+ 'minute' => ':count minutt|:count minuttir',
+ 'min' => ':count minutt|:count minuttir',
+ 'second' => ':count sekund|:count sekundir',
+ 's' => ':count sekund|:count sekundir',
'ago' => ':time síðan',
'from_now' => 'um :time',
'after' => ':time aftaná',
*/
return array(
- 'year' => '1 an|:count ans',
- 'y' => '1 an|:count ans',
+ 'year' => ':count an|:count ans',
+ 'y' => ':count an|:count ans',
'month' => ':count mois',
'm' => ':count mois',
- 'week' => '1 semaine|:count semaines',
- 'w' => '1 semaine|:count semaines',
- 'day' => '1 jour|:count jours',
- 'd' => '1 jour|:count jours',
- 'hour' => '1 heure|:count heures',
- 'h' => '1 heure|:count heures',
- 'minute' => '1 minute|:count minutes',
- 'min' => '1 minute|:count minutes',
- 'second' => '1 seconde|:count secondes',
- 's' => '1 seconde|:count secondes',
+ 'week' => ':count semaine|:count semaines',
+ 'w' => ':count sem.|:count sem.',
+ 'day' => ':count jour|:count jours',
+ 'd' => ':count j.|:count j.',
+ 'hour' => ':count heure|:count heures',
+ 'h' => ':count h|:count h.',
+ 'minute' => ':count minute|:count minutes',
+ 'min' => ':count min.|:count min.',
+ 'second' => ':count seconde|:count secondes',
+ 's' => ':count sec.|:count sec.',
'ago' => 'il y a :time',
'from_now' => 'dans :time',
'after' => ':time après',
'before' => ':time avant',
+ 'diff_now' => "à l'instant",
+ 'diff_yesterday' => 'hier',
+ 'diff_tomorrow' => 'demain',
+ 'diff_before_yesterday' => 'avant-hier',
+ 'diff_after_tomorrow' => 'après-demain',
);
*/
return array(
- 'year' => '1 ano|:count anos',
- 'month' => '1 mes|:count meses',
- 'week' => '1 semana|:count semanas',
- 'day' => '1 día|:count días',
- 'hour' => '1 hora|:count horas',
- 'minute' => '1 minuto|:count minutos',
- 'second' => '1 segundo|:count segundos',
+ 'year' => ':count ano|:count anos',
+ 'month' => ':count mes|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'day' => ':count día|:count días',
+ 'hour' => ':count hora|:count horas',
+ 'minute' => ':count minuto|:count minutos',
+ 'second' => ':count segundo|:count segundos',
'ago' => 'fai :time',
'from_now' => 'dentro de :time',
'after' => ':time despois',
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count વર્ષ|:count વર્ષો',
+ 'y' => ':countવર્ષ|:countવર્ષો',
+ 'month' => ':count મહિનો|:count મહિના',
+ 'm' => ':countમહિનો|:countમહિના',
+ 'week' => ':count અઠવાડિયું|:count અઠવાડિયા',
+ 'w' => ':countઅઠ.|:countઅઠ.',
+ 'day' => ':count દિવસ|:count દિવસો',
+ 'd' => ':countદિ.|:countદિ.',
+ 'hour' => ':count કલાક|:count કલાકો',
+ 'h' => ':countક.|:countક.',
+ 'minute' => ':count મિનિટ|:count મિનિટ',
+ 'min' => ':countમિ.|:countમિ.',
+ 'second' => ':count સેકેન્ડ|:count સેકેન્ડ',
+ 's' => ':countસે.|:countસે.',
+ 'ago' => ':time પહેલા',
+ 'from_now' => ':time અત્યારથી',
+ 'after' => ':time પછી',
+ 'before' => ':time પહેલા',
+);
return array(
'year' => ':count տարի',
- 'y' => ':count տարի',
+ 'y' => ':countտ',
'month' => ':count ամիս',
- 'm' => ':count ամիս',
+ 'm' => ':countամ',
'week' => ':count շաբաթ',
- 'w' => ':count շաբաթ',
+ 'w' => ':countշ',
'day' => ':count օր',
- 'd' => ':count օր',
+ 'd' => ':countօր',
'hour' => ':count ժամ',
- 'h' => ':count ժամ',
+ 'h' => ':countժ',
'minute' => ':count րոպե',
- 'min' => ':count րոպե',
- 'second' => ':count վայրկյան',
- 's' => ':count վայրկյան',
+ 'min' => ':countր',
+ 'second' => ':count վարկյան',
+ 's' => ':countվրկ',
'ago' => ':time առաջ',
- 'from_now' => ':time Õ°Õ¥Õ¿Õ¸',
+ 'from_now' => ':time Õ¶Õ¥Ö\80Õ¯Õ¡ ÕºÕ¡Õ°Õ«Ö\81',
'after' => ':time հետո',
'before' => ':time առաջ',
);
*/
return array(
- 'year' => '1 anno|:count anni',
- 'y' => '1 anno|:count anni',
- 'month' => '1 mese|:count mesi',
- 'm' => '1 mese|:count mesi',
- 'week' => '1 settimana|:count settimane',
- 'w' => '1 settimana|:count settimane',
- 'day' => '1 giorno|:count giorni',
- 'd' => '1 giorno|:count giorni',
- 'hour' => '1 ora|:count ore',
- 'h' => '1 ora|:count ore',
- 'minute' => '1 minuto|:count minuti',
- 'min' => '1 minuto|:count minuti',
- 'second' => '1 secondo|:count secondi',
- 's' => '1 secondo|:count secondi',
+ 'year' => ':count anno|:count anni',
+ 'y' => ':count anno|:count anni',
+ 'month' => ':count mese|:count mesi',
+ 'm' => ':count mese|:count mesi',
+ 'week' => ':count settimana|:count settimane',
+ 'w' => ':count settimana|:count settimane',
+ 'day' => ':count giorno|:count giorni',
+ 'd' => ':count giorno|:count giorni',
+ 'hour' => ':count ora|:count ore',
+ 'h' => ':count ora|:count ore',
+ 'minute' => ':count minuto|:count minuti',
+ 'min' => ':count minuto|:count minuti',
+ 'second' => ':count secondo|:count secondi',
+ 's' => ':count secondo|:count secondi',
'ago' => ':time fa',
- 'from_now' => ':time da adesso',
+ 'from_now' => 'tra :time',
'after' => ':time dopo',
'before' => ':time prima',
+ 'diff_now' => 'proprio ora',
+ 'diff_yesterday' => 'ieri',
+ 'diff_tomorrow' => 'domani',
+ 'diff_before_yesterday' => "l'altro ieri",
+ 'diff_after_tomorrow' => 'dopodomani',
);
*/
return array(
- 'year' => ':count 年',
- 'y' => ':count 年',
- 'month' => ':count ヶ月',
- 'm' => ':count ヶ月',
- 'week' => ':count 週間',
- 'w' => ':count 週間',
- 'day' => ':count 日',
- 'd' => ':count 日',
- 'hour' => ':count 時間',
- 'h' => ':count 時間',
- 'minute' => ':count 分',
- 'min' => ':count 分',
- 'second' => ':count 秒',
- 's' => ':count 秒',
- 'ago' => ':time 前',
- 'from_now' => '今から :time',
- 'after' => ':time 後',
- 'before' => ':time 前',
+ 'year' => ':count年',
+ 'y' => ':count年',
+ 'month' => ':countヶ月',
+ 'm' => ':countヶ月',
+ 'week' => ':count週間',
+ 'w' => ':count週間',
+ 'day' => ':count日',
+ 'd' => ':count日',
+ 'hour' => ':count時間',
+ 'h' => ':count時間',
+ 'minute' => ':count分',
+ 'min' => ':count分',
+ 'second' => ':count秒',
+ 's' => ':count秒',
+ 'ago' => ':time前',
+ 'from_now' => '今から:time',
+ 'after' => ':time後',
+ 'before' => ':time前',
);
--- /dev/null
+<?php
+/*
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array(
+ 'year' => ':count жыл',
+ 'y' => ':count жыл',
+ 'month' => ':count ай',
+ 'm' => ':count ай',
+ 'week' => ':count апта',
+ 'w' => ':count апта',
+ 'day' => ':count күн',
+ 'd' => ':count күн',
+ 'hour' => ':count сағат',
+ 'h' => ':count сағат',
+ 'minute' => ':count минут',
+ 'min' => ':count минут',
+ 'second' => ':count секунд',
+ 's' => ':count секунд',
+ 'ago' => ':time бұрын',
+ 'from_now' => ':time кейін',
+ 'after' => ':time кейін',
+ 'before' => ':time бұрын',
+);
*/
return array(
- 'year' => '1 година|:count години',
- 'month' => '1 месец|:count месеци',
- 'week' => '1 седмица|:count седмици',
- 'day' => '1 ден|:count дена',
- 'hour' => '1 час|:count часа',
- 'minute' => '1 минута|:count минути',
- 'second' => '1 секунда|:count секунди',
+ 'year' => ':count година|:count години',
+ 'month' => ':count месец|:count месеци',
+ 'week' => ':count седмица|:count седмици',
+ 'day' => ':count ден|:count дена',
+ 'hour' => ':count час|:count часа',
+ 'minute' => ':count минута|:count минути',
+ 'second' => ':count секунда|:count секунди',
'ago' => 'пред :time',
'from_now' => ':time од сега',
'after' => 'по :time',
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @translator Batmandakh Erdenebileg <batmandakh.e@icloud.com>
+ */
+
+return array(
+ 'year' => ':count жил',
+ 'y' => ':count жил',
+ 'month' => ':count сар',
+ 'm' => ':count сар',
+ 'week' => ':count долоо хоног',
+ 'w' => ':count долоо хоног',
+ 'day' => ':count өдөр',
+ 'd' => ':count өдөр',
+ 'hour' => ':count цаг',
+ 'h' => ':countц',
+ 'minute' => ':count минут',
+ 'min' => ':countм',
+ 'second' => ':count секунд',
+ 's' => ':countс',
+
+ 'ago' => ':timeн өмнө',
+ 'year_ago' => ':count жилий',
+ 'month_ago' => ':count сары',
+ 'day_ago' => ':count хоногий',
+ 'hour_ago' => ':count цагий',
+ 'minute_ago' => ':count минуты',
+ 'second_ago' => ':count секунды',
+
+ 'from_now' => 'одоогоос :time',
+ 'year_from_now' => ':count жилийн дараа',
+ 'month_from_now' => ':count сарын дараа',
+ 'day_from_now' => ':count хоногийн дараа',
+ 'hour_from_now' => ':count цагийн дараа',
+ 'minute_from_now' => ':count минутын дараа',
+ 'second_from_now' => ':count секундын дараа',
+
+ // Does it required to make translation for before, after as follows? hmm, I think we've made it with ago and from now keywords already. Anyway, I've included it just in case of undesired action...
+ 'after' => ':timeн дараа',
+ 'year_after' => ':count жилий',
+ 'month_after' => ':count сары',
+ 'day_after' => ':count хоногий',
+ 'hour_after' => ':count цагий',
+ 'minute_after' => ':count минуты',
+ 'second_after' => ':count секунды',
+ 'before' => ':timeн өмнө',
+ 'year_before' => ':count жилий',
+ 'month_before' => ':count сары',
+ 'day_before' => ':count хоногий',
+ 'hour_before' => ':count цагий',
+ 'minute_before' => ':count минуты',
+ 'second_before' => ':count секунды',
+);
return array(
'year' => ':count jaar',
'y' => ':count jaar',
- 'month' => '1 maand|:count maanden',
- 'm' => '1 maand|:count maanden',
- 'week' => '1 week|:count weken',
- 'w' => '1 week|:count weken',
- 'day' => '1 dag|:count dagen',
- 'd' => '1 dag|:count dagen',
+ 'month' => ':count maand|:count maanden',
+ 'm' => ':count maand|:count maanden',
+ 'week' => ':count week|:count weken',
+ 'w' => ':count week|:count weken',
+ 'day' => ':count dag|:count dagen',
+ 'd' => ':count dag|:count dagen',
'hour' => ':count uur',
'h' => ':count uur',
- 'minute' => '1 minuut|:count minuten',
- 'min' => '1 minuut|:count minuten',
- 'second' => '1 seconde|:count seconden',
- 's' => '1 seconde|:count seconden',
+ 'minute' => ':count minuut|:count minuten',
+ 'min' => ':count minuut|:count minuten',
+ 'second' => ':count seconde|:count seconden',
+ 's' => ':count seconde|:count seconden',
'ago' => ':time geleden',
'from_now' => 'over :time',
'after' => ':time later',
*/
return array(
- 'year' => '1 år|:count år',
- 'y' => '1 år|:count år',
- 'month' => '1 måned|:count måneder',
- 'm' => '1 måned|:count måneder',
- 'week' => '1 uke|:count uker',
- 'w' => '1 uke|:count uker',
- 'day' => '1 dag|:count dager',
- 'd' => '1 dag|:count dager',
- 'hour' => '1 time|:count timer',
- 'h' => '1 time|:count timer',
- 'minute' => '1 minutt|:count minutter',
- 'min' => '1 minutt|:count minutter',
- 'second' => '1 sekund|:count sekunder',
- 's' => '1 sekund|:count sekunder',
+ 'year' => ':count år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count måned|:count måneder',
+ 'm' => ':count måned|:count måneder',
+ 'week' => ':count uke|:count uker',
+ 'w' => ':count uke|:count uker',
+ 'day' => ':count dag|:count dager',
+ 'd' => ':count dag|:count dager',
+ 'hour' => ':count time|:count timer',
+ 'h' => ':count time|:count timer',
+ 'minute' => ':count minutt|:count minutter',
+ 'min' => ':count minutt|:count minutter',
+ 'second' => ':count sekund|:count sekunder',
+ 's' => ':count sekund|:count sekunder',
'ago' => ':time siden',
'from_now' => 'om :time',
'after' => ':time etter',
*/
return array(
- 'year' => '1 rok|:count lata|:count lat',
- 'y' => '1 rok|:count lata|:count lat',
- 'month' => '1 miesiąc|:count miesiące|:count miesięcy',
- 'm' => '1 miesiąc|:count miesiące|:count miesięcy',
- 'week' => '1 tydzień|:count tygodnie|:count tygodni',
- 'w' => '1 tydzień|:count tygodnie|:count tygodni',
- 'day' => '1 dzień|:count dni|:count dni',
- 'd' => '1 dzień|:count dni|:count dni',
- 'hour' => '1 godzina|:count godziny|:count godzin',
- 'h' => '1 godzina|:count godziny|:count godzin',
- 'minute' => '1 minuta|:count minuty|:count minut',
- 'min' => '1 minuta|:count minuty|:count minut',
- 'second' => '1 sekunda|:count sekundy|:count sekund',
- 's' => '1 sekunda|:count sekundy|:count sekund',
+ 'year' => ':count rok|:count lata|:count lat',
+ 'y' => ':count rok|:count lata|:count lat',
+ 'month' => ':count miesiąc|:count miesiące|:count miesięcy',
+ 'm' => ':count miesiąc|:count miesiące|:count miesięcy',
+ 'week' => ':count tydzień|:count tygodnie|:count tygodni',
+ 'w' => ':count tydzień|:count tygodnie|:count tygodni',
+ 'day' => ':count dzień|:count dni|:count dni',
+ 'd' => ':count dzień|:count dni|:count dni',
+ 'hour' => ':count godzina|:count godziny|:count godzin',
+ 'h' => ':count godzina|:count godziny|:count godzin',
+ 'minute' => ':count minuta|:count minuty|:count minut',
+ 'min' => ':count minuta|:count minuty|:count minut',
+ 'second' => ':count sekunda|:count sekundy|:count sekund',
+ 's' => ':count sekunda|:count sekundy|:count sekund',
'ago' => ':time temu',
'from_now' => ':time od teraz',
- 'after' => ':time przed',
- 'before' => ':time po',
+ 'after' => ':time po',
+ 'before' => ':time przed',
);
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count کال|:count کاله',
+ 'y' => ':countکال|:countکاله',
+ 'month' => ':count مياشت|:count مياشتي',
+ 'm' => ':countمياشت|:countمياشتي',
+ 'week' => ':count اونۍ|:count اونۍ',
+ 'w' => ':countاونۍ|:countاونۍ',
+ 'day' => ':count ورځ|:count ورځي',
+ 'd' => ':countورځ|:countورځي',
+ 'hour' => ':count ساعت|:count ساعته',
+ 'h' => ':countساعت|:countساعته',
+ 'minute' => ':count دقيقه|:count دقيقې',
+ 'min' => ':countدقيقه|:countدقيقې',
+ 'second' => ':count ثانيه|:count ثانيې',
+ 's' => ':countثانيه|:countثانيې',
+ 'ago' => ':time دمخه',
+ 'from_now' => ':time له اوس څخه',
+ 'after' => ':time وروسته',
+ 'before' => ':time دمخه',
+);
*/
return array(
- 'year' => '1 ano|:count anos',
- 'y' => '1 ano|:count anos',
- 'month' => '1 mês|:count meses',
- 'm' => '1 mês|:count meses',
- 'week' => '1 semana|:count semanas',
- 'w' => '1 semana|:count semanas',
- 'day' => '1 dia|:count dias',
- 'd' => '1 dia|:count dias',
- 'hour' => '1 hora|:count horas',
- 'h' => '1 hora|:count horas',
- 'minute' => '1 minuto|:count minutos',
- 'min' => '1 minuto|:count minutos',
- 'second' => '1 segundo|:count segundos',
- 's' => '1 segundo|:count segundos',
+ 'year' => ':count ano|:count anos',
+ 'y' => ':count ano|:count anos',
+ 'month' => ':count mês|:count meses',
+ 'm' => ':count mês|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'w' => ':count semana|:count semanas',
+ 'day' => ':count dia|:count dias',
+ 'd' => ':count dia|:count dias',
+ 'hour' => ':count hora|:count horas',
+ 'h' => ':count hora|:count horas',
+ 'minute' => ':count minuto|:count minutos',
+ 'min' => ':count minuto|:count minutos',
+ 'second' => ':count segundo|:count segundos',
+ 's' => ':count segundo|:count segundos',
'ago' => ':time atrás',
'from_now' => 'em :time',
'after' => ':time depois',
*/
return array(
- 'year' => '1 ano|:count anos',
- 'y' => '1 ano|:count anos',
- 'month' => '1 mês|:count meses',
- 'm' => '1 mês|:count meses',
- 'week' => '1 semana|:count semanas',
- 'w' => '1 semana|:count semanas',
- 'day' => '1 dia|:count dias',
- 'd' => '1 dia|:count dias',
- 'hour' => '1 hora|:count horas',
- 'h' => '1 hora|:count horas',
- 'minute' => '1 minuto|:count minutos',
- 'min' => '1 minuto|:count minutos',
- 'second' => '1 segundo|:count segundos',
- 's' => '1 segundo|:count segundos',
+ 'year' => ':count ano|:count anos',
+ 'y' => ':count ano|:count anos',
+ 'month' => ':count mês|:count meses',
+ 'm' => ':count mês|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'w' => ':count semana|:count semanas',
+ 'day' => ':count dia|:count dias',
+ 'd' => ':count dia|:count dias',
+ 'hour' => ':count hora|:count horas',
+ 'h' => ':count hora|:count horas',
+ 'minute' => ':count minuto|:count minutos',
+ 'min' => ':count minuto|:count minutos',
+ 'second' => ':count segundo|:count segundos',
+ 's' => ':count segundo|:count segundos',
'ago' => 'há :time',
'from_now' => 'em :time',
'after' => 'após :time',
's' => 'sekundu|:count sekundy|:count sekúnd',
'ago' => 'pred :time',
'from_now' => 'za :time',
- 'after' => ':time neskôr',
+ 'after' => 'o :time neskôr',
'before' => ':time predtým',
+ 'year_ago' => 'rokom|:count rokmi|:count rokmi',
+ 'month_ago' => 'mesiacom|:count mesiacmi|:count mesiacmi',
+ 'week_ago' => 'týždňom|:count týždňami|:count týždňami',
+ 'day_ago' => 'dňom|:count dňami|:count dňami',
+ 'hour_ago' => 'hodinou|:count hodinami|:count hodinami',
+ 'minute_ago' => 'minútou|:count minútami|:count minútami',
+ 'second_ago' => 'sekundou|:count sekundami|:count sekundami',
);
*/
return array(
- 'year' => '1 vit|:count vjet',
- 'y' => '1 vit|:count vjet',
- 'month' => '1 muaj|:count muaj',
- 'm' => '1 muaj|:count muaj',
- 'week' => '1 javë|:count javë',
- 'w' => '1 javë|:count javë',
- 'day' => '1 ditë|:count ditë',
- 'd' => '1 ditë|:count ditë',
- 'hour' => '1 orë|:count orë',
- 'h' => '1 orë|:count orë',
- 'minute' => '1 minutë|:count minuta',
- 'min' => '1 minutë|:count minuta',
- 'second' => '1 sekondë|:count sekonda',
- 's' => '1 sekondë|:count sekonda',
+ 'year' => ':count vit|:count vjet',
+ 'y' => ':count vit|:count vjet',
+ 'month' => ':count muaj|:count muaj',
+ 'm' => ':count muaj|:count muaj',
+ 'week' => ':count javë|:count javë',
+ 'w' => ':count javë|:count javë',
+ 'day' => ':count ditë|:count ditë',
+ 'd' => ':count ditë|:count ditë',
+ 'hour' => ':count orë|:count orë',
+ 'h' => ':count orë|:count orë',
+ 'minute' => ':count minutë|:count minuta',
+ 'min' => ':count minutë|:count minuta',
+ 'second' => ':count sekondë|:count sekonda',
+ 's' => ':count sekondë|:count sekonda',
'ago' => ':time më parë',
'from_now' => ':time nga tani',
'after' => ':time pas',
'from_now' => ':time od sada',
'after' => 'nakon :time',
'before' => 'pre :time',
+
+ 'year_from_now' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
+ 'year_ago' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
+
+ 'week_from_now' => '{1} :count nedelju|{2,3,4} :count nedelje|[5,Inf[ :count nedelja',
+ 'week_ago' => '{1} :count nedelju|{2,3,4} :count nedelje|[5,Inf[ :count nedelja',
);
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Carbon package.
+ *
+ * (c) Nikola Zeravcic <office@bytenet.rs>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[ :count година',
+ 'y' => ':count г.',
+ 'month' => '{1} :count месец|{2,3,4}:count месеца|[5,Inf[ :count месеци',
+ 'm' => ':count м.',
+ 'week' => '{1} :count недеља|{2,3,4}:count недеље|[5,Inf[ :count недеља',
+ 'w' => ':count нед.',
+ 'day' => '{1,21,31} :count дан|[2,Inf[ :count дана',
+ 'd' => ':count д.',
+ 'hour' => '{1,21} :count сат|{2,3,4,22,23,24}:count сата|[5,Inf[ :count сати',
+ 'h' => ':count ч.',
+ 'minute' => '{1,21,31,41,51} :count минут|[2,Inf[ :count минута',
+ 'min' => ':count мин.',
+ 'second' => '{1,21,31,41,51} :count секунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count секунде|[5,Inf[:count секунди',
+ 's' => ':count сек.',
+ 'ago' => 'пре :time',
+ 'from_now' => 'за :time',
+ 'after' => ':time након',
+ 'before' => ':time пре',
+
+ 'year_from_now' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година',
+ 'year_ago' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година',
+
+ 'week_from_now' => '{1} :count недељу|{2,3,4} :count недеље|[5,Inf[ :count недеља',
+ 'week_ago' => '{1} :count недељу|{2,3,4} :count недеље|[5,Inf[ :count недеља',
+
+);
* file that was distributed with this source code.
*/
-return array(
- 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count godine|[0,Inf[ :count godina',
- 'y' => ':count g.',
- 'month' => '{1} :count mjesec|{2,3,4}:count mjeseca|[5,Inf[ :count mjeseci',
- 'm' => ':count mj.',
- 'week' => '{1} :count nedjelja|{2,3,4}:count nedjelje|[5,Inf[ :count nedjelja',
- 'w' => ':count ned.',
- 'day' => '{1,21,31} :count dan|[2,Inf[ :count dana',
- 'd' => ':count d.',
- 'hour' => '{1,21} :count sat|{2,3,4,22,23,24}:count sata|[5,Inf[ :count sati',
- 'h' => ':count č.',
- 'minute' => '{1,21,31,41,51} :count minut|[2,Inf[ :count minuta',
- 'min' => ':count min.',
- 'second' => '{1,21,31,41,51} :count sekund|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count sekunde|[5,Inf[:count sekundi',
- 's' => ':count sek.',
- 'ago' => 'prije :time',
- 'from_now' => 'za :time',
- 'after' => ':time nakon',
- 'before' => ':time prije',
-
- 'year_from_now' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
- 'year_ago' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
-
- 'week_from_now' => '{1} :count nedjelju|{2,3,4} :count nedjelje|[5,Inf[ :count nedjelja',
- 'week_ago' => '{1} :count nedjelju|{2,3,4} :count nedjelje|[5,Inf[ :count nedjelja',
-
-);
+return require __DIR__.'/sr_Latn_ME.php';
*/
return array(
- 'year' => '1 år|:count år',
- 'y' => '1 år|:count år',
- 'month' => '1 månad|:count månader',
- 'm' => '1 månad|:count månader',
- 'week' => '1 vecka|:count veckor',
- 'w' => '1 vecka|:count veckor',
- 'day' => '1 dag|:count dagar',
- 'd' => '1 dag|:count dagar',
- 'hour' => '1 timme|:count timmar',
- 'h' => '1 timme|:count timmar',
- 'minute' => '1 minut|:count minuter',
- 'min' => '1 minut|:count minuter',
- 'second' => '1 sekund|:count sekunder',
- 's' => '1 sekund|:count sekunder',
+ 'year' => ':count år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count månad|:count månader',
+ 'm' => ':count månad|:count månader',
+ 'week' => ':count vecka|:count veckor',
+ 'w' => ':count vecka|:count veckor',
+ 'day' => ':count dag|:count dagar',
+ 'd' => ':count dag|:count dagar',
+ 'hour' => ':count timme|:count timmar',
+ 'h' => ':count timme|:count timmar',
+ 'minute' => ':count minut|:count minuter',
+ 'min' => ':count minut|:count minuter',
+ 'second' => ':count sekund|:count sekunder',
+ 's' => ':count sekund|:count sekunder',
'ago' => ':time sedan',
'from_now' => 'om :time',
'after' => ':time efter',
*/
return array(
- 'year' => '1 ปี|:count ปี',
- 'y' => '1 ปี|:count ปี',
- 'month' => '1 เดือน|:count เดือน',
- 'm' => '1 เดือน|:count เดือน',
- 'week' => '1 สัปดาห์|:count สัปดาห์',
- 'w' => '1 สัปดาห์|:count สัปดาห์',
- 'day' => '1 วัน|:count วัน',
- 'd' => '1 วัน|:count วัน',
- 'hour' => '1 ชั่วโมง|:count ชั่วโมง',
- 'h' => '1 ชั่วโมง|:count ชั่วโมง',
- 'minute' => '1 นาที|:count นาที',
- 'min' => '1 นาที|:count นาที',
- 'second' => '1 วินาที|:count วินาที',
- 's' => '1 วินาที|:count วินาที',
- 'ago' => ':time ที่แล้ว',
- 'from_now' => ':time จากนี้',
- 'after' => 'หลัง:time',
- 'before' => 'ก่อน:time',
+ 'year' => ':count ปี',
+ 'y' => ':count ปี',
+ 'month' => ':count เดือน',
+ 'm' => ':count เดือน',
+ 'week' => ':count สัปดาห์',
+ 'w' => ':count สัปดาห์',
+ 'day' => ':count วัน',
+ 'd' => ':count วัน',
+ 'hour' => ':count ชั่วโมง',
+ 'h' => ':count ชั่วโมง',
+ 'minute' => ':count นาที',
+ 'min' => ':count นาที',
+ 'second' => ':count วินาที',
+ 's' => ':count วินาที',
+ 'ago' => ':timeที่แล้ว',
+ 'from_now' => ':timeต่อจากนี้',
+ 'after' => ':timeหลังจากนี้',
+ 'before' => ':timeก่อน',
);
'min' => ':count хвилину|:count хвилини|:count хвилин',
'second' => ':count секунду|:count секунди|:count секунд',
's' => ':count секунду|:count секунди|:count секунд',
- 'ago' => ':time назад',
+ 'ago' => ':time тому',
'from_now' => 'через :time',
'after' => ':time після',
'before' => ':time до',
*/
return array(
- 'year' => ':count yil|:count yil|:count yil',
- 'y' => ':count yil|:count yil|:count yil',
- 'month' => ':count oy|:count oy|:count oylar',
- 'm' => ':count oy|:count oy|:count oylar',
- 'week' => ':count hafta|:count hafta|:count hafta',
- 'w' => ':count hafta|:count hafta|:count hafta',
- 'day' => ':count kun|:count kun|:count kun',
- 'd' => ':count kun|:count kun|:count kun',
- 'hour' => ':count soat|:count soat|:count soat',
- 'h' => ':count soat|:count soat|:count soat',
- 'minute' => ':count minut|:count minut|:count minut',
- 'min' => ':count minut|:count minut|:count minut',
- 'second' => ':count sekund|:count sekund|:count sekund',
- 's' => ':count sekund|:count sekund|:count sekund',
+ 'year' => ':count yil',
+ 'y' => ':count yil',
+ 'month' => ':count oy',
+ 'm' => ':count oy',
+ 'week' => ':count hafta',
+ 'w' => ':count hafta',
+ 'day' => ':count kun',
+ 'd' => ':count kun',
+ 'hour' => ':count soat',
+ 'h' => ':count soat',
+ 'minute' => ':count daqiqa',
+ 'min' => ':count daq',
+ 'second' => ':count soniya',
+ 's' => ':count s',
'ago' => ':time avval',
- 'from_now' => ':time keyin',
+ 'from_now' => ':time dan keyin',
'after' => ':time keyin',
'before' => ':time oldin',
);
*/
return array(
- 'year' => ':count 年',
- 'y' => ':count 年',
- 'month' => ':count 月',
- 'm' => ':count 月',
- 'week' => ':count 周',
- 'w' => ':count 周',
- 'day' => ':count 天',
- 'd' => ':count 天',
- 'hour' => ':count 小時',
- 'h' => ':count 小時',
- 'minute' => ':count 分鐘',
- 'min' => ':count 分鐘',
- 'second' => ':count 秒',
- 's' => ':count 秒',
+ 'year' => ':count年',
+ 'y' => ':count年',
+ 'month' => ':count月',
+ 'm' => ':count月',
+ 'week' => ':count週',
+ 'w' => ':count週',
+ 'day' => ':count天',
+ 'd' => ':count天',
+ 'hour' => ':count小時',
+ 'h' => ':count小時',
+ 'minute' => ':count分鐘',
+ 'min' => ':count分鐘',
+ 'second' => ':count秒',
+ 's' => ':count秒',
'ago' => ':time前',
- 'from_now' => '距現在 :time',
+ 'from_now' => '距現在:time',
'after' => ':time後',
'before' => ':time前',
);
--- /dev/null
+<?php
+
+namespace Carbon;
+
+use Symfony\Component\Translation;
+
+class Translator extends Translation\Translator
+{
+ /**
+ * Singleton for Translator.
+ *
+ * @var static
+ */
+ protected static $singleton;
+
+ /**
+ * List of custom localized messages.
+ *
+ * @var array
+ */
+ protected static $messages = array();
+
+ /**
+ * Return a singleton instance of Translator.
+ *
+ * @param string|null $locale optional initial locale ("en" - english by default)
+ *
+ * @return static
+ */
+ public static function get($locale = null)
+ {
+ if (static::$singleton === null) {
+ static::$singleton = new static($locale ?: 'en');
+ }
+
+ return static::$singleton;
+ }
+
+ public function __construct($locale, Translation\Formatter\MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false)
+ {
+ $this->addLoader('array', new Translation\Loader\ArrayLoader());
+ parent::__construct($locale, $formatter, $cacheDir, $debug);
+ }
+
+ /**
+ * Reset messages of a locale (all locale if no locale passed).
+ * Remove custom messages and reload initial messages from matching
+ * file in Lang directory.
+ *
+ * @param string|null $locale
+ *
+ * @return bool
+ */
+ public function resetMessages($locale = null)
+ {
+ if ($locale === null) {
+ static::$messages = array();
+
+ return true;
+ }
+
+ if (file_exists($filename = __DIR__.'/Lang/'.$locale.'.php')) {
+ static::$messages[$locale] = require $filename;
+ $this->addResource('array', static::$messages[$locale], $locale);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Init messages language from matching file in Lang directory.
+ *
+ * @param string $locale
+ *
+ * @return bool
+ */
+ protected function loadMessagesFromFile($locale)
+ {
+ if (isset(static::$messages[$locale])) {
+ return true;
+ }
+
+ return $this->resetMessages($locale);
+ }
+
+ /**
+ * Set messages of a locale and take file first if present.
+ *
+ * @param string $locale
+ * @param array $messages
+ *
+ * @return $this
+ */
+ public function setMessages($locale, $messages)
+ {
+ $this->loadMessagesFromFile($locale);
+ $this->addResource('array', $messages, $locale);
+ static::$messages[$locale] = array_merge(
+ isset(static::$messages[$locale]) ? static::$messages[$locale] : array(),
+ $messages
+ );
+
+ return $this;
+ }
+
+ /**
+ * Get messages of a locale, if none given, return all the
+ * languages.
+ *
+ * @param string|null $locale
+ *
+ * @return array
+ */
+ public function getMessages($locale = null)
+ {
+ return $locale === null ? static::$messages : static::$messages[$locale];
+ }
+
+ /**
+ * Set the current translator locale and indicate if the source locale file exists
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public function setLocale($locale)
+ {
+ $locale = preg_replace_callback('/[-_]([a-z]{2,})/', function ($matches) {
+ // _2-letters is a region, _3+-letters is a variant
+ return '_'.call_user_func(strlen($matches[1]) > 2 ? 'ucfirst' : 'strtoupper', $matches[1]);
+ }, strtolower($locale));
+
+ if ($this->loadMessagesFromFile($locale)) {
+ parent::setLocale($locale);
+
+ return true;
+ }
+
+ return false;
+ }
+}
--- /dev/null
+<?php
+
+interface JsonSerializable
+{
+ /**
+ * Specify data which should be serialized to JSON.
+ *
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ *
+ * @return mixed data which can be serialized by <b>json_encode</b>,
+ * which is a value of any type other than a resource.
+ *
+ * @since 5.4.0
+ */
+ public function jsonSerialize();
+}
+++ /dev/null
-The MIT License (MIT)
-
-Copyright (c) 2015 Paragon Initiative Enterprises
-
-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.
-
+++ /dev/null
-#!/usr/bin/env bash
-
-basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) )
-
-php -dphar.readonly=0 "$basedir/other/build_phar.php" $*
\ No newline at end of file
+++ /dev/null
-{
- "name": "paragonie/random_compat",
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
- "keywords": [
- "csprng",
- "random",
- "pseudorandom"
- ],
- "license": "MIT",
- "type": "library",
- "authors": [
- {
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
- }
- ],
- "support": {
- "issues": "https://github.com/paragonie/random_compat/issues",
- "email": "info@paragonie.com",
- "source": "https://github.com/paragonie/random_compat"
- },
- "require": {
- "php": ">=5.2.0"
- },
- "require-dev": {
- "phpunit/phpunit": "4.*|5.*"
- },
- "suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
- },
- "autoload": {
- "files": [
- "lib/random.php"
- ]
- }
-}
+++ /dev/null
------BEGIN PUBLIC KEY-----
-MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm
-pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p
-+h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc
------END PUBLIC KEY-----
+++ /dev/null
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v2.0.22 (MingW32)
-
-iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip
-QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg
-1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW
-NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA
-NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV
-JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74=
-=B6+8
------END PGP SIGNATURE-----
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!is_callable('RandomCompat_strlen')) {
- if (
- defined('MB_OVERLOAD_STRING') &&
- ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
- ) {
- /**
- * strlen() implementation that isn't brittle to mbstring.func_overload
- *
- * This version uses mb_strlen() in '8bit' mode to treat strings as raw
- * binary rather than UTF-8, ISO-8859-1, etc
- *
- * @param string $binary_string
- *
- * @throws TypeError
- *
- * @return int
- */
- function RandomCompat_strlen($binary_string)
- {
- if (!is_string($binary_string)) {
- throw new TypeError(
- 'RandomCompat_strlen() expects a string'
- );
- }
-
- return (int) mb_strlen($binary_string, '8bit');
- }
-
- } else {
- /**
- * strlen() implementation that isn't brittle to mbstring.func_overload
- *
- * This version just used the default strlen()
- *
- * @param string $binary_string
- *
- * @throws TypeError
- *
- * @return int
- */
- function RandomCompat_strlen($binary_string)
- {
- if (!is_string($binary_string)) {
- throw new TypeError(
- 'RandomCompat_strlen() expects a string'
- );
- }
- return (int) strlen($binary_string);
- }
- }
-}
-
-if (!is_callable('RandomCompat_substr')) {
-
- if (
- defined('MB_OVERLOAD_STRING')
- &&
- ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
- ) {
- /**
- * substr() implementation that isn't brittle to mbstring.func_overload
- *
- * This version uses mb_substr() in '8bit' mode to treat strings as raw
- * binary rather than UTF-8, ISO-8859-1, etc
- *
- * @param string $binary_string
- * @param int $start
- * @param int $length (optional)
- *
- * @throws TypeError
- *
- * @return string
- */
- function RandomCompat_substr($binary_string, $start, $length = null)
- {
- if (!is_string($binary_string)) {
- throw new TypeError(
- 'RandomCompat_substr(): First argument should be a string'
- );
- }
-
- if (!is_int($start)) {
- throw new TypeError(
- 'RandomCompat_substr(): Second argument should be an integer'
- );
- }
-
- if ($length === null) {
- /**
- * mb_substr($str, 0, NULL, '8bit') returns an empty string on
- * PHP 5.3, so we have to find the length ourselves.
- */
- $length = RandomCompat_strlen($binary_string) - $start;
- } elseif (!is_int($length)) {
- throw new TypeError(
- 'RandomCompat_substr(): Third argument should be an integer, or omitted'
- );
- }
-
- // Consistency with PHP's behavior
- if ($start === RandomCompat_strlen($binary_string) && $length === 0) {
- return '';
- }
- if ($start > RandomCompat_strlen($binary_string)) {
- return '';
- }
-
- return (string) mb_substr($binary_string, $start, $length, '8bit');
- }
-
- } else {
-
- /**
- * substr() implementation that isn't brittle to mbstring.func_overload
- *
- * This version just uses the default substr()
- *
- * @param string $binary_string
- * @param int $start
- * @param int $length (optional)
- *
- * @throws TypeError
- *
- * @return string
- */
- function RandomCompat_substr($binary_string, $start, $length = null)
- {
- if (!is_string($binary_string)) {
- throw new TypeError(
- 'RandomCompat_substr(): First argument should be a string'
- );
- }
-
- if (!is_int($start)) {
- throw new TypeError(
- 'RandomCompat_substr(): Second argument should be an integer'
- );
- }
-
- if ($length !== null) {
- if (!is_int($length)) {
- throw new TypeError(
- 'RandomCompat_substr(): Third argument should be an integer, or omitted'
- );
- }
-
- return (string) substr($binary_string, $start, $length);
- }
-
- return (string) substr($binary_string, $start);
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!is_callable('RandomCompat_intval')) {
-
- /**
- * Cast to an integer if we can, safely.
- *
- * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
- * (non-inclusive), it will sanely cast it to an int. If you it's equal to
- * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
- * lose precision, so the <= and => operators might accidentally let a float
- * through.
- *
- * @param int|float $number The number we want to convert to an int
- * @param boolean $fail_open Set to true to not throw an exception
- *
- * @return float|int
- *
- * @throws TypeError
- */
- function RandomCompat_intval($number, $fail_open = false)
- {
- if (is_int($number) || is_float($number)) {
- $number += 0;
- } elseif (is_numeric($number)) {
- $number += 0;
- }
-
- if (
- is_float($number)
- &&
- $number > ~PHP_INT_MAX
- &&
- $number < PHP_INT_MAX
- ) {
- $number = (int) $number;
- }
-
- if (is_int($number)) {
- return (int) $number;
- } elseif (!$fail_open) {
- throw new TypeError(
- 'Expected an integer.'
- );
- }
- return $number;
- }
-}
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!class_exists('Error', false)) {
- // We can't really avoid making this extend Exception in PHP 5.
- class Error extends Exception
- {
-
- }
-}
-
-if (!class_exists('TypeError', false)) {
- if (is_subclass_of('Error', 'Exception')) {
- class TypeError extends Error
- {
-
- }
- } else {
- class TypeError extends Exception
- {
-
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * @version 2.0.10
- * @released 2017-03-13
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!defined('PHP_VERSION_ID')) {
- // This constant was introduced in PHP 5.2.7
- $RandomCompatversion = array_map('intval', explode('.', PHP_VERSION));
- define(
- 'PHP_VERSION_ID',
- $RandomCompatversion[0] * 10000
- + $RandomCompatversion[1] * 100
- + $RandomCompatversion[2]
- );
- $RandomCompatversion = null;
-}
-
-/**
- * PHP 7.0.0 and newer have these functions natively.
- */
-if (PHP_VERSION_ID >= 70000) {
- return;
-}
-
-if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
- define('RANDOM_COMPAT_READ_BUFFER', 8);
-}
-
-$RandomCompatDIR = dirname(__FILE__);
-
-require_once $RandomCompatDIR . '/byte_safe_strings.php';
-require_once $RandomCompatDIR . '/cast_to_int.php';
-require_once $RandomCompatDIR . '/error_polyfill.php';
-
-if (!is_callable('random_bytes')) {
- /**
- * PHP 5.2.0 - 5.6.x way to implement random_bytes()
- *
- * We use conditional statements here to define the function in accordance
- * to the operating environment. It's a micro-optimization.
- *
- * In order of preference:
- * 1. Use libsodium if available.
- * 2. fread() /dev/urandom if available (never on Windows)
- * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
- * 4. COM('CAPICOM.Utilities.1')->GetRandom()
- *
- * See RATIONALE.md for our reasoning behind this particular order
- */
- if (extension_loaded('libsodium')) {
- // See random_bytes_libsodium.php
- if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
- require_once $RandomCompatDIR . '/random_bytes_libsodium.php';
- } elseif (method_exists('Sodium', 'randombytes_buf')) {
- require_once $RandomCompatDIR . '/random_bytes_libsodium_legacy.php';
- }
- }
-
- /**
- * Reading directly from /dev/urandom:
- */
- if (DIRECTORY_SEPARATOR === '/') {
- // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
- // way to exclude Windows.
- $RandomCompatUrandom = true;
- $RandomCompat_basedir = ini_get('open_basedir');
-
- if (!empty($RandomCompat_basedir)) {
- $RandomCompat_open_basedir = explode(
- PATH_SEPARATOR,
- strtolower($RandomCompat_basedir)
- );
- $RandomCompatUrandom = (array() !== array_intersect(
- array('/dev', '/dev/', '/dev/urandom'),
- $RandomCompat_open_basedir
- ));
- $RandomCompat_open_basedir = null;
- }
-
- if (
- !is_callable('random_bytes')
- &&
- $RandomCompatUrandom
- &&
- @is_readable('/dev/urandom')
- ) {
- // Error suppression on is_readable() in case of an open_basedir
- // or safe_mode failure. All we care about is whether or not we
- // can read it at this point. If the PHP environment is going to
- // panic over trying to see if the file can be read in the first
- // place, that is not helpful to us here.
-
- // See random_bytes_dev_urandom.php
- require_once $RandomCompatDIR . '/random_bytes_dev_urandom.php';
- }
- // Unset variables after use
- $RandomCompat_basedir = null;
- } else {
- $RandomCompatUrandom = false;
- }
-
- /**
- * mcrypt_create_iv()
- *
- * We only want to use mcypt_create_iv() if:
- *
- * - random_bytes() hasn't already been defined
- * - the mcrypt extensions is loaded
- * - One of these two conditions is true:
- * - We're on Windows (DIRECTORY_SEPARATOR !== '/')
- * - We're not on Windows and /dev/urandom is readabale
- * (i.e. we're not in a chroot jail)
- * - Special case:
- * - If we're not on Windows, but the PHP version is between
- * 5.6.10 and 5.6.12, we don't want to use mcrypt. It will
- * hang indefinitely. This is bad.
- * - If we're on Windows, we want to use PHP >= 5.3.7 or else
- * we get insufficient entropy errors.
- */
- if (
- !is_callable('random_bytes')
- &&
- // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be.
- (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307)
- &&
- // Prevent this code from hanging indefinitely on non-Windows;
- // see https://bugs.php.net/bug.php?id=69833
- (
- DIRECTORY_SEPARATOR !== '/' ||
- (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
- )
- &&
- extension_loaded('mcrypt')
- ) {
- // See random_bytes_mcrypt.php
- require_once $RandomCompatDIR . '/random_bytes_mcrypt.php';
- }
- $RandomCompatUrandom = null;
-
- /**
- * This is a Windows-specific fallback, for when the mcrypt extension
- * isn't loaded.
- */
- if (
- !is_callable('random_bytes')
- &&
- extension_loaded('com_dotnet')
- &&
- class_exists('COM')
- ) {
- $RandomCompat_disabled_classes = preg_split(
- '#\s*,\s*#',
- strtolower(ini_get('disable_classes'))
- );
-
- if (!in_array('com', $RandomCompat_disabled_classes)) {
- try {
- $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
- if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
- // See random_bytes_com_dotnet.php
- require_once $RandomCompatDIR . '/random_bytes_com_dotnet.php';
- }
- } catch (com_exception $e) {
- // Don't try to use it.
- }
- }
- $RandomCompat_disabled_classes = null;
- $RandomCompatCOMtest = null;
- }
-
- /**
- * throw new Exception
- */
- if (!is_callable('random_bytes')) {
- /**
- * We don't have any more options, so let's throw an exception right now
- * and hope the developer won't let it fail silently.
- *
- * @param mixed $length
- * @return void
- * @throws Exception
- */
- function random_bytes($length)
- {
- unset($length); // Suppress "variable not used" warnings.
- throw new Exception(
- 'There is no suitable CSPRNG installed on your system'
- );
- }
- }
-}
-
-if (!is_callable('random_int')) {
- require_once $RandomCompatDIR . '/random_int.php';
-}
-
-$RandomCompatDIR = null;
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!is_callable('random_bytes')) {
- /**
- * Windows with PHP < 5.3.0 will not have the function
- * openssl_random_pseudo_bytes() available, so let's use
- * CAPICOM to work around this deficiency.
- *
- * @param int $bytes
- *
- * @throws Exception
- *
- * @return string
- */
- function random_bytes($bytes)
- {
- try {
- $bytes = RandomCompat_intval($bytes);
- } catch (TypeError $ex) {
- throw new TypeError(
- 'random_bytes(): $bytes must be an integer'
- );
- }
-
- if ($bytes < 1) {
- throw new Error(
- 'Length must be greater than 0'
- );
- }
-
- $buf = '';
- if (!class_exists('COM')) {
- throw new Error(
- 'COM does not exist'
- );
- }
- $util = new COM('CAPICOM.Utilities.1');
- $execCount = 0;
-
- /**
- * Let's not let it loop forever. If we run N times and fail to
- * get N bytes of random data, then CAPICOM has failed us.
- */
- do {
- $buf .= base64_decode($util->GetRandom($bytes, 0));
- if (RandomCompat_strlen($buf) >= $bytes) {
- /**
- * Return our random entropy buffer here:
- */
- return RandomCompat_substr($buf, 0, $bytes);
- }
- ++$execCount;
- } while ($execCount < $bytes);
-
- /**
- * If we reach here, PHP has failed us.
- */
- throw new Exception(
- 'Could not gather sufficient random data'
- );
- }
-}
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
- define('RANDOM_COMPAT_READ_BUFFER', 8);
-}
-
-if (!is_callable('random_bytes')) {
- /**
- * Unless open_basedir is enabled, use /dev/urandom for
- * random numbers in accordance with best practices
- *
- * Why we use /dev/urandom and not /dev/random
- * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers
- *
- * @param int $bytes
- *
- * @throws Exception
- *
- * @return string
- */
- function random_bytes($bytes)
- {
- static $fp = null;
- /**
- * This block should only be run once
- */
- if (empty($fp)) {
- /**
- * We use /dev/urandom if it is a char device.
- * We never fall back to /dev/random
- */
- $fp = fopen('/dev/urandom', 'rb');
- if (!empty($fp)) {
- $st = fstat($fp);
- if (($st['mode'] & 0170000) !== 020000) {
- fclose($fp);
- $fp = false;
- }
- }
-
- if (!empty($fp)) {
- /**
- * stream_set_read_buffer() does not exist in HHVM
- *
- * If we don't set the stream's read buffer to 0, PHP will
- * internally buffer 8192 bytes, which can waste entropy
- *
- * stream_set_read_buffer returns 0 on success
- */
- if (is_callable('stream_set_read_buffer')) {
- stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER);
- }
- if (is_callable('stream_set_chunk_size')) {
- stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER);
- }
- }
- }
-
- try {
- $bytes = RandomCompat_intval($bytes);
- } catch (TypeError $ex) {
- throw new TypeError(
- 'random_bytes(): $bytes must be an integer'
- );
- }
-
- if ($bytes < 1) {
- throw new Error(
- 'Length must be greater than 0'
- );
- }
-
- /**
- * This if() block only runs if we managed to open a file handle
- *
- * It does not belong in an else {} block, because the above
- * if (empty($fp)) line is logic that should only be run once per
- * page load.
- */
- if (!empty($fp)) {
- /**
- * @var int
- */
- $remaining = $bytes;
-
- /**
- * @var string|bool
- */
- $buf = '';
-
- /**
- * We use fread() in a loop to protect against partial reads
- */
- do {
- /**
- * @var string|bool
- */
- $read = fread($fp, $remaining);
- if (!is_string($read)) {
- if ($read === false) {
- /**
- * We cannot safely read from the file. Exit the
- * do-while loop and trigger the exception condition
- *
- * @var string|bool
- */
- $buf = false;
- break;
- }
- }
- /**
- * Decrease the number of bytes returned from remaining
- */
- $remaining -= RandomCompat_strlen($read);
- /**
- * @var string|bool
- */
- $buf = $buf . $read;
- } while ($remaining > 0);
-
- /**
- * Is our result valid?
- */
- if (is_string($buf)) {
- if (RandomCompat_strlen($buf) === $bytes) {
- /**
- * Return our random entropy buffer here:
- */
- return $buf;
- }
- }
- }
-
- /**
- * If we reach here, PHP has failed us.
- */
- throw new Exception(
- 'Error reading from source device'
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!is_callable('random_bytes')) {
- /**
- * If the libsodium PHP extension is loaded, we'll use it above any other
- * solution.
- *
- * libsodium-php project:
- * @ref https://github.com/jedisct1/libsodium-php
- *
- * @param int $bytes
- *
- * @throws Exception
- *
- * @return string
- */
- function random_bytes($bytes)
- {
- try {
- $bytes = RandomCompat_intval($bytes);
- } catch (TypeError $ex) {
- throw new TypeError(
- 'random_bytes(): $bytes must be an integer'
- );
- }
-
- if ($bytes < 1) {
- throw new Error(
- 'Length must be greater than 0'
- );
- }
-
- /**
- * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
- * generated in one invocation.
- */
- if ($bytes > 2147483647) {
- $buf = '';
- for ($i = 0; $i < $bytes; $i += 1073741824) {
- $n = ($bytes - $i) > 1073741824
- ? 1073741824
- : $bytes - $i;
- $buf .= \Sodium\randombytes_buf($n);
- }
- } else {
- $buf = \Sodium\randombytes_buf($bytes);
- }
-
- if ($buf !== false) {
- if (RandomCompat_strlen($buf) === $bytes) {
- return $buf;
- }
- }
-
- /**
- * If we reach here, PHP has failed us.
- */
- throw new Exception(
- 'Could not gather sufficient random data'
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!is_callable('random_bytes')) {
- /**
- * If the libsodium PHP extension is loaded, we'll use it above any other
- * solution.
- *
- * libsodium-php project:
- * @ref https://github.com/jedisct1/libsodium-php
- *
- * @param int $bytes
- *
- * @throws Exception
- *
- * @return string
- */
- function random_bytes($bytes)
- {
- try {
- $bytes = RandomCompat_intval($bytes);
- } catch (TypeError $ex) {
- throw new TypeError(
- 'random_bytes(): $bytes must be an integer'
- );
- }
-
- if ($bytes < 1) {
- throw new Error(
- 'Length must be greater than 0'
- );
- }
-
- /**
- * @var string
- */
- $buf = '';
-
- /**
- * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
- * generated in one invocation.
- */
- if ($bytes > 2147483647) {
- for ($i = 0; $i < $bytes; $i += 1073741824) {
- $n = ($bytes - $i) > 1073741824
- ? 1073741824
- : $bytes - $i;
- $buf .= Sodium::randombytes_buf($n);
- }
- } else {
- $buf .= Sodium::randombytes_buf($bytes);
- }
-
- if (is_string($buf)) {
- if (RandomCompat_strlen($buf) === $bytes) {
- return $buf;
- }
- }
-
- /**
- * If we reach here, PHP has failed us.
- */
- throw new Exception(
- 'Could not gather sufficient random data'
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
-if (!is_callable('random_bytes')) {
- /**
- * Powered by ext/mcrypt (and thankfully NOT libmcrypt)
- *
- * @ref https://bugs.php.net/bug.php?id=55169
- * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386
- *
- * @param int $bytes
- *
- * @throws Exception
- *
- * @return string
- */
- function random_bytes($bytes)
- {
- try {
- $bytes = RandomCompat_intval($bytes);
- } catch (TypeError $ex) {
- throw new TypeError(
- 'random_bytes(): $bytes must be an integer'
- );
- }
-
- if ($bytes < 1) {
- throw new Error(
- 'Length must be greater than 0'
- );
- }
-
- $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
- if (
- $buf !== false
- &&
- RandomCompat_strlen($buf) === $bytes
- ) {
- /**
- * Return our random entropy buffer here:
- */
- return $buf;
- }
-
- /**
- * If we reach here, PHP has failed us.
- */
- throw new Exception(
- 'Could not gather sufficient random data'
- );
- }
-}
+++ /dev/null
-<?php
-
-if (!is_callable('random_int')) {
- /**
- * Random_* Compatibility Library
- * for using the new PHP 7 random_* API in PHP 5 projects
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
- *
- * 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.
- */
-
- /**
- * Fetch a random integer between $min and $max inclusive
- *
- * @param int $min
- * @param int $max
- *
- * @throws Exception
- *
- * @return int
- */
- function random_int($min, $max)
- {
- /**
- * Type and input logic checks
- *
- * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
- * (non-inclusive), it will sanely cast it to an int. If you it's equal to
- * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
- * lose precision, so the <= and => operators might accidentally let a float
- * through.
- */
-
- try {
- $min = RandomCompat_intval($min);
- } catch (TypeError $ex) {
- throw new TypeError(
- 'random_int(): $min must be an integer'
- );
- }
-
- try {
- $max = RandomCompat_intval($max);
- } catch (TypeError $ex) {
- throw new TypeError(
- 'random_int(): $max must be an integer'
- );
- }
-
- /**
- * Now that we've verified our weak typing system has given us an integer,
- * let's validate the logic then we can move forward with generating random
- * integers along a given range.
- */
- if ($min > $max) {
- throw new Error(
- 'Minimum value must be less than or equal to the maximum value'
- );
- }
-
- if ($max === $min) {
- return $min;
- }
-
- /**
- * Initialize variables to 0
- *
- * We want to store:
- * $bytes => the number of random bytes we need
- * $mask => an integer bitmask (for use with the &) operator
- * so we can minimize the number of discards
- */
- $attempts = $bits = $bytes = $mask = $valueShift = 0;
-
- /**
- * At this point, $range is a positive number greater than 0. It might
- * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
- * a float and we will lose some precision.
- */
- $range = $max - $min;
-
- /**
- * Test for integer overflow:
- */
- if (!is_int($range)) {
-
- /**
- * Still safely calculate wider ranges.
- * Provided by @CodesInChaos, @oittaa
- *
- * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
- *
- * We use ~0 as a mask in this case because it generates all 1s
- *
- * @ref https://eval.in/400356 (32-bit)
- * @ref http://3v4l.org/XX9r5 (64-bit)
- */
- $bytes = PHP_INT_SIZE;
- $mask = ~0;
-
- } else {
-
- /**
- * $bits is effectively ceil(log($range, 2)) without dealing with
- * type juggling
- */
- while ($range > 0) {
- if ($bits % 8 === 0) {
- ++$bytes;
- }
- ++$bits;
- $range >>= 1;
- $mask = $mask << 1 | 1;
- }
- $valueShift = $min;
- }
-
- $val = 0;
- /**
- * Now that we have our parameters set up, let's begin generating
- * random integers until one falls between $min and $max
- */
- do {
- /**
- * The rejection probability is at most 0.5, so this corresponds
- * to a failure probability of 2^-128 for a working RNG
- */
- if ($attempts > 128) {
- throw new Exception(
- 'random_int: RNG is broken - too many rejections'
- );
- }
-
- /**
- * Let's grab the necessary number of random bytes
- */
- $randomByteString = random_bytes($bytes);
-
- /**
- * Let's turn $randomByteString into an integer
- *
- * This uses bitwise operators (<< and |) to build an integer
- * out of the values extracted from ord()
- *
- * Example: [9F] | [6D] | [32] | [0C] =>
- * 159 + 27904 + 3276800 + 201326592 =>
- * 204631455
- */
- $val &= 0;
- for ($i = 0; $i < $bytes; ++$i) {
- $val |= ord($randomByteString[$i]) << ($i * 8);
- }
-
- /**
- * Apply mask
- */
- $val &= $mask;
- $val += $valueShift;
-
- ++$attempts;
- /**
- * If $val overflows to a floating point number,
- * ... or is larger than $max,
- * ... or smaller than $min,
- * then try again.
- */
- } while (!is_int($val) || $val > $max || $val < $min);
-
- return (int)$val;
- }
-}
+++ /dev/null
-<?php
-$dist = dirname(__DIR__).'/dist';
-if (!is_dir($dist)) {
- mkdir($dist, 0755);
-}
-if (file_exists($dist.'/random_compat.phar')) {
- unlink($dist.'/random_compat.phar');
-}
-$phar = new Phar(
- $dist.'/random_compat.phar',
- FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME,
- 'random_compat.phar'
-);
-rename(
- dirname(__DIR__).'/lib/random.php',
- dirname(__DIR__).'/lib/index.php'
-);
-$phar->buildFromDirectory(dirname(__DIR__).'/lib');
-rename(
- dirname(__DIR__).'/lib/index.php',
- dirname(__DIR__).'/lib/random.php'
-);
-
-/**
- * If we pass an (optional) path to a private key as a second argument, we will
- * sign the Phar with OpenSSL.
- *
- * If you leave this out, it will produce an unsigned .phar!
- */
-if ($argc > 1) {
- if (!@is_readable($argv[1])) {
- echo 'Could not read the private key file:', $argv[1], "\n";
- exit(255);
- }
- $pkeyFile = file_get_contents($argv[1]);
-
- $private = openssl_get_privatekey($pkeyFile);
- if ($private !== false) {
- $pkey = '';
- openssl_pkey_export($private, $pkey);
- $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
-
- /**
- * Save the corresponding public key to the file
- */
- if (!@is_readable($dist.'/random_compat.phar.pubkey')) {
- $details = openssl_pkey_get_details($private);
- file_put_contents(
- $dist.'/random_compat.phar.pubkey',
- $details['key']
- );
- }
- } else {
- echo 'An error occurred reading the private key from OpenSSL.', "\n";
- exit(255);
- }
-}
+++ /dev/null
-<?php
-
-require_once 'lib/byte_safe_strings.php';
-require_once 'lib/cast_to_int.php';
-require_once 'lib/error_polyfill.php';
-require_once 'other/ide_stubs/libsodium.php';
-require_once 'lib/random.php';
-
-$int = random_int(0, 65536);
+++ /dev/null
-<?xml version="1.0"?>
-<psalm
- autoloader="psalm-autoload.php"
- stopOnFirstError="false"
- useDocblockTypes="true"
->
- <projectFiles>
- <directory name="lib" />
- </projectFiles>
- <issueHandlers>
- <InvalidOperand errorLevel="info" />
- <UndefinedConstant errorLevel="info" />
- <MissingReturnType errorLevel="info" />
- </issueHandlers>
-</psalm>
--- /dev/null
+composer.lock
+composer.phar
+/vendor/
--- /dev/null
+The MIT License (MIT)
+
+Copyright (c) 2013-2016 container-interop
+Copyright (c) 2016 PHP Framework Interoperability Group
+
+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.
--- /dev/null
+# PSR Container
+
+This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md).
+
+Note that this is not a container implementation of its own. See the specification for more details.
--- /dev/null
+{
+ "name": "psr/container",
+ "type": "library",
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
+ "homepage": "https://github.com/php-fig/container",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Psr\Container;
+
+/**
+ * Base interface representing a generic exception in a container.
+ */
+interface ContainerExceptionInterface
+{
+}
--- /dev/null
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Psr\Container;
+
+/**
+ * Describes the interface of a container that exposes methods to read its entries.
+ */
+interface ContainerInterface
+{
+ /**
+ * Finds an entry of the container by its identifier and returns it.
+ *
+ * @param string $id Identifier of the entry to look for.
+ *
+ * @throws NotFoundExceptionInterface No entry was found for **this** identifier.
+ * @throws ContainerExceptionInterface Error while retrieving the entry.
+ *
+ * @return mixed Entry.
+ */
+ public function get($id);
+
+ /**
+ * Returns true if the container can return an entry for the given identifier.
+ * Returns false otherwise.
+ *
+ * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
+ * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
+ *
+ * @param string $id Identifier of the entry to look for.
+ *
+ * @return bool
+ */
+ public function has($id);
+}
--- /dev/null
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Psr\Container;
+
+/**
+ * No entry was found in the container.
+ */
+interface NotFoundExceptionInterface extends ContainerExceptionInterface
+{
+}
--- /dev/null
+; This file is for unifying the coding style for different editors and IDEs.
+; More information at http://editorconfig.org
+
+root = true
+
+[*]
+charset = utf-8
+indent_size = 4
+indent_style = space
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
--- /dev/null
+# The MIT License (MIT)
+
+Copyright (c) 2016 PHP Framework Interoperability Group
+
+> 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.
--- /dev/null
+PHP FIG Simple Cache PSR
+========================
+
+This repository holds all interfaces related to PSR-16.
+
+Note that this is not a cache implementation of its own. It is merely an interface that describes a cache implementation. See [the specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md) for more details.
+
+You can find implementations of the specification by looking for packages providing the [psr/simple-cache-implementation](https://packagist.org/providers/psr/simple-cache-implementation) virtual package.
--- /dev/null
+{
+ "name": "psr/simple-cache",
+ "description": "Common interfaces for simple caching",
+ "keywords": ["psr", "psr-16", "cache", "simple-cache", "caching"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
--- /dev/null
+<?php
+
+namespace Psr\SimpleCache;
+
+/**
+ * Interface used for all types of exceptions thrown by the implementing library.
+ */
+interface CacheException
+{
+}
--- /dev/null
+<?php
+
+namespace Psr\SimpleCache;
+
+interface CacheInterface
+{
+ /**
+ * Fetches a value from the cache.
+ *
+ * @param string $key The unique key of this item in the cache.
+ * @param mixed $default Default value to return if the key does not exist.
+ *
+ * @return mixed The value of the item from the cache, or $default in case of cache miss.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function get($key, $default = null);
+
+ /**
+ * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
+ *
+ * @param string $key The key of the item to store.
+ * @param mixed $value The value of the item to store, must be serializable.
+ * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and
+ * the driver supports TTL then the library may set a default value
+ * for it or let the driver take care of that.
+ *
+ * @return bool True on success and false on failure.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function set($key, $value, $ttl = null);
+
+ /**
+ * Delete an item from the cache by its unique key.
+ *
+ * @param string $key The unique cache key of the item to delete.
+ *
+ * @return bool True if the item was successfully removed. False if there was an error.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function delete($key);
+
+ /**
+ * Wipes clean the entire cache's keys.
+ *
+ * @return bool True on success and false on failure.
+ */
+ public function clear();
+
+ /**
+ * Obtains multiple cache items by their unique keys.
+ *
+ * @param iterable $keys A list of keys that can obtained in a single operation.
+ * @param mixed $default Default value to return for keys that do not exist.
+ *
+ * @return iterable A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if $keys is neither an array nor a Traversable,
+ * or if any of the $keys are not a legal value.
+ */
+ public function getMultiple($keys, $default = null);
+
+ /**
+ * Persists a set of key => value pairs in the cache, with an optional TTL.
+ *
+ * @param iterable $values A list of key => value pairs for a multiple-set operation.
+ * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and
+ * the driver supports TTL then the library may set a default value
+ * for it or let the driver take care of that.
+ *
+ * @return bool True on success and false on failure.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if $values is neither an array nor a Traversable,
+ * or if any of the $values are not a legal value.
+ */
+ public function setMultiple($values, $ttl = null);
+
+ /**
+ * Deletes multiple cache items in a single operation.
+ *
+ * @param iterable $keys A list of string-based keys to be deleted.
+ *
+ * @return bool True if the items were successfully removed. False if there was an error.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if $keys is neither an array nor a Traversable,
+ * or if any of the $keys are not a legal value.
+ */
+ public function deleteMultiple($keys);
+
+ /**
+ * Determines whether an item is present in the cache.
+ *
+ * NOTE: It is recommended that has() is only to be used for cache warming type purposes
+ * and not to be used within your live applications operations for get/set, as this method
+ * is subject to a race condition where your has() will return true and immediately after,
+ * another script can remove it making the state of your app out of date.
+ *
+ * @param string $key The cache item key.
+ *
+ * @return bool
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function has($key);
+}
--- /dev/null
+<?php
+
+namespace Psr\SimpleCache;
+
+/**
+ * Exception interface for invalid cache arguments.
+ *
+ * When an invalid argument is passed it must throw an exception which implements
+ * this interface
+ */
+interface InvalidArgumentException extends CacheException
+{
+}
dist: trusty
php:
- 7.1
- - 7.0
- nightly
matrix:
--- /dev/null
+Copyright (c) Roots
+
+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.
--- /dev/null
+# Sage Installer
+[](https://packagist.org/packages/roots/sage-installer)
+[](https://travis-ci.org/roots/sage-installer)
+
+This repository contains the installation scripts for the [Sage starter theme](https://github.com/roots/sage).
+
+## Contributing
+
+Contributions are welcome from everyone. We have [contributing guidelines](https://github.com/roots/guidelines/blob/master/CONTRIBUTING.md) to help you get started.
+
+## Community
+
+Keep track of development and community news.
+
+* Participate on the [Roots Discourse](https://discourse.roots.io/)
+* Follow [@rootswp on Twitter](https://twitter.com/rootswp)
+* Read and subscribe to the [Roots Blog](https://roots.io/blog/)
+* Subscribe to the [Roots Newsletter](https://roots.io/subscribe/)
+* Listen to the [Roots Radio podcast](https://roots.io/podcast/)
{
"name": "roots/sage-installer",
- "description": "Sage installer.",
+ "description": "Sage starter theme installer",
"keywords": [
"sage",
"wordpress",
"theme",
"foundation",
"bootstrap",
- "tachyons",
- "fontawesome"
+ "tachyons"
],
"license": "MIT",
"authors": [
}
},
"require": {
- "illuminate/console": "~5.4",
- "illuminate/filesystem": "~5.4",
+ "illuminate/console": "~5.6",
+ "illuminate/filesystem": "~5.6",
"symfony/process": "~3.3"
},
"require-dev": {
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "830bbdac04a250b72790f759bf898bb3",
+ "content-hash": "bf7009886d0c045b1491c1910010330b",
"packages": [
{
"name": "doctrine/inflector",
- "version": "v1.2.0",
+ "version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462"
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a",
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^6.2"
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2.x-dev"
+ "dev-master": "1.3.x-dev"
}
},
"autoload": {
"singularize",
"string"
],
- "time": "2017-07-22T12:18:28+00:00"
+ "time": "2018-01-09T20:05:19+00:00"
},
{
"name": "illuminate/console",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/console.git",
- "reference": "bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e"
+ "reference": "8e276273dd518d83e229488b358ddf3a0b47acff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/console/zipball/bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e",
- "reference": "bdc5c6f53cb474e2aeec46b6a9999fcedfb62a4e",
+ "url": "https://api.github.com/repos/illuminate/console/zipball/8e276273dd518d83e229488b358ddf3a0b47acff",
+ "reference": "8e276273dd518d83e229488b358ddf3a0b47acff",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "nesbot/carbon": "~1.20",
- "php": ">=5.6.4",
- "symfony/console": "~3.2"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/console": "~4.0"
},
"suggest": {
+ "dragonmantank/cron-expression": "Required to use scheduling component (~2.0).",
"guzzlehttp/guzzle": "Required to use the ping methods on schedules (~6.0).",
- "mtdowling/cron-expression": "Required to use scheduling component (~1.0).",
- "symfony/process": "Required to use scheduling component (~3.2)."
+ "symfony/process": "Required to use scheduling component (~4.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Console package.",
"homepage": "https://laravel.com",
- "time": "2017-06-10T13:11:18+00:00"
+ "time": "2018-04-07T17:05:26+00:00"
},
{
"name": "illuminate/contracts",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0"
+ "reference": "322ec80498b3bf85bc4025d028e130a9b50242b9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/contracts/zipball/31f0193eb14aa3ee07841dc254081425616e79f0",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0",
+ "url": "https://api.github.com/repos/illuminate/contracts/zipball/322ec80498b3bf85bc4025d028e130a9b50242b9",
+ "reference": "322ec80498b3bf85bc4025d028e130a9b50242b9",
"shasum": ""
},
"require": {
- "php": ">=5.6.4"
+ "php": "^7.1.3",
+ "psr/container": "~1.0",
+ "psr/simple-cache": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com",
- "time": "2017-04-19T20:17:43+00:00"
+ "time": "2018-04-07T17:05:26+00:00"
},
{
"name": "illuminate/filesystem",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/filesystem.git",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda"
+ "reference": "c9ab9376076cedd88a374d7281d62b619634d578"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/filesystem/zipball/e0ee832f625fbfadb816a972655b1a66af1a5bda",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda",
+ "url": "https://api.github.com/repos/illuminate/filesystem/zipball/c9ab9376076cedd88a374d7281d62b619634d578",
+ "reference": "c9ab9376076cedd88a374d7281d62b619634d578",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4",
- "symfony/finder": "~3.2"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/finder": "~4.0"
},
"suggest": {
"league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).",
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).",
- "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0)."
+ "league/flysystem-cached-adapter": "Required to use the Flysystem cache (~1.0).",
+ "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).",
+ "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (~1.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Filesystem package.",
"homepage": "https://laravel.com",
- "time": "2017-05-18T14:37:58+00:00"
+ "time": "2018-04-06T13:15:37+00:00"
},
{
"name": "illuminate/support",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d"
+ "reference": "cc8d6f5cef3a901de6bb7d1b362102a6db001085"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/support/zipball/a42393b56d0ec75f55e760f2a47bcf85a17a278d",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d",
+ "url": "https://api.github.com/repos/illuminate/support/zipball/cc8d6f5cef3a901de6bb7d1b362102a6db001085",
+ "reference": "cc8d6f5cef3a901de6bb7d1b362102a6db001085",
"shasum": ""
},
"require": {
- "doctrine/inflector": "~1.0",
+ "doctrine/inflector": "~1.1",
"ext-mbstring": "*",
- "illuminate/contracts": "5.4.*",
- "paragonie/random_compat": "~1.4|~2.0",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "nesbot/carbon": "^1.24.1",
+ "php": "^7.1.3"
},
- "replace": {
- "tightenco/collect": "self.version"
+ "conflict": {
+ "tightenco/collect": "<5.5.33"
},
"suggest": {
- "illuminate/filesystem": "Required to use the composer class (5.2.*).",
- "symfony/process": "Required to use the composer class (~3.2).",
- "symfony/var-dumper": "Required to use the dd function (~3.2)."
+ "illuminate/filesystem": "Required to use the composer class (5.6.*).",
+ "symfony/process": "Required to use the composer class (~4.0).",
+ "symfony/var-dumper": "Required to use the dd function (~4.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
- "time": "2017-06-15T12:35:32+00:00"
+ "time": "2018-04-17T12:26:47+00:00"
},
{
"name": "nesbot/carbon",
- "version": "1.22.1",
+ "version": "1.27.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc"
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc",
- "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
"shasum": ""
},
"require": {
- "php": ">=5.3.0",
- "symfony/translation": "~2.6 || ~3.0"
+ "php": ">=5.3.9",
+ "symfony/translation": "~2.6 || ~3.0 || ~4.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2",
- "phpunit/phpunit": "~4.0 || ~5.0"
+ "phpunit/phpunit": "^4.8.35 || ^5.7"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.23-dev"
- }
- },
"autoload": {
"psr-4": {
- "Carbon\\": "src/Carbon/"
+ "": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"datetime",
"time"
],
- "time": "2017-01-16T07:55:07+00:00"
+ "time": "2018-04-23T09:02:57+00:00"
},
{
- "name": "paragonie/random_compat",
- "version": "v2.0.10",
+ "name": "psr/container",
+ "version": "1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/paragonie/random_compat.git",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
- "php": ">=5.2.0"
- },
- "require-dev": {
- "phpunit/phpunit": "4.*|5.*"
- },
- "suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ "php": ">=5.3.0"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
"autoload": {
- "files": [
- "lib/random.php"
- ]
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
}
],
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
"keywords": [
- "csprng",
- "pseudorandom",
- "random"
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
],
- "time": "2017-03-13T16:27:32+00:00"
+ "time": "2017-02-14T16:28:37+00:00"
},
{
- "name": "psr/log",
- "version": "1.0.2",
+ "name": "psr/simple-cache",
+ "version": "1.0.1",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/log.git",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
},
"autoload": {
"psr-4": {
- "Psr\\Log\\": "Psr/Log/"
+ "Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"homepage": "http://www.php-fig.org/"
}
],
- "description": "Common interface for logging libraries",
- "homepage": "https://github.com/php-fig/log",
+ "description": "Common interfaces for simple caching",
"keywords": [
- "log",
+ "cache",
+ "caching",
"psr",
- "psr-3"
+ "psr-16",
+ "simple-cache"
],
- "time": "2016-10-10T12:19:37+00:00"
+ "time": "2017-10-23T01:57:42+00:00"
},
{
"name": "symfony/console",
- "version": "v3.3.6",
+ "version": "v4.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "b0878233cb5c4391347e5495089c7af11b8e6201"
+ "reference": "aad9a6fe47319f22748fd764f52d3a7ca6fa6b64"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/b0878233cb5c4391347e5495089c7af11b8e6201",
- "reference": "b0878233cb5c4391347e5495089c7af11b8e6201",
+ "url": "https://api.github.com/repos/symfony/console/zipball/aad9a6fe47319f22748fd764f52d3a7ca6fa6b64",
+ "reference": "aad9a6fe47319f22748fd764f52d3a7ca6fa6b64",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
- "symfony/debug": "~2.8|~3.0",
+ "php": "^7.1.3",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "symfony/dependency-injection": "<3.3"
+ "symfony/dependency-injection": "<3.4",
+ "symfony/process": "<3.3"
},
"require-dev": {
"psr/log": "~1.0",
- "symfony/config": "~3.3",
- "symfony/dependency-injection": "~3.3",
- "symfony/event-dispatcher": "~2.8|~3.0",
- "symfony/filesystem": "~2.8|~3.0",
- "symfony/http-kernel": "~2.8|~3.0",
- "symfony/process": "~2.8|~3.0"
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/event-dispatcher": "~3.4|~4.0",
+ "symfony/lock": "~3.4|~4.0",
+ "symfony/process": "~3.4|~4.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
- "symfony/filesystem": "",
+ "symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2017-07-29T21:27:59+00:00"
- },
- {
- "name": "symfony/debug",
- "version": "v3.3.6",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/debug.git",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
- "shasum": ""
- },
- "require": {
- "php": ">=5.5.9",
- "psr/log": "~1.0"
- },
- "conflict": {
- "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
- },
- "require-dev": {
- "symfony/http-kernel": "~2.8|~3.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.3-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Debug\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Debug Component",
- "homepage": "https://symfony.com",
- "time": "2017-07-28T15:27:31+00:00"
+ "time": "2018-04-03T05:24:00+00:00"
},
{
"name": "symfony/finder",
- "version": "v3.3.6",
+ "version": "v4.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4"
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2017-06-01T21:01:25+00:00"
+ "time": "2018-04-04T05:10:37+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.4.0",
+ "version": "v1.7.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "f29dca382a6485c3cbe6379f0c61230167681937"
+ "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937",
- "reference": "f29dca382a6485c3cbe6379f0c61230167681937",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b",
+ "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b",
"shasum": ""
},
"require": {
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "1.7-dev"
}
},
"autoload": {
"portable",
"shim"
],
- "time": "2017-06-09T14:24:12+00:00"
+ "time": "2018-01-30T19:27:44+00:00"
},
{
"name": "symfony/process",
- "version": "v3.3.6",
+ "version": "v3.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a"
+ "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a",
+ "url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b",
+ "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "3.4-dev"
}
},
"autoload": {
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2017-07-13T13:05:09+00:00"
+ "time": "2018-04-03T05:22:50+00:00"
},
{
"name": "symfony/translation",
- "version": "v3.3.6",
+ "version": "v4.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3"
+ "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
- "reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/e20a9b7f9f62cb33a11638b345c248e7d510c938",
+ "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
+ "php": "^7.1.3",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "symfony/config": "<2.8",
- "symfony/yaml": "<3.3"
+ "symfony/config": "<3.4",
+ "symfony/dependency-injection": "<3.4",
+ "symfony/yaml": "<3.4"
},
"require-dev": {
"psr/log": "~1.0",
- "symfony/config": "~2.8|~3.0",
- "symfony/intl": "^2.8.18|^3.2.5",
- "symfony/yaml": "~3.3"
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/finder": "~2.8|~3.0|~4.0",
+ "symfony/intl": "~3.4|~4.0",
+ "symfony/yaml": "~3.4|~4.0"
},
"suggest": {
"psr/log": "To use logging capability in translator",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
- "time": "2017-06-24T16:45:30+00:00"
+ "time": "2018-02-22T10:50:29+00:00"
}
],
"packages-dev": [
{
"name": "squizlabs/php_codesniffer",
- "version": "3.0.2",
+ "version": "3.2.3",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51"
+ "reference": "4842476c434e375f9d3182ff7b89059583aa8b27"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/c7594a88ae75401e8f8d0bd4deb8431b39045c51",
- "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27",
+ "reference": "4842476c434e375f9d3182ff7b89059583aa8b27",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.0"
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"phpcs",
"standards"
],
- "time": "2017-07-18T01:12:32+00:00"
+ "time": "2018-02-20T21:35:23+00:00"
}
],
"aliases": [],
/** @var \Throwable Catchable error thrown during construction. */
protected $configError;
- /** @var string Path to theme root folder, e.g., /srv/www/example.dev/current/web/app/themes/sage */
+ /** @var string Path to theme root folder, e.g., /srv/www/example.test/current/web/app/themes/sage */
protected $root;
/** {@inheritdoc} */
use InvalidArgumentException;
use Roots\Sage\Installer\Presets\Bootstrap;
use Roots\Sage\Installer\Presets\Bulma;
-use Roots\Sage\Installer\Presets\FontAwesome;
use Roots\Sage\Installer\Presets\Foundation;
use Roots\Sage\Installer\Presets\None;
use Roots\Sage\Installer\Presets\Preset;
'Confirm overwriting files',
null
);
- $this->addOption(
- 'fontawesome',
- 'F',
- InputOption::VALUE_NONE,
- 'Install Font-Awesome',
- null
- );
}
/** {@inheritdoc} */
protected function interact(InputInterface $input, OutputInterface $output)
{
$this->framework();
- $this->fontAwesome();
}
/** {@inheritdoc} */
return;
}
$preset->handle();
- $this->extras();
$this->info('Done.');
$this->comment('Please run `yarn && yarn build` to compile your fresh scaffolding.');
- }
-
- protected function extras()
- {
- if ($this->option('fontawesome')) {
- (new FontAwesome($this->root))->handle();
- }
+ $this->comment('');
+ $this->comment('Help support our open-source development efforts by contributing to Sage on OpenCollective:');
+ $this->comment('https://opencollective.com/sage');
+ $this->comment('Join us on the Roots Community Slack when you become a supporter!');
}
protected function framework()
$this->input->setArgument('framework', $this->presets->slugs()[$framework]);
}
- protected function fontAwesome()
- {
- $installFontAwesome = $this->option('fontawesome')
- ?: $this->confirm('Do you want to install Font Awesome?');
-
- $this->input->setOption('fontawesome', $installFontAwesome);
- }
-
/**
* Confirm overwriting files
*
/** {@inheritdoc} */
protected function updatePackagesArray(array $packages)
{
- $packages['dependencies']['bootstrap'] = '^4.0.0-beta';
- $packages['dependencies']['popper.js'] = '~1.11';
+ $packages['dependencies']['bootstrap'] = 'v4.1.0';
+ $packages['dependencies']['popper.js'] = '^1.14.3';
return $packages;
}
}
+++ /dev/null
-<?php
-
-namespace Roots\Sage\Installer\Presets;
-
-class FontAwesome extends Preset
-{
- public $addOn = true;
-
- /** {@inheritdoc} */
- protected function updatePackagesArray(array $packages)
- {
- $packages['dependencies']['font-awesome'] = '~4.7';
- return $packages;
- }
-}
/** {@inheritdoc} */
protected function updatePackagesArray(array $packages)
{
- $packages['dependencies']['tachyons-sass'] = '~4.7';
+ $packages['dependencies']['tachyons-sass'] = '~4.8';
return $packages;
}
}
+/** Import Bootstrap functions */
+@import "~bootstrap/scss/functions";
+$theme-colors: (
+ primary: #525ddc
+);
/** Colors */
-$primary: #27ae60;
+$primary: #525ddc;
/** Box Model */
$spacer: 2rem;
+++ /dev/null
-$fa-font-path: '~font-awesome/fonts';
-
-@import "~font-awesome/scss/font-awesome";
/** Colors */
$foundation-palette: (
- primary: #27ae60,
+ primary: #525ddc,
secondary: #1866ff,
success: #3adb76,
warning: #ffae00,
/** Colors */
-$brand-primary: #27ae60;
+$brand-primary: #525ddc;
/** Box Model */
$spacer: 2rem;
/** Colors */
-$brand-primary: #27ae60;
+$brand-primary: #525ddc;
/** Box Model */
$spacer: 2rem;
class ThemeHeaders
{
protected $content;
-
+
public $stylesheet;
public $headers = [
'Name' => 'Sage Starter Theme',
'URI' => 'https://roots.io/sage/',
'Description' => 'Sage is a WordPress starter theme.',
- 'Version' => '9.0.0',
+ 'Version' => '9.0.1',
'Author' => 'Roots',
'Author URI' => 'https://roots.io/'
];
-
+
public function __construct($stylesheet = '')
{
$this->headers = new Collection($this->headers);
$this->stylesheet = $stylesheet ?: getcwd().'/resources/style.css';
}
-
+
public function getCurrentHeaders()
{
$this->content = file_get_contents($this->stylesheet);
class Config extends \Illuminate\Config\Repository
{
+ protected static $instance;
}
"require": {
"php": ">=7",
"composer/installers": "~1.0",
- "illuminate/view": "~5.4",
- "illuminate/config": "~5.4"
+ "illuminate/view": "~5.6",
+ "illuminate/config": "~5.6"
},
"require-dev": {
"squizlabs/php_codesniffer": "~3.0"
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "cebd394669ff4718bcfc1a092d3dc63f",
+ "content-hash": "8dcadb1a070fc044aa0770fd18116d7e",
"packages": [
{
"name": "composer/installers",
- "version": "v1.4.0",
+ "version": "v1.5.0",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
- "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b"
+ "reference": "049797d727261bf27f2690430d935067710049c2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/installers/zipball/9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b",
- "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b",
+ "url": "https://api.github.com/repos/composer/installers/zipball/049797d727261bf27f2690430d935067710049c2",
+ "reference": "049797d727261bf27f2690430d935067710049c2",
"shasum": ""
},
"require": {
},
"require-dev": {
"composer/composer": "1.0.*@dev",
- "phpunit/phpunit": "4.1.*"
+ "phpunit/phpunit": "^4.8.36"
},
"type": "composer-plugin",
"extra": {
"lavalite",
"lithium",
"magento",
+ "majima",
"mako",
"mediawiki",
"modulework",
+ "modx",
"moodle",
"osclass",
"phpbb",
"piwik",
"ppi",
"puppet",
+ "pxcms",
"reindex",
"roundcube",
"shopware",
"zend",
"zikula"
],
- "time": "2017-08-09T07:53:48+00:00"
+ "time": "2017-12-29T09:13:20+00:00"
},
{
"name": "doctrine/inflector",
- "version": "v1.2.0",
+ "version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462"
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462",
- "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a",
+ "reference": "5527a48b7313d15261292c149e55e26eae771b0a",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^6.2"
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2.x-dev"
+ "dev-master": "1.3.x-dev"
}
},
"autoload": {
"singularize",
"string"
],
- "time": "2017-07-22T12:18:28+00:00"
+ "time": "2018-01-09T20:05:19+00:00"
},
{
"name": "illuminate/config",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/config.git",
- "reference": "8fe700aa596bc623d347e4578041fbda7a44c3d9"
+ "reference": "e8158dff3189deed846c84c66c60fa68c21ee579"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/config/zipball/8fe700aa596bc623d347e4578041fbda7a44c3d9",
- "reference": "8fe700aa596bc623d347e4578041fbda7a44c3d9",
+ "url": "https://api.github.com/repos/illuminate/config/zipball/e8158dff3189deed846c84c66c60fa68c21ee579",
+ "reference": "e8158dff3189deed846c84c66c60fa68c21ee579",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Config package.",
"homepage": "https://laravel.com",
- "time": "2017-02-04T20:27:32+00:00"
+ "time": "2017-11-07T20:23:51+00:00"
},
{
"name": "illuminate/container",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
- "reference": "c5b8a02a34a52c307f16922334c355c5eef725a6"
+ "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/container/zipball/c5b8a02a34a52c307f16922334c355c5eef725a6",
- "reference": "c5b8a02a34a52c307f16922334c355c5eef725a6",
+ "url": "https://api.github.com/repos/illuminate/container/zipball/4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
+ "reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "php": "^7.1.3",
+ "psr/container": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Container package.",
"homepage": "https://laravel.com",
- "time": "2017-05-24T14:15:53+00:00"
+ "time": "2018-01-21T02:13:38+00:00"
},
{
"name": "illuminate/contracts",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0"
+ "reference": "322ec80498b3bf85bc4025d028e130a9b50242b9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/contracts/zipball/31f0193eb14aa3ee07841dc254081425616e79f0",
- "reference": "31f0193eb14aa3ee07841dc254081425616e79f0",
+ "url": "https://api.github.com/repos/illuminate/contracts/zipball/322ec80498b3bf85bc4025d028e130a9b50242b9",
+ "reference": "322ec80498b3bf85bc4025d028e130a9b50242b9",
"shasum": ""
},
"require": {
- "php": ">=5.6.4"
+ "php": "^7.1.3",
+ "psr/container": "~1.0",
+ "psr/simple-cache": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com",
- "time": "2017-04-19T20:17:43+00:00"
+ "time": "2018-04-07T17:05:26+00:00"
},
{
"name": "illuminate/events",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/events.git",
- "reference": "ebdca3b0305e9fc954afb9e422c4559482cd11e6"
+ "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/events/zipball/ebdca3b0305e9fc954afb9e422c4559482cd11e6",
- "reference": "ebdca3b0305e9fc954afb9e422c4559482cd11e6",
+ "url": "https://api.github.com/repos/illuminate/events/zipball/b6e73ed40478cef2ef98d5ddb27f333291606cea",
+ "reference": "b6e73ed40478cef2ef98d5ddb27f333291606cea",
"shasum": ""
},
"require": {
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4"
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Events package.",
"homepage": "https://laravel.com",
- "time": "2017-05-02T12:57:00+00:00"
+ "time": "2018-02-26T19:00:55+00:00"
},
{
"name": "illuminate/filesystem",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/filesystem.git",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda"
+ "reference": "c9ab9376076cedd88a374d7281d62b619634d578"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/filesystem/zipball/e0ee832f625fbfadb816a972655b1a66af1a5bda",
- "reference": "e0ee832f625fbfadb816a972655b1a66af1a5bda",
+ "url": "https://api.github.com/repos/illuminate/filesystem/zipball/c9ab9376076cedd88a374d7281d62b619634d578",
+ "reference": "c9ab9376076cedd88a374d7281d62b619634d578",
"shasum": ""
},
"require": {
- "illuminate/contracts": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4",
- "symfony/finder": "~3.2"
+ "illuminate/contracts": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/finder": "~4.0"
},
"suggest": {
"league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).",
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).",
- "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0)."
+ "league/flysystem-cached-adapter": "Required to use the Flysystem cache (~1.0).",
+ "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).",
+ "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (~1.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Filesystem package.",
"homepage": "https://laravel.com",
- "time": "2017-05-18T14:37:58+00:00"
+ "time": "2018-04-06T13:15:37+00:00"
},
{
"name": "illuminate/support",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d"
+ "reference": "cc8d6f5cef3a901de6bb7d1b362102a6db001085"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/support/zipball/a42393b56d0ec75f55e760f2a47bcf85a17a278d",
- "reference": "a42393b56d0ec75f55e760f2a47bcf85a17a278d",
+ "url": "https://api.github.com/repos/illuminate/support/zipball/cc8d6f5cef3a901de6bb7d1b362102a6db001085",
+ "reference": "cc8d6f5cef3a901de6bb7d1b362102a6db001085",
"shasum": ""
},
"require": {
- "doctrine/inflector": "~1.0",
+ "doctrine/inflector": "~1.1",
"ext-mbstring": "*",
- "illuminate/contracts": "5.4.*",
- "paragonie/random_compat": "~1.4|~2.0",
- "php": ">=5.6.4"
+ "illuminate/contracts": "5.6.*",
+ "nesbot/carbon": "^1.24.1",
+ "php": "^7.1.3"
},
- "replace": {
- "tightenco/collect": "self.version"
+ "conflict": {
+ "tightenco/collect": "<5.5.33"
},
"suggest": {
- "illuminate/filesystem": "Required to use the composer class (5.2.*).",
- "symfony/process": "Required to use the composer class (~3.2).",
- "symfony/var-dumper": "Required to use the dd function (~3.2)."
+ "illuminate/filesystem": "Required to use the composer class (5.6.*).",
+ "symfony/process": "Required to use the composer class (~4.0).",
+ "symfony/var-dumper": "Required to use the dd function (~4.0)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
- "time": "2017-06-15T12:35:32+00:00"
+ "time": "2018-04-17T12:26:47+00:00"
},
{
"name": "illuminate/view",
- "version": "v5.4.27",
+ "version": "v5.6.17",
"source": {
"type": "git",
"url": "https://github.com/illuminate/view.git",
- "reference": "423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75"
+ "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/view/zipball/423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75",
- "reference": "423652ea1c4c4c2f6494bd6b8cfb6eb943c5ba75",
+ "url": "https://api.github.com/repos/illuminate/view/zipball/54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
+ "reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
"shasum": ""
},
"require": {
- "illuminate/container": "5.4.*",
- "illuminate/contracts": "5.4.*",
- "illuminate/events": "5.4.*",
- "illuminate/filesystem": "5.4.*",
- "illuminate/support": "5.4.*",
- "php": ">=5.6.4",
- "symfony/debug": "~3.2"
+ "illuminate/container": "5.6.*",
+ "illuminate/contracts": "5.6.*",
+ "illuminate/events": "5.6.*",
+ "illuminate/filesystem": "5.6.*",
+ "illuminate/support": "5.6.*",
+ "php": "^7.1.3",
+ "symfony/debug": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
],
"description": "The Illuminate View package.",
"homepage": "https://laravel.com",
- "time": "2017-06-07T13:32:57+00:00"
+ "time": "2018-04-03T12:56:35+00:00"
},
{
- "name": "paragonie/random_compat",
- "version": "v2.0.10",
+ "name": "nesbot/carbon",
+ "version": "1.27.0",
"source": {
"type": "git",
- "url": "https://github.com/paragonie/random_compat.git",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
+ "url": "https://github.com/briannesbitt/Carbon.git",
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
+ "reference": "ef81c39b67200dcd7401c24363dcac05ac3a4fe9",
"shasum": ""
},
"require": {
- "php": ">=5.2.0"
+ "php": ">=5.3.9",
+ "symfony/translation": "~2.6 || ~3.0 || ~4.0"
},
"require-dev": {
- "phpunit/phpunit": "4.*|5.*"
+ "friendsofphp/php-cs-fixer": "~2",
+ "phpunit/phpunit": "^4.8.35 || ^5.7"
},
- "suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "http://nesbot.com"
+ }
+ ],
+ "description": "A simple API extension for DateTime.",
+ "homepage": "http://carbon.nesbot.com",
+ "keywords": [
+ "date",
+ "datetime",
+ "time"
+ ],
+ "time": "2018-04-23T09:02:57+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
"autoload": {
- "files": [
- "lib/random.php"
- ]
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
],
"authors": [
{
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
}
],
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
"keywords": [
- "csprng",
- "pseudorandom",
- "random"
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
],
- "time": "2017-03-13T16:27:32+00:00"
+ "time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/log",
],
"time": "2016-10-10T12:19:37+00:00"
},
+ {
+ "name": "psr/simple-cache",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "time": "2017-10-23T01:57:42+00:00"
+ },
{
"name": "symfony/debug",
- "version": "v3.3.6",
+ "version": "v4.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13"
+ "reference": "5961d02d48828671f5d8a7805e06579d692f6ede"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
- "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/5961d02d48828671f5d8a7805e06579d692f6ede",
+ "reference": "5961d02d48828671f5d8a7805e06579d692f6ede",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
+ "php": "^7.1.3",
"psr/log": "~1.0"
},
"conflict": {
- "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ "symfony/http-kernel": "<3.4"
},
"require-dev": {
- "symfony/http-kernel": "~2.8|~3.0"
+ "symfony/http-kernel": "~3.4|~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2017-07-28T15:27:31+00:00"
+ "time": "2018-04-03T05:24:00+00:00"
},
{
"name": "symfony/finder",
- "version": "v3.3.6",
+ "version": "v4.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4"
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
+ "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
},
"autoload": {
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2017-06-01T21:01:25+00:00"
+ "time": "2018-04-04T05:10:37+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b",
+ "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2018-01-30T19:27:44+00:00"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v4.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/e20a9b7f9f62cb33a11638b345c248e7d510c938",
+ "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/config": "<3.4",
+ "symfony/dependency-injection": "<3.4",
+ "symfony/yaml": "<3.4"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/finder": "~2.8|~3.0|~4.0",
+ "symfony/intl": "~3.4|~4.0",
+ "symfony/yaml": "~3.4|~4.0"
+ },
+ "suggest": {
+ "psr/log": "To use logging capability in translator",
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Translation Component",
+ "homepage": "https://symfony.com",
+ "time": "2018-02-22T10:50:29+00:00"
}
],
"packages-dev": [
{
"name": "squizlabs/php_codesniffer",
- "version": "3.0.2",
+ "version": "3.2.3",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51"
+ "reference": "4842476c434e375f9d3182ff7b89059583aa8b27"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/c7594a88ae75401e8f8d0bd4deb8431b39045c51",
- "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27",
+ "reference": "4842476c434e375f9d3182ff7b89059583aa8b27",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.0"
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"phpcs",
"standards"
],
- "time": "2017-07-18T01:12:32+00:00"
+ "time": "2018-02-20T21:35:23+00:00"
}
],
"aliases": [],
namespace Symfony\Component\Console;
+use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\DebugFormatterHelper;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
-use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Exception\LogicException;
+use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
private $runningCommand;
private $name;
private $version;
+ private $commandLoader;
private $catchExceptions = true;
private $autoExit = true;
private $definition;
private $terminal;
private $defaultCommand;
private $singleCommand;
+ private $initialized;
/**
* @param string $name The name of the application
* @param string $version The version of the application
*/
- public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
+ public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN')
{
$this->name = $name;
$this->version = $version;
$this->terminal = new Terminal();
$this->defaultCommand = 'list';
- $this->helperSet = $this->getDefaultHelperSet();
- $this->definition = $this->getDefaultInputDefinition();
-
- foreach ($this->getDefaultCommands() as $command) {
- $this->add($command);
- }
}
public function setDispatcher(EventDispatcherInterface $dispatcher)
$this->dispatcher = $dispatcher;
}
+ public function setCommandLoader(CommandLoaderInterface $commandLoader)
+ {
+ $this->commandLoader = $commandLoader;
+ }
+
/**
* Runs the current application.
*
- * @param InputInterface $input An Input instance
- * @param OutputInterface $output An Output instance
- *
* @return int 0 if everything went fine, or an error code
*
* @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
$output = new ConsoleOutput();
}
- if (null !== $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) {
- @trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), E_USER_DEPRECATED);
+ $renderException = function ($e) use ($output) {
+ if (!$e instanceof \Exception) {
+ $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
+ }
+ if ($output instanceof ConsoleOutputInterface) {
+ $this->renderException($e, $output->getErrorOutput());
+ } else {
+ $this->renderException($e, $output);
+ }
+ };
+ if ($phpHandler = set_exception_handler($renderException)) {
+ restore_exception_handler();
+ if (!is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
+ $debugHandler = true;
+ } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
+ $phpHandler[0]->setExceptionHandler($debugHandler);
+ }
}
$this->configureIO($input, $output);
try {
- $e = null;
$exitCode = $this->doRun($input, $output);
- } catch (\Exception $x) {
- $e = $x;
- } catch (\Throwable $x) {
- $e = new FatalThrowableError($x);
- }
-
- if (null !== $e) {
- if (!$this->catchExceptions || !$x instanceof \Exception) {
- throw $x;
+ } catch (\Exception $e) {
+ if (!$this->catchExceptions) {
+ throw $e;
}
- if ($output instanceof ConsoleOutputInterface) {
- $this->renderException($e, $output->getErrorOutput());
- } else {
- $this->renderException($e, $output);
- }
+ $renderException($e);
$exitCode = $e->getCode();
if (is_numeric($exitCode)) {
} else {
$exitCode = 1;
}
+ } finally {
+ // if the exception handler changed, keep it
+ // otherwise, unregister $renderException
+ if (!$phpHandler) {
+ if (set_exception_handler($renderException) === $renderException) {
+ restore_exception_handler();
+ }
+ restore_exception_handler();
+ } elseif (!$debugHandler) {
+ $finalHandler = $phpHandler[0]->setExceptionHandler(null);
+ if ($finalHandler !== $renderException) {
+ $phpHandler[0]->setExceptionHandler($finalHandler);
+ }
+ }
}
if ($this->autoExit) {
/**
* Runs the current application.
*
- * @param InputInterface $input An Input instance
- * @param OutputInterface $output An Output instance
- *
* @return int 0 if everything went fine, or an error code
*/
public function doRun(InputInterface $input, OutputInterface $output)
if (!$name) {
$name = $this->defaultCommand;
- $this->definition->setArguments(array_merge(
- $this->definition->getArguments(),
+ $definition = $this->getDefinition();
+ $definition->setArguments(array_merge(
+ $definition->getArguments(),
array(
- 'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name),
+ 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
)
));
}
try {
- $e = $this->runningCommand = null;
+ $this->runningCommand = null;
// the command name MUST be the first element of the input
$command = $this->find($name);
- } catch (\Exception $e) {
} catch (\Throwable $e) {
- }
- if (null !== $e) {
if (null !== $this->dispatcher) {
$event = new ConsoleErrorEvent($input, $output, $e);
$this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);
- $e = $event->getError();
if (0 === $event->getExitCode()) {
return 0;
}
+
+ $e = $event->getError();
}
throw $e;
return $exitCode;
}
- /**
- * Set a helper set to be used with the command.
- *
- * @param HelperSet $helperSet The helper set
- */
public function setHelperSet(HelperSet $helperSet)
{
$this->helperSet = $helperSet;
*/
public function getHelperSet()
{
+ if (!$this->helperSet) {
+ $this->helperSet = $this->getDefaultHelperSet();
+ }
+
return $this->helperSet;
}
- /**
- * Set an input definition to be used with this application.
- *
- * @param InputDefinition $definition The input definition
- */
public function setDefinition(InputDefinition $definition)
{
$this->definition = $definition;
*/
public function getDefinition()
{
+ if (!$this->definition) {
+ $this->definition = $this->getDefaultInputDefinition();
+ }
+
if ($this->singleCommand) {
$inputDefinition = $this->definition;
$inputDefinition->setArguments();
* If a command with the same name already exists, it will be overridden.
* If the command is not enabled it will not be added.
*
- * @param Command $command A Command object
- *
* @return Command|null The registered command if enabled or null
*/
public function add(Command $command)
{
+ $this->init();
+
$command->setApplication($this);
if (!$command->isEnabled()) {
throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
}
+ if (!$command->getName()) {
+ throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($command)));
+ }
+
$this->commands[$command->getName()] = $command;
foreach ($command->getAliases() as $alias) {
*/
public function get($name)
{
- if (!isset($this->commands[$name])) {
+ $this->init();
+
+ if (!$this->has($name)) {
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
}
*/
public function has($name)
{
- return isset($this->commands[$name]);
+ $this->init();
+
+ return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name)));
}
/**
*/
public function find($name)
{
- $allCommands = array_keys($this->commands);
+ $this->init();
+
+ $aliases = array();
+ $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
$commands = preg_grep('{^'.$expr.'}', $allCommands);
- if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
+ if (empty($commands)) {
+ $commands = preg_grep('{^'.$expr.'}i', $allCommands);
+ }
+
+ // if no commands matched or we just matched namespaces
+ if (empty($commands) || count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) {
if (false !== $pos = strrpos($name, ':')) {
// check if a namespace exists and contains commands
$this->findNamespace(substr($name, 0, $pos));
// filter out aliases for commands which are already on the list
if (count($commands) > 1) {
- $commandList = $this->commands;
- $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
- $commandName = $commandList[$nameOrAlias]->getName();
+ $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
+ $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
+ $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias;
+ $aliases[$nameOrAlias] = $commandName;
return $commandName === $nameOrAlias || !in_array($commandName, $commands);
- });
+ }));
}
- $exact = in_array($name, $commands, true);
+ $exact = in_array($name, $commands, true) || isset($aliases[$name]);
if (count($commands) > 1 && !$exact) {
$usableWidth = $this->terminal->getWidth() - 10;
$abbrevs = array_values($commands);
$maxLen = max(Helper::strlen($abbrev), $maxLen);
}
$abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) {
+ if (!$commandList[$cmd] instanceof Command) {
+ return $cmd;
+ }
$abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription();
return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev;
*/
public function all($namespace = null)
{
+ $this->init();
+
if (null === $namespace) {
- return $this->commands;
+ if (!$this->commandLoader) {
+ return $this->commands;
+ }
+
+ $commands = $this->commands;
+ foreach ($this->commandLoader->getNames() as $name) {
+ if (!isset($commands[$name]) && $this->has($name)) {
+ $commands[$name] = $this->get($name);
+ }
+ }
+
+ return $commands;
}
$commands = array();
}
}
+ if ($this->commandLoader) {
+ foreach ($this->commandLoader->getNames() as $name) {
+ if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) {
+ $commands[$name] = $this->get($name);
+ }
+ }
+ }
+
return $commands;
}
/**
* Renders a caught exception.
- *
- * @param \Exception $e An exception instance
- * @param OutputInterface $output An OutputInterface instance
*/
public function renderException(\Exception $e, OutputInterface $output)
{
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
- do {
- $title = sprintf(
- ' [%s%s] ',
- get_class($e),
- $output->isVerbose() && 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''
- );
+ $this->doRenderException($e, $output);
- $len = Helper::strlen($title);
+ if (null !== $this->runningCommand) {
+ $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
+ $output->writeln('', OutputInterface::VERBOSITY_QUIET);
+ }
+ }
- $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX;
- // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
- if (defined('HHVM_VERSION') && $width > 1 << 31) {
- $width = 1 << 31;
+ protected function doRenderException(\Exception $e, OutputInterface $output)
+ {
+ do {
+ $message = trim($e->getMessage());
+ if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
+ $title = sprintf(' [%s%s] ', get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
+ $len = Helper::strlen($title);
+ } else {
+ $len = 0;
}
+
+ $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX;
$lines = array();
- foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
+ foreach ('' !== $message ? preg_split('/\r?\n/', $message) : array() as $line) {
foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
// pre-format lines to get the right string length
$lineLength = Helper::strlen($line) + 4;
}
$messages = array();
+ if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
+ $messages[] = sprintf('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
+ }
$messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
- $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
+ if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
+ $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
+ }
foreach ($lines as $line) {
$messages[] = sprintf('<error> %s %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
}
// exception related properties
$trace = $e->getTrace();
- array_unshift($trace, array(
- 'function' => '',
- 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
- 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
- 'args' => array(),
- ));
for ($i = 0, $count = count($trace); $i < $count; ++$i) {
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
}
} while ($e = $e->getPrevious());
-
- if (null !== $this->runningCommand) {
- $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
- $output->writeln('', OutputInterface::VERBOSITY_QUIET);
- }
- }
-
- /**
- * Tries to figure out the terminal width in which this application runs.
- *
- * @return int|null
- *
- * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
- */
- protected function getTerminalWidth()
- {
- @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);
-
- return $this->terminal->getWidth();
- }
-
- /**
- * Tries to figure out the terminal height in which this application runs.
- *
- * @return int|null
- *
- * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
- */
- protected function getTerminalHeight()
- {
- @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);
-
- return $this->terminal->getHeight();
- }
-
- /**
- * Tries to figure out the terminal dimensions based on the current environment.
- *
- * @return array Array containing width and height
- *
- * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
- */
- public function getTerminalDimensions()
- {
- @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);
-
- return array($this->terminal->getWidth(), $this->terminal->getHeight());
- }
-
- /**
- * Sets terminal dimensions.
- *
- * Can be useful to force terminal dimensions for functional tests.
- *
- * @param int $width The width
- * @param int $height The height
- *
- * @return $this
- *
- * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead.
- */
- public function setTerminalDimensions($width, $height)
- {
- @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), E_USER_DEPRECATED);
-
- putenv('COLUMNS='.$width);
- putenv('LINES='.$height);
-
- return $this;
}
/**
* Configures the input and output instances based on the user arguments and options.
- *
- * @param InputInterface $input An InputInterface instance
- * @param OutputInterface $output An OutputInterface instance
*/
protected function configureIO(InputInterface $input, OutputInterface $output)
{
$inputStream = $input->getStream();
}
- // This check ensures that calling QuestionHelper::setInputStream() works
- // To be removed in 4.0 (in the same time as QuestionHelper::setInputStream)
- if (!$inputStream && $this->getHelperSet()->has('question')) {
- $inputStream = $this->getHelperSet()->get('question')->getInputStream(false);
- }
-
if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
$input->setInteractive(false);
}
}
+ switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
+ case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break;
+ case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break;
+ case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break;
+ case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break;
+ default: $shellVerbosity = 0; break;
+ }
+
if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) {
$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
- $input->setInteractive(false);
+ $shellVerbosity = -1;
} else {
- if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || $input->getParameterOption('--verbose', false, true) === 3) {
+ if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) {
$output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
- } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || $input->getParameterOption('--verbose', false, true) === 2) {
+ $shellVerbosity = 3;
+ } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) {
$output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
+ $shellVerbosity = 2;
} elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) {
$output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
+ $shellVerbosity = 1;
}
}
+
+ if (-1 === $shellVerbosity) {
+ $input->setInteractive(false);
+ }
+
+ putenv('SHELL_VERBOSITY='.$shellVerbosity);
+ $_ENV['SHELL_VERBOSITY'] = $shellVerbosity;
+ $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity;
}
/**
* If an event dispatcher has been attached to the application,
* events are also dispatched during the life-cycle of the command.
*
- * @param Command $command A Command instance
- * @param InputInterface $input An Input instance
- * @param OutputInterface $output An Output instance
- *
* @return int 0 if everything went fine, or an error code
*/
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
} else {
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
}
- } catch (\Exception $e) {
} catch (\Throwable $e) {
- }
- if (null !== $e) {
- if ($this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) {
- $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
- $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
- $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
-
- if ($x !== $event->getException()) {
- $e = $event->getException();
- }
- }
$event = new ConsoleErrorEvent($input, $output, $e, $command);
$this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);
$e = $event->getError();
/**
* Gets the name of the command based on input.
*
- * @param InputInterface $input The input interface
- *
* @return string The command name
*/
protected function getCommandName(InputInterface $input)
* Finds alternative of $name among $collection,
* if nothing is found in $collection, try in $abbrevs.
*
- * @param string $name The string
- * @param array|\Traversable $collection The collection
+ * @param string $name The string
+ * @param iterable $collection The collection
*
* @return string[] A sorted array of similar string
*/
$lines[] = str_pad($line, $width);
$line = $char;
}
- if ('' !== $line) {
- $lines[] = count($lines) ? str_pad($line, $width) : $line;
- }
+
+ $lines[] = count($lines) ? str_pad($line, $width) : $line;
mb_convert_variables($encoding, 'utf8', $lines);
return $namespaces;
}
+
+ private function init()
+ {
+ if ($this->initialized) {
+ return;
+ }
+ $this->initialized = true;
+
+ foreach ($this->getDefaultCommands() as $command) {
+ $this->add($command);
+ }
+ }
}
CHANGELOG
=========
+4.0.0
+-----
+
+ * `OutputFormatter` throws an exception when unknown options are used
+ * removed `QuestionHelper::setInputStream()/getInputStream()`
+ * removed `Application::getTerminalWidth()/getTerminalHeight()` and
+ `Application::setTerminalDimensions()/getTerminalDimensions()`
+* removed `ConsoleExceptionEvent`
+* removed `ConsoleEvents::EXCEPTION`
+
+3.4.0
+-----
+
+ * added `SHELL_VERBOSITY` env var to control verbosity
+ * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11
+ `ContainerCommandLoader` for commands lazy-loading
+ * added a case-insensitive command name matching fallback
+ * added static `Command::$defaultName/getDefaultName()`, allowing for
+ commands to be registered at compile time in the application command loader.
+ Setting the `$defaultName` property avoids the need for filling the `command`
+ attribute on the `console.command` tag when using `AddConsoleCommandPass`.
+
3.3.0
-----
* deprecated console.exception event in favor of console.error
* added ability to handle `CommandNotFoundException` through the
`console.error` event
+* deprecated default validation in `SymfonyQuestionHelper::ask`
3.2.0
------
*/
class Command
{
+ /**
+ * @var string|null The default command name
+ */
+ protected static $defaultName;
+
private $application;
private $name;
private $processTitle;
private $helperSet;
/**
- * Constructor.
- *
+ * @return string|null The default command name or null when no default name is set
+ */
+ public static function getDefaultName()
+ {
+ $class = get_called_class();
+ $r = new \ReflectionProperty($class, 'defaultName');
+
+ return $class === $r->class ? static::$defaultName : null;
+ }
+
+ /**
* @param string|null $name The name of the command; passing null means it must be set in configure()
*
* @throws LogicException When the command name is empty
*/
- public function __construct($name = null)
+ public function __construct(string $name = null)
{
$this->definition = new InputDefinition();
- if (null !== $name) {
+ if (null !== $name || null !== $name = static::getDefaultName()) {
$this->setName($name);
}
$this->configure();
-
- if (!$this->name) {
- throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
- }
}
/**
$this->ignoreValidationErrors = true;
}
- /**
- * Sets the application instance for this command.
- *
- * @param Application $application An Application instance
- */
public function setApplication(Application $application = null)
{
$this->application = $application;
}
}
- /**
- * Sets the helper set.
- *
- * @param HelperSet $helperSet A HelperSet instance
- */
public function setHelperSet(HelperSet $helperSet)
{
$this->helperSet = $helperSet;
* execute() method, you set the code to execute by passing
* a Closure to the setCode() method.
*
- * @param InputInterface $input An InputInterface instance
- * @param OutputInterface $output An OutputInterface instance
- *
* @return null|int null or 0 if everything went fine, or an error code
*
* @throws LogicException When this abstract method is not implemented
* This method is executed before the InputDefinition is validated.
* This means that this is the only place where the command can
* interactively ask for values of missing required arguments.
- *
- * @param InputInterface $input An InputInterface instance
- * @param OutputInterface $output An OutputInterface instance
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
*
* This is mainly useful when a lot of commands extends one main command
* where some things need to be initialized based on the input arguments and options.
- *
- * @param InputInterface $input An InputInterface instance
- * @param OutputInterface $output An OutputInterface instance
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
* setCode() method or by overriding the execute() method
* in a sub-class.
*
- * @param InputInterface $input An InputInterface instance
- * @param OutputInterface $output An OutputInterface instance
- *
* @return int The command exit code
*
* @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}.
if ($code instanceof \Closure) {
$r = new \ReflectionFunction($code);
if (null === $r->getClosureThis()) {
- if (\PHP_VERSION_ID < 70000) {
- // Bug in PHP5: https://bugs.php.net/bug.php?id=64761
- // This means that we cannot bind static closures and therefore we must
- // ignore any errors here. There is no way to test if the closure is
- // bindable.
- $code = @\Closure::bind($code, $this);
- } else {
- $code = \Closure::bind($code, $this);
- }
+ $code = \Closure::bind($code, $this);
}
}
}
/**
- * @return bool Whether the command should be publicly shown or not.
+ * @return bool whether the command should be publicly shown or not
*/
public function isHidden()
{
*
* It must be non-empty and parts can optionally be separated by ":".
*
- * @param string $name
- *
* @throws InvalidArgumentException When the name is invalid
*/
- private function validateName($name)
+ private function validateName(string $name)
{
if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
;
}
- /**
- * Sets the command.
- *
- * @param Command $command The command to set
- */
public function setCommand(Command $command)
{
$this->command = $command;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Exception\RuntimeException;
-use Symfony\Component\Filesystem\LockHandler;
+use Symfony\Component\Lock\Factory;
+use Symfony\Component\Lock\Lock;
+use Symfony\Component\Lock\Store\FlockStore;
+use Symfony\Component\Lock\Store\SemaphoreStore;
/**
* Basic lock feature for commands.
*/
trait LockableTrait
{
- private $lockHandler;
+ /** @var Lock */
+ private $lock;
/**
* Locks a command.
*/
private function lock($name = null, $blocking = false)
{
- if (!class_exists(LockHandler::class)) {
- throw new RuntimeException('To enable the locking feature you must install the symfony/filesystem component.');
+ if (!class_exists(SemaphoreStore::class)) {
+ throw new RuntimeException('To enable the locking feature you must install the symfony/lock component.');
}
- if (null !== $this->lockHandler) {
+ if (null !== $this->lock) {
throw new LogicException('A lock is already in place.');
}
- $this->lockHandler = new LockHandler($name ?: $this->getName());
+ if (SemaphoreStore::isSupported()) {
+ $store = new SemaphoreStore();
+ } else {
+ $store = new FlockStore();
+ }
- if (!$this->lockHandler->lock($blocking)) {
- $this->lockHandler = null;
+ $this->lock = (new Factory($store))->createLock($name ?: $this->getName());
+ if (!$this->lock->acquire($blocking)) {
+ $this->lock = null;
return false;
}
*/
private function release()
{
- if ($this->lockHandler) {
- $this->lockHandler->release();
- $this->lockHandler = null;
+ if ($this->lock) {
+ $this->lock->release();
+ $this->lock = null;
}
}
}
--- /dev/null
+<?php
+
+namespace Symfony\Component\Console\CommandLoader;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\CommandNotFoundException;
+
+/**
+ * @author Robin Chalas <robin.chalas@gmail.com>
+ */
+interface CommandLoaderInterface
+{
+ /**
+ * Loads a command.
+ *
+ * @param string $name
+ *
+ * @return Command
+ *
+ * @throws CommandNotFoundException
+ */
+ public function get($name);
+
+ /**
+ * Checks if a command exists.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function has($name);
+
+ /**
+ * @return string[] All registered command names
+ */
+ public function getNames();
+}
--- /dev/null
+<?php
+
+namespace Symfony\Component\Console\CommandLoader;
+
+use Psr\Container\ContainerInterface;
+use Symfony\Component\Console\Exception\CommandNotFoundException;
+
+/**
+ * Loads commands from a PSR-11 container.
+ *
+ * @author Robin Chalas <robin.chalas@gmail.com>
+ */
+class ContainerCommandLoader implements CommandLoaderInterface
+{
+ private $container;
+ private $commandMap;
+
+ /**
+ * @param ContainerInterface $container A container from which to load command services
+ * @param array $commandMap An array with command names as keys and service ids as values
+ */
+ public function __construct(ContainerInterface $container, array $commandMap)
+ {
+ $this->container = $container;
+ $this->commandMap = $commandMap;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($name)
+ {
+ if (!$this->has($name)) {
+ throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
+ }
+
+ return $this->container->get($this->commandMap[$name]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($name)
+ {
+ return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNames()
+ {
+ return array_keys($this->commandMap);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\CommandLoader;
+
+use Symfony\Component\Console\Exception\CommandNotFoundException;
+
+/**
+ * A simple command loader using factories to instantiate commands lazily.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+class FactoryCommandLoader implements CommandLoaderInterface
+{
+ private $factories;
+
+ /**
+ * @param callable[] $factories Indexed by command names
+ */
+ public function __construct(array $factories)
+ {
+ $this->factories = $factories;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($name)
+ {
+ return isset($this->factories[$name]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($name)
+ {
+ if (!isset($this->factories[$name])) {
+ throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
+ }
+
+ $factory = $this->factories[$name];
+
+ return $factory();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNames()
+ {
+ return array_keys($this->factories);
+ }
+}
* before they are handled to the command.
*
* @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
- *
- * @var string
*/
const COMMAND = 'console.command';
* executed by the console.
*
* @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
- *
- * @var string
*/
const TERMINATE = 'console.terminate';
- /**
- * The EXCEPTION event occurs when an uncaught exception appears
- * while executing Command#run().
- *
- * This event allows you to deal with the exception or
- * to modify the thrown exception.
- *
- * @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent")
- *
- * @var string
- *
- * @deprecated The console.exception event is deprecated since version 3.3 and will be removed in 4.0. Use the console.error event instead.
- */
- const EXCEPTION = 'console.exception';
-
/**
* The ERROR event occurs when an uncaught exception or error appears.
*
* to modify the thrown exception.
*
* @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
- *
- * @var string
*/
const ERROR = 'console.error';
}
namespace Symfony\Component\Console\DependencyInjection;
use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\TypedReference;
/**
* Registers console commands.
*/
class AddConsoleCommandPass implements CompilerPassInterface
{
+ private $commandLoaderServiceId;
+ private $commandTag;
+
+ public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command')
+ {
+ $this->commandLoaderServiceId = $commandLoaderServiceId;
+ $this->commandTag = $commandTag;
+ }
+
public function process(ContainerBuilder $container)
{
- $commandServices = $container->findTaggedServiceIds('console.command', true);
+ $commandServices = $container->findTaggedServiceIds($this->commandTag, true);
+ $lazyCommandMap = array();
+ $lazyCommandRefs = array();
$serviceIds = array();
foreach ($commandServices as $id => $tags) {
$definition = $container->getDefinition($id);
$class = $container->getParameterBag()->resolveValue($definition->getClass());
- if (!$r = $container->getReflectionClass($class)) {
- throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
- }
- if (!$r->isSubclassOf(Command::class)) {
- throw new InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be a subclass of "%s".', $id, Command::class));
+ if (isset($tags[0]['command'])) {
+ $commandName = $tags[0]['command'];
+ } else {
+ if (!$r = $container->getReflectionClass($class)) {
+ throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
+ }
+ if (!$r->isSubclassOf(Command::class)) {
+ throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
+ }
+ $commandName = $class::getDefaultName();
}
- $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class));
- if ($container->hasAlias($commandId) || isset($serviceIds[$commandId])) {
- $commandId = $commandId.'_'.$id;
+ if (null === $commandName) {
+ if (!$definition->isPublic() || $definition->isPrivate()) {
+ $commandId = 'console.command.public_alias.'.$id;
+ $container->setAlias($commandId, $id)->setPublic(true);
+ $id = $commandId;
+ }
+ $serviceIds[] = $id;
+
+ continue;
}
- if (!$definition->isPublic()) {
- $container->setAlias($commandId, $id);
- $id = $commandId;
+
+ unset($tags[0]);
+ $lazyCommandMap[$commandName] = $id;
+ $lazyCommandRefs[$id] = new TypedReference($id, $class);
+ $aliases = array();
+
+ foreach ($tags as $tag) {
+ if (isset($tag['command'])) {
+ $aliases[] = $tag['command'];
+ $lazyCommandMap[$tag['command']] = $id;
+ }
}
- $serviceIds[$commandId] = $id;
+ $definition->addMethodCall('setName', array($commandName));
+
+ if ($aliases) {
+ $definition->addMethodCall('setAliases', array($aliases));
+ }
}
+ $container
+ ->register($this->commandLoaderServiceId, ContainerCommandLoader::class)
+ ->setPublic(true)
+ ->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap));
+
$container->setParameter('console.command.ids', $serviceIds);
}
}
{
const GLOBAL_NAMESPACE = '_global';
- /**
- * @var Application
- */
private $application;
-
- /**
- * @var null|string
- */
private $namespace;
+ private $showHidden;
/**
* @var array
*/
private $aliases;
- /**
- * @var bool
- */
- private $showHidden;
-
- /**
- * Constructor.
- *
- * @param Application $application
- * @param string|null $namespace
- * @param bool $showHidden
- */
- public function __construct(Application $application, $namespace = null, $showHidden = false)
+ public function __construct(Application $application, string $namespace = null, bool $showHidden = false)
{
$this->application = $application;
$this->namespace = $namespace;
}
}
- /**
- * @param array $commands
- *
- * @return array
- */
- private function sortCommands(array $commands)
+ private function sortCommands(array $commands): array
{
$namespacedCommands = array();
$globalCommands = array();
/**
* Describes an InputArgument instance.
*
- * @param InputArgument $argument
- * @param array $options
- *
* @return string|mixed
*/
abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
/**
* Describes an InputOption instance.
*
- * @param InputOption $option
- * @param array $options
- *
* @return string|mixed
*/
abstract protected function describeInputOption(InputOption $option, array $options = array());
/**
* Describes an InputDefinition instance.
*
- * @param InputDefinition $definition
- * @param array $options
- *
* @return string|mixed
*/
abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
/**
* Describes a Command instance.
*
- * @param Command $command
- * @param array $options
- *
* @return string|mixed
*/
abstract protected function describeCommand(Command $command, array $options = array());
/**
* Describes an Application instance.
*
- * @param Application $application
- * @param array $options
- *
* @return string|mixed
*/
abstract protected function describeApplication(Application $application, array $options = array());
interface DescriptorInterface
{
/**
- * Describes an InputArgument instance.
+ * Describes an object if supported.
*
* @param OutputInterface $output
* @param object $object
/**
* Writes data as json.
*
- * @param array $data
- * @param array $options
- *
* @return array|string
*/
private function writeData(array $data, array $options)
}
/**
- * @param InputArgument $argument
- *
* @return array
*/
private function getInputArgumentData(InputArgument $argument)
}
/**
- * @param InputOption $option
- *
* @return array
*/
private function getInputOptionData(InputOption $option)
{
return array(
'name' => '--'.$option->getName(),
- 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
+ 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
'accept_value' => $option->acceptValue(),
'is_value_required' => $option->isValueRequired(),
'is_multiple' => $option->isArray(),
}
/**
- * @param InputDefinition $definition
- *
* @return array
*/
private function getInputDefinitionData(InputDefinition $definition)
}
/**
- * @param Command $command
- *
* @return array
*/
private function getCommandData(Command $command)
{
$name = '--'.$option->getName();
if ($option->getShortcut()) {
- $name .= '|-'.implode('|-', explode('|', $option->getShortcut())).'';
+ $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).'';
}
$this->write(
$this->writeText('<comment>Usage:</comment>', $options);
foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
$this->writeText("\n");
- $this->writeText(' '.$usage, $options);
+ $this->writeText(' '.OutputFormatter::escape($usage), $options);
}
$this->writeText("\n");
/**
* Formats command aliases to show them in the command description.
- *
- * @param Command $command
- *
- * @return string
*/
- private function getCommandAliasesText($command)
+ private function getCommandAliasesText(Command $command): string
{
$text = '';
$aliases = $command->getAliases();
* Formats input option/argument default value.
*
* @param mixed $default
- *
- * @return string
*/
- private function formatDefaultValue($default)
+ private function formatDefaultValue($default): string
{
if (INF === $default) {
return 'INF';
/**
* @param (Command|string)[] $commands
- *
- * @return int
*/
- private function getColumnWidth(array $commands)
+ private function getColumnWidth(array $commands): int
{
$widths = array();
/**
* @param InputOption[] $options
- *
- * @return int
*/
- private function calculateTotalWidthForOptions($options)
+ private function calculateTotalWidthForOptions(array $options): int
{
$totalWidth = 0;
foreach ($options as $option) {
class XmlDescriptor extends Descriptor
{
/**
- * @param InputDefinition $definition
- *
* @return \DOMDocument
*/
public function getInputDefinitionDocument(InputDefinition $definition)
}
/**
- * @param Command $command
- *
* @return \DOMDocument
*/
public function getCommandDocument(Command $command)
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->appendChild($rootXml = $dom->createElement('symfony'));
- if ($application->getName() !== 'UNKNOWN') {
+ if ('UNKNOWN' !== $application->getName()) {
$rootXml->setAttribute('name', $application->getName());
- if ($application->getVersion() !== 'UNKNOWN') {
+ if ('UNKNOWN' !== $application->getVersion()) {
$rootXml->setAttribute('version', $application->getVersion());
}
}
/**
* Appends document children to parent node.
- *
- * @param \DOMNode $parentNode
- * @param \DOMNode $importedParent
*/
private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
{
/**
* Writes DOM document.
*
- * @param \DOMDocument $dom
- *
* @return \DOMDocument|string
*/
private function writeDocument(\DOMDocument $dom)
$this->write($dom->saveXML());
}
- /**
- * @param InputArgument $argument
- *
- * @return \DOMDocument
- */
- private function getInputArgumentDocument(InputArgument $argument)
+ private function getInputArgumentDocument(InputArgument $argument): \DOMDocument
{
$dom = new \DOMDocument('1.0', 'UTF-8');
return $dom;
}
- /**
- * @param InputOption $option
- *
- * @return \DOMDocument
- */
- private function getInputOptionDocument(InputOption $option)
+ private function getInputOptionDocument(InputOption $option): \DOMDocument
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$pos = strpos($option->getShortcut(), '|');
if (false !== $pos) {
$objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
- $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
+ $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
} else {
$objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
}
/**
* Indicates if the command should be run or skipped.
- *
- * @var bool
*/
private $commandShouldRun = true;
namespace Symfony\Component\Console\Event;
use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
private $error;
private $exitCode;
- public function __construct(InputInterface $input, OutputInterface $output, $error, Command $command = null)
+ public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null)
{
parent::__construct($command, $input, $output);
- $this->setError($error);
+ $this->error = $error;
}
- /**
- * Returns the thrown error/exception.
- *
- * @return \Throwable
- */
- public function getError()
+ public function getError(): \Throwable
{
return $this->error;
}
- /**
- * Replaces the thrown error/exception.
- *
- * @param \Throwable $error
- */
- public function setError($error)
+ public function setError(\Throwable $error): void
{
- if (!$error instanceof \Throwable && !$error instanceof \Exception) {
- throw new InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', is_object($error) ? get_class($error) : gettype($error)));
- }
-
$this->error = $error;
}
- /**
- * Sets the exit code.
- *
- * @param int $exitCode The command exit code
- */
- public function setExitCode($exitCode)
+ public function setExitCode(int $exitCode): void
{
- $this->exitCode = (int) $exitCode;
+ $this->exitCode = $exitCode;
$r = new \ReflectionProperty($this->error, 'code');
$r->setAccessible(true);
$r->setValue($this->error, $this->exitCode);
}
- /**
- * Gets the exit code.
- *
- * @return int The command exit code
- */
- public function getExitCode()
+ public function getExitCode(): int
{
- return null !== $this->exitCode ? $this->exitCode : ($this->error->getCode() ?: 1);
+ return null !== $this->exitCode ? $this->exitCode : (is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
}
}
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Console\Event;
-
-@trigger_error(sprintf('The "%s" class is deprecated since version 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', ConsoleExceptionEvent::class), E_USER_DEPRECATED);
-
-use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-/**
- * Allows to handle exception thrown in a command.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- *
- * @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead.
- */
-class ConsoleExceptionEvent extends ConsoleEvent
-{
- private $exception;
- private $exitCode;
-
- public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
- {
- parent::__construct($command, $input, $output);
-
- $this->setException($exception);
- $this->exitCode = (int) $exitCode;
- }
-
- /**
- * Returns the thrown exception.
- *
- * @return \Exception The thrown exception
- */
- public function getException()
- {
- return $this->exception;
- }
-
- /**
- * Replaces the thrown exception.
- *
- * This exception will be thrown if no response is set in the event.
- *
- * @param \Exception $exception The thrown exception
- */
- public function setException(\Exception $exception)
- {
- $this->exception = $exception;
- }
-
- /**
- * Gets the exit code.
- *
- * @return int The command exit code
- */
- public function getExitCode()
- {
- return $this->exitCode;
- }
-}
*/
class ConsoleTerminateEvent extends ConsoleEvent
{
- /**
- * The exit code of the command.
- *
- * @var int
- */
private $exitCode;
- public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
+ public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode)
{
parent::__construct($command, $input, $output);
$error = $event->getError();
if (!$inputString = $this->getInputString($event)) {
- return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => $error->getMessage()));
+ return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('exception' => $error, 'message' => $error->getMessage()));
}
- $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $inputString, 'message' => $error->getMessage()));
+ $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()));
}
public function onConsoleTerminate(ConsoleTerminateEvent $event)
}
if (!$inputString = $this->getInputString($event)) {
- return $this->logger->error('The console exited with code "{code}"', array('code' => $exitCode));
+ return $this->logger->debug('The console exited with code "{code}"', array('code' => $exitCode));
}
- $this->logger->error('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode));
+ $this->logger->debug('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode));
}
public static function getSubscribedEvents()
private $alternatives;
/**
- * @param string $message Exception message to throw
- * @param array $alternatives List of similar defined names
- * @param int $code Exception code
- * @param Exception $previous previous exception used for the exception chaining
+ * @param string $message Exception message to throw
+ * @param array $alternatives List of similar defined names
+ * @param int $code Exception code
+ * @param \Exception $previous Previous exception used for the exception chaining
*/
- public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
+ public function __construct(string $message, array $alternatives = array(), int $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
if ('\\' === substr($text, -1)) {
$len = strlen($text);
$text = rtrim($text, '\\');
- $text .= str_repeat('<<', $len - strlen($text));
+ $text = str_replace("\0", '', $text);
+ $text .= str_repeat("\0", $len - strlen($text));
}
return $text;
* @param bool $decorated Whether this formatter should actually decorate strings
* @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
*/
- public function __construct($decorated = false, array $styles = array())
+ public function __construct(bool $decorated = false, array $styles = array())
{
- $this->decorated = (bool) $decorated;
+ $this->decorated = $decorated;
$this->setStyle('error', new OutputFormatterStyle('white', 'red'));
$this->setStyle('info', new OutputFormatterStyle('green'));
$output .= $this->applyCurrentStyle(substr($message, $offset));
- if (false !== strpos($output, '<<')) {
- return strtr($output, array('\\<' => '<', '<<' => '\\'));
+ if (false !== strpos($output, "\0")) {
+ return strtr($output, array("\0" => '\\', '\\<' => '<'));
}
return str_replace('\\<', '<', $output);
/**
* Tries to create new style instance from string.
*
- * @param string $string
- *
- * @return OutputFormatterStyle|false false if string is not format string
+ * @return OutputFormatterStyle|false False if string is not format string
*/
- private function createStyleFromString($string)
+ private function createStyleFromString(string $string)
{
if (isset($this->styles[$string])) {
return $this->styles[$string];
preg_match_all('([^,;]+)', $match[1], $options);
$options = array_shift($options);
foreach ($options as $option) {
- try {
- $style->setOption($option);
- } catch (\InvalidArgumentException $e) {
- @trigger_error(sprintf('Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), E_USER_DEPRECATED);
-
- return false;
- }
+ $style->setOption($option);
}
} else {
return false;
/**
* Applies current style from stack to text, if must be applied.
- *
- * @param string $text Input text
- *
- * @return string Styled text
*/
- private function applyCurrentStyle($text)
+ private function applyCurrentStyle(string $text): string
{
return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
}
* @param string|null $background The style background color name
* @param array $options The style options
*/
- public function __construct($foreground = null, $background = null, array $options = array())
+ public function __construct(string $foreground = null, string $background = null, array $options = array())
{
if (null !== $foreground) {
$this->setForeground($foreground);
}
/**
- * Sets multiple style options at once.
- *
- * @param array $options
+ * {@inheritdoc}
*/
public function setOptions(array $options)
{
/**
* Sets multiple style options at once.
- *
- * @param array $options
*/
public function setOptions(array $options);
*/
private $styles;
- /**
- * @var OutputFormatterStyleInterface
- */
private $emptyStyle;
- /**
- * Constructor.
- *
- * @param OutputFormatterStyleInterface|null $emptyStyle
- */
public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
{
$this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
/**
* Pushes a style in the stack.
- *
- * @param OutputFormatterStyleInterface $style
*/
public function push(OutputFormatterStyleInterface $style)
{
/**
* Pops a style from the stack.
*
- * @param OutputFormatterStyleInterface|null $style
- *
* @return OutputFormatterStyleInterface
*
* @throws InvalidArgumentException When style tags incorrectly nested
}
/**
- * @param OutputFormatterStyleInterface $emptyStyle
- *
* @return $this
*/
public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
*/
private $descriptors = array();
- /**
- * Constructor.
- */
public function __construct()
{
$this
protected $helperSet = null;
/**
- * Sets the helper set associated with this helper.
- *
- * @param HelperSet $helperSet A HelperSet instance
+ * {@inheritdoc}
*/
public function setHelperSet(HelperSet $helperSet = null)
{
}
/**
- * Gets the helper set associated with this helper.
- *
- * @return HelperSet|null
+ * {@inheritdoc}
*/
public function getHelperSet()
{
{
/**
* Sets the helper set associated with this helper.
- *
- * @param HelperSet $helperSet A HelperSet instance
*/
public function setHelperSet(HelperSet $helperSet = null);
private $command;
/**
- * Constructor.
- *
* @param Helper[] $helpers An array of helper
*/
public function __construct(array $helpers = array())
return $this->helpers[$name];
}
- /**
- * Sets the command associated with this helper set.
- *
- * @param Command $command A Command instance
- */
public function setCommand(Command $command = null)
{
$this->command = $command;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
-use Symfony\Component\Process\ProcessBuilder;
/**
* The ProcessHelper class provides helpers to run external processes.
$formatter = $this->getHelperSet()->get('debug_formatter');
- if (is_array($cmd)) {
- $process = ProcessBuilder::create($cmd)->getProcess();
- } elseif ($cmd instanceof Process) {
+ if ($cmd instanceof Process) {
$process = $cmd;
} else {
$process = new Process($cmd);
*/
final class ProgressBar
{
- // options
private $barWidth = 28;
private $barChar;
private $emptyBarChar = '-';
private $format;
private $internalFormat;
private $redrawFreq = 1;
-
- /**
- * @var OutputInterface
- */
private $output;
private $step = 0;
private $max;
* @param OutputInterface $output An OutputInterface instance
* @param int $max Maximum steps (0 if unknown)
*/
- public function __construct(OutputInterface $output, $max = 0)
+ public function __construct(OutputInterface $output, int $max = 0)
{
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
* @param string $name The placeholder name (including the delimiter char like %)
* @param callable $callable A PHP callable
*/
- public static function setPlaceholderFormatterDefinition($name, callable $callable)
+ public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void
{
if (!self::$formatters) {
self::$formatters = self::initPlaceholderFormatters();
*
* @return callable|null A PHP callable
*/
- public static function getPlaceholderFormatterDefinition($name)
+ public static function getPlaceholderFormatterDefinition(string $name): ?callable
{
if (!self::$formatters) {
self::$formatters = self::initPlaceholderFormatters();
* @param string $name The format name
* @param string $format A format string
*/
- public static function setFormatDefinition($name, $format)
+ public static function setFormatDefinition(string $name, string $format): void
{
if (!self::$formats) {
self::$formats = self::initFormats();
*
* @return string|null A format string
*/
- public static function getFormatDefinition($name)
+ public static function getFormatDefinition(string $name): ?string
{
if (!self::$formats) {
self::$formats = self::initFormats();
* @param string $message The text to associate with the placeholder
* @param string $name The name of the placeholder
*/
- public function setMessage($message, $name = 'message')
+ public function setMessage(string $message, string $name = 'message')
{
$this->messages[$name] = $message;
}
- public function getMessage($name = 'message')
+ public function getMessage(string $name = 'message')
{
return $this->messages[$name];
}
- /**
- * Gets the progress bar start time.
- *
- * @return int The progress bar start time
- */
- public function getStartTime()
+ public function getStartTime(): int
{
return $this->startTime;
}
- /**
- * Gets the progress bar maximal steps.
- *
- * @return int The progress bar max steps
- */
- public function getMaxSteps()
+ public function getMaxSteps(): int
{
return $this->max;
}
- /**
- * Gets the current step position.
- *
- * @return int The progress bar step
- */
- public function getProgress()
+ public function getProgress(): int
{
return $this->step;
}
- /**
- * Gets the progress bar step width.
- *
- * @return int The progress bar step width
- */
- private function getStepWidth()
+ private function getStepWidth(): int
{
return $this->stepWidth;
}
- /**
- * Gets the current progress bar percent.
- *
- * @return float The current progress bar percent
- */
- public function getProgressPercent()
+ public function getProgressPercent(): float
{
return $this->percent;
}
- /**
- * Sets the progress bar width.
- *
- * @param int $size The progress bar size
- */
- public function setBarWidth($size)
+ public function setBarWidth(int $size)
{
- $this->barWidth = max(1, (int) $size);
+ $this->barWidth = max(1, $size);
}
- /**
- * Gets the progress bar width.
- *
- * @return int The progress bar size
- */
- public function getBarWidth()
+ public function getBarWidth(): int
{
return $this->barWidth;
}
- /**
- * Sets the bar character.
- *
- * @param string $char A character
- */
- public function setBarCharacter($char)
+ public function setBarCharacter(string $char)
{
$this->barChar = $char;
}
- /**
- * Gets the bar character.
- *
- * @return string A character
- */
- public function getBarCharacter()
+ public function getBarCharacter(): string
{
if (null === $this->barChar) {
return $this->max ? '=' : $this->emptyBarChar;
return $this->barChar;
}
- /**
- * Sets the empty bar character.
- *
- * @param string $char A character
- */
- public function setEmptyBarCharacter($char)
+ public function setEmptyBarCharacter(string $char)
{
$this->emptyBarChar = $char;
}
- /**
- * Gets the empty bar character.
- *
- * @return string A character
- */
- public function getEmptyBarCharacter()
+ public function getEmptyBarCharacter(): string
{
return $this->emptyBarChar;
}
- /**
- * Sets the progress bar character.
- *
- * @param string $char A character
- */
- public function setProgressCharacter($char)
+ public function setProgressCharacter(string $char)
{
$this->progressChar = $char;
}
- /**
- * Gets the progress bar character.
- *
- * @return string A character
- */
- public function getProgressCharacter()
+ public function getProgressCharacter(): string
{
return $this->progressChar;
}
- /**
- * Sets the progress bar format.
- *
- * @param string $format The format
- */
- public function setFormat($format)
+ public function setFormat(string $format)
{
$this->format = null;
$this->internalFormat = $format;
*
* @param int|float $freq The frequency in steps
*/
- public function setRedrawFrequency($freq)
+ public function setRedrawFrequency(int $freq)
{
- $this->redrawFreq = max((int) $freq, 1);
+ $this->redrawFreq = max($freq, 1);
}
/**
*
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
*/
- public function start($max = null)
+ public function start(int $max = null)
{
$this->startTime = time();
$this->step = 0;
*
* @param int $step Number of steps to advance
*/
- public function advance($step = 1)
+ public function advance(int $step = 1)
{
$this->setProgress($this->step + $step);
}
/**
* Sets whether to overwrite the progressbar, false for new line.
- *
- * @param bool $overwrite
*/
- public function setOverwrite($overwrite)
+ public function setOverwrite(bool $overwrite)
{
- $this->overwrite = (bool) $overwrite;
+ $this->overwrite = $overwrite;
}
- /**
- * Sets the current progress.
- *
- * @param int $step The current progress
- */
- public function setProgress($step)
+ public function setProgress(int $step)
{
- $step = (int) $step;
-
if ($this->max && $step > $this->max) {
$this->max = $step;
} elseif ($step < 0) {
/**
* Finishes the progress output.
*/
- public function finish()
+ public function finish(): void
{
if (!$this->max) {
$this->max = $this->step;
/**
* Outputs the current progress string.
*/
- public function display()
+ public function display(): void
{
if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
return;
* while a progress bar is running.
* Call display() to show the progress bar again.
*/
- public function clear()
+ public function clear(): void
{
if (!$this->overwrite) {
return;
$this->overwrite('');
}
- /**
- * Sets the progress bar format.
- *
- * @param string $format The format
- */
- private function setRealFormat($format)
+ private function setRealFormat(string $format)
{
// try to use the _nomax variant if available
if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
$this->formatLineCount = substr_count($this->format, "\n");
}
- /**
- * Sets the progress bar maximal steps.
- *
- * @param int $max The progress bar max steps
- */
- private function setMaxSteps($max)
+ private function setMaxSteps(int $max)
{
- $this->max = max(0, (int) $max);
- $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
+ $this->max = max(0, $max);
+ $this->stepWidth = $this->max ? Helper::strlen((string) $this->max) : 4;
}
/**
* Overwrites a previous message to the output.
- *
- * @param string $message The message
*/
- private function overwrite($message)
+ private function overwrite(string $message): void
{
if ($this->overwrite) {
if (!$this->firstRun) {
$this->output->write($message);
}
- private function determineBestFormat()
+ private function determineBestFormat(): string
{
switch ($this->output->getVerbosity()) {
// OutputInterface::VERBOSITY_QUIET: display is disabled anyway
}
}
- private static function initPlaceholderFormatters()
+ private static function initPlaceholderFormatters(): array
{
return array(
'bar' => function (ProgressBar $bar, OutputInterface $output) {
);
}
- private static function initFormats()
+ private static function initFormats(): array
{
return array(
'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
);
}
- /**
- * @return string
- */
- private function buildLine()
+ private function buildLine(): string
{
$regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i";
$callback = function ($matches) {
* @param int $indicatorChangeInterval Change interval in milliseconds
* @param array|null $indicatorValues Animated indicator characters
*/
- public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
+ public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null)
{
$this->output = $output;
/**
* Overwrites a previous message to the output.
- *
- * @param string $message The message
*/
- private function overwrite($message)
+ private function overwrite(string $message)
{
if ($this->output->isDecorated()) {
$this->output->write("\x0D\x1B[2K");
namespace Symfony\Component\Console\Helper;
-use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
+use Symfony\Component\Console\Formatter\OutputFormatter;
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Question\ChoiceQuestion;
/**
* Asks a question to the user.
*
- * @param InputInterface $input An InputInterface instance
- * @param OutputInterface $output An OutputInterface instance
- * @param Question $question The question to ask
- *
* @return mixed The user answer
*
* @throws RuntimeException If there is no data to read in the input stream
}
if (!$input->isInteractive()) {
+ if ($question instanceof ChoiceQuestion) {
+ $choices = $question->getChoices();
+
+ return $choices[$question->getDefault()];
+ }
+
return $question->getDefault();
}
return $this->validateAttempts($interviewer, $output, $question);
}
- /**
- * Sets the input stream to read from when interacting with the user.
- *
- * This is mainly useful for testing purpose.
- *
- * @deprecated since version 3.2, to be removed in 4.0. Use
- * StreamableInputInterface::setStream() instead.
- *
- * @param resource $stream The input stream
- *
- * @throws InvalidArgumentException In case the stream is not a resource
- */
- public function setInputStream($stream)
- {
- @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::setStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED);
-
- if (!is_resource($stream)) {
- throw new InvalidArgumentException('Input stream must be a valid resource.');
- }
-
- $this->inputStream = $stream;
- }
-
- /**
- * Returns the helper's input stream.
- *
- * @deprecated since version 3.2, to be removed in 4.0. Use
- * StreamableInputInterface::getStream() instead.
- *
- * @return resource
- */
- public function getInputStream()
- {
- if (0 === func_num_args() || func_get_arg(0)) {
- @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::getStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED);
- }
-
- return $this->inputStream;
- }
-
/**
* {@inheritdoc}
*/
/**
* Asks the question to the user.
*
- * @param OutputInterface $output
- * @param Question $question
- *
* @return bool|mixed|null|string
*
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
$ret = trim($ret);
}
} else {
- $ret = trim($this->autocomplete($output, $question, $inputStream));
+ $ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
}
$ret = strlen($ret) > 0 ? $ret : $question->getDefault();
/**
* Outputs the question prompt.
- *
- * @param OutputInterface $output
- * @param Question $question
*/
protected function writePrompt(OutputInterface $output, Question $question)
{
/**
* Outputs an error message.
- *
- * @param OutputInterface $output
- * @param \Exception $error
*/
protected function writeError(OutputInterface $output, \Exception $error)
{
* @param OutputInterface $output
* @param Question $question
* @param resource $inputStream
- *
- * @return string
*/
- private function autocomplete(OutputInterface $output, Question $question, $inputStream)
+ private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete): string
{
- $autocomplete = $question->getAutocompleterValues();
$ret = '';
$i = 0;
$output->write("\033[1D");
}
- if ($i === 0) {
+ if (0 === $i) {
$ofs = -1;
$matches = $autocomplete;
$numMatches = count($matches);
foreach ($autocomplete as $value) {
// If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
- if (0 === strpos($value, $ret) && $i !== strlen($value)) {
+ if (0 === strpos($value, $ret)) {
$matches[$numMatches++] = $value;
}
}
// Save cursor position
$output->write("\0337");
// Write highlighted text
- $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
+ $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
// Restore cursor position
$output->write("\0338");
}
* @param OutputInterface $output An Output instance
* @param resource $inputStream The handler resource
*
- * @return string The answer
- *
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
*/
- private function getHiddenResponse(OutputInterface $output, $inputStream)
+ private function getHiddenResponse(OutputInterface $output, $inputStream): string
{
if ('\\' === DIRECTORY_SEPARATOR) {
$exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
}
if (false !== $shell = $this->getShell()) {
- $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
+ $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
$command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
$value = rtrim(shell_exec($command));
$output->writeln('');
/**
* Returns whether Stty is available or not.
- *
- * @return bool
*/
- private function hasSttyAvailable()
+ private function hasSttyAvailable(): bool
{
if (null !== self::$stty) {
return self::$stty;
exec('stty 2>&1', $output, $exitcode);
- return self::$stty = $exitcode === 0;
+ return self::$stty = 0 === $exitcode;
}
}
namespace Symfony\Component\Console\Helper;
-use Symfony\Component\Console\Exception\LogicException;
-use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\ConfirmationQuestion;
*/
class SymfonyQuestionHelper extends QuestionHelper
{
- /**
- * {@inheritdoc}
- */
- public function ask(InputInterface $input, OutputInterface $output, Question $question)
- {
- $validator = $question->getValidator();
- $question->setValidator(function ($value) use ($validator) {
- if (null !== $validator) {
- $value = $validator($value);
- } else {
- // make required
- if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
- throw new LogicException('A value is required.');
- }
- }
-
- return $value;
- });
-
- return parent::ask($input, $output, $question);
- }
-
/**
* {@inheritdoc}
*/
{
/**
* Table headers.
- *
- * @var array
*/
private $headers = array();
/**
* Table rows.
- *
- * @var array
*/
private $rows = array();
/**
* Column widths cache.
- *
- * @var array
*/
private $effectiveColumnWidths = array();
/**
* Number of columns cache.
*
- * @var array
+ * @var int
*/
private $numberOfColumns;
* Renders table to output.
*
* Example:
+ * <code>
* +---------------+-----------------------+------------------+
* | ISBN | Title | Author |
* +---------------+-----------------------+------------------+
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
* | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
* +---------------+-----------------------+------------------+
+ * </code>
*/
public function render()
{
/**
* Renders horizontal header separator.
*
- * Example: +-----+-----------+-------+
+ * Example: <code>+-----+-----------+-------+</code>
*/
private function renderRowSeparator()
{
/**
* Renders table row.
*
- * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
- *
- * @param array $row
- * @param string $cellFormat
+ * Example: <code>| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |</code>
*/
- private function renderRow(array $row, $cellFormat)
+ private function renderRow(array $row, string $cellFormat)
{
if (empty($row)) {
return;
/**
* Renders table cell with padding.
- *
- * @param array $row
- * @param int $column
- * @param string $cellFormat
*/
- private function renderCell(array $row, $column, $cellFormat)
+ private function renderCell(array $row, int $column, string $cellFormat)
{
$cell = isset($row[$column]) ? $row[$column] : '';
$width = $this->effectiveColumnWidths[$column];
/**
* fill rows that contains rowspan > 1.
*
- * @param array $rows
- * @param int $line
- *
- * @return array
+ * @throws InvalidArgumentException
*/
- private function fillNextRows($rows, $line)
+ private function fillNextRows(array $rows, int $line): array
{
$unmergedRows = array();
foreach ($rows[$line] as $column => $cell) {
+ if (null !== $cell && !$cell instanceof TableCell && !is_scalar($cell) && !(is_object($cell) && method_exists($cell, '__toString'))) {
+ throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing __toString, %s given.', gettype($cell)));
+ }
if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
$nbLines = $cell->getRowspan() - 1;
$lines = array($cell);
/**
* fill cells for a row that contains colspan > 1.
- *
- * @param array $row
- *
- * @return array
*/
private function fillCells($row)
{
return $newRow ?: $row;
}
- /**
- * @param array $rows
- * @param int $line
- *
- * @return array
- */
- private function copyRow($rows, $line)
+ private function copyRow(array $rows, int $line): array
{
$row = $rows[$line];
foreach ($row as $cellKey => $cellValue) {
/**
* Gets number of columns by row.
- *
- * @param array $row
- *
- * @return int
*/
- private function getNumberOfColumns(array $row)
+ private function getNumberOfColumns(array $row): int
{
$columns = count($row);
foreach ($row as $column) {
/**
* Gets list of columns for the given row.
- *
- * @param array $row
- *
- * @return array
*/
- private function getRowColumns($row)
+ private function getRowColumns(array $row): array
{
$columns = range(0, $this->numberOfColumns - 1);
foreach ($row as $cellKey => $cell) {
/**
* Calculates columns widths.
- *
- * @param array $rows
*/
- private function calculateColumnsWidth($rows)
+ private function calculateColumnsWidth(array $rows)
{
for ($column = 0; $column < $this->numberOfColumns; ++$column) {
$lengths = array();
}
}
- /**
- * Gets column width.
- *
- * @return int
- */
- private function getColumnSeparatorWidth()
+ private function getColumnSeparatorWidth(): int
{
return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
}
- /**
- * Gets cell width.
- *
- * @param array $row
- * @param int $column
- *
- * @return int
- */
- private function getCellWidth(array $row, $column)
+ private function getCellWidth(array $row, int $column): int
{
$cellWidth = 0;
*/
class TableCell
{
- /**
- * @var string
- */
private $value;
-
- /**
- * @var array
- */
private $options = array(
'rowspan' => 1,
'colspan' => 1,
);
- /**
- * @param string $value
- * @param array $options
- */
- public function __construct($value = '', array $options = array())
+ public function __construct(string $value = '', array $options = array())
{
- if (is_numeric($value) && !is_string($value)) {
- $value = (string) $value;
- }
-
$this->value = $value;
// check option names
*/
class TableSeparator extends TableCell
{
- /**
- * @param array $options
- */
public function __construct(array $options = array())
{
parent::__construct('', $options);
private $parsed;
/**
- * Constructor.
- *
* @param array|null $argv An array of parameters from the CLI (in the argv format)
* @param InputDefinition|null $definition A InputDefinition instance
*/
if (false !== $pos = strpos($name, '=')) {
if (0 === strlen($value = substr($name, $pos + 1))) {
- // if no value after "=" then substr() returns "" since php7 only, false before
- // see http://php.net/manual/fr/migration70.incompatible.php#119151
- if (\PHP_VERSION_ID < 70000 && false === $value) {
- $value = '';
- }
array_unshift($this->parsed, $value);
}
$this->addLongOption(substr($name, 0, $pos), $value);
$values = (array) $values;
foreach ($this->tokens as $token) {
- if ($onlyParams && $token === '--') {
+ if ($onlyParams && '--' === $token) {
return false;
}
foreach ($values as $value) {
- if ($token === $value || 0 === strpos($token, $value.'=')) {
+ // Options with values:
+ // For long options, test for '--option=' at beginning
+ // For short options, test for '-o' at beginning
+ $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
+ if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
return true;
}
}
while (0 < count($tokens)) {
$token = array_shift($tokens);
- if ($onlyParams && $token === '--') {
+ if ($onlyParams && '--' === $token) {
return false;
}
foreach ($values as $value) {
- if ($token === $value || 0 === strpos($token, $value.'=')) {
- if (false !== $pos = strpos($token, '=')) {
- return substr($token, $pos + 1);
- }
-
+ if ($token === $value) {
return array_shift($tokens);
}
+ // Options with values:
+ // For long options, test for '--option=' at beginning
+ // For short options, test for '-o' at beginning
+ $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
+ if ('' !== $leading && 0 === strpos($token, $leading)) {
+ return substr($token, strlen($leading));
+ }
}
}
return $match[1].$this->escapeToken($match[2]);
}
- if ($token && $token[0] !== '-') {
+ if ($token && '-' !== $token[0]) {
return $this->escapeToken($token);
}
{
private $parameters;
- /**
- * Constructor.
- *
- * @param array $parameters An array of parameters
- * @param InputDefinition|null $definition A InputDefinition instance
- */
public function __construct(array $parameters, InputDefinition $definition = null)
{
$this->parameters = $parameters;
$v = $k;
}
- if ($onlyParams && $v === '--') {
+ if ($onlyParams && '--' === $v) {
return false;
}
$values = (array) $values;
foreach ($this->parameters as $k => $v) {
- if ($onlyParams && ($k === '--' || (is_int($k) && $v === '--'))) {
+ if ($onlyParams && ('--' === $k || (is_int($k) && '--' === $v))) {
return false;
}
$params = array();
foreach ($this->parameters as $param => $val) {
if ($param && '-' === $param[0]) {
- $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
+ if (is_array($val)) {
+ foreach ($val as $v) {
+ $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
+ }
+ } else {
+ $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
+ }
} else {
- $params[] = $this->escapeToken($val);
+ $params[] = is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val);
}
}
protected function parse()
{
foreach ($this->parameters as $key => $value) {
- if ($key === '--') {
+ if ('--' === $key) {
return;
}
if (0 === strpos($key, '--')) {
*/
abstract class Input implements InputInterface, StreamableInputInterface
{
- /**
- * @var InputDefinition
- */
protected $definition;
protected $stream;
protected $options = array();
protected $arguments = array();
protected $interactive = true;
- /**
- * Constructor.
- *
- * @param InputDefinition|null $definition A InputDefinition instance
- */
public function __construct(InputDefinition $definition = null)
{
if (null === $definition) {
private $description;
/**
- * Constructor.
- *
* @param string $name The argument name
* @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL
* @param string $description A description text
*
* @throws InvalidArgumentException When argument mode is not valid
*/
- public function __construct($name, $mode = null, $description = '', $default = null)
+ public function __construct(string $name, int $mode = null, string $description = '', $default = null)
{
if (null === $mode) {
$mode = self::OPTIONAL;
- } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
+ } elseif ($mode > 7 || $mode < 1) {
throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
}
private $shortcuts;
/**
- * Constructor.
- *
* @param array $definition An array of InputArgument and InputOption instance
*/
public function __construct(array $definition = array())
/**
* Sets the definition of the input.
- *
- * @param array $definition The definition array
*/
public function setDefinition(array $definition)
{
}
/**
- * Adds an InputArgument object.
- *
- * @param InputArgument $argument An InputArgument object
- *
* @throws LogicException When incorrect argument is given
*/
public function addArgument(InputArgument $argument)
}
/**
- * Adds an InputOption object.
- *
- * @param InputOption $option An InputOption object
- *
* @throws LogicException When option given already exist
*/
public function addOption(InputOption $option)
/**
* Gets an InputOption by shortcut.
*
- * @param string $shortcut the Shortcut name
+ * @param string $shortcut The Shortcut name
*
* @return InputOption An InputOption object
*/
/**
* Returns the first argument from the raw parameters (not parsed).
*
- * @return string The value of the first argument or null otherwise
+ * @return string|null The value of the first argument or null otherwise
*/
public function getFirstArgument();
*
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
+ * Does not necessarily return the correct result for short options
+ * when multiple flags are combined in the same option.
*
* @param string|array $values The values to look for in the raw parameters (can be an array)
* @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
*
* This method is to be used to introspect the input parameters
* before they have been validated. It must be used carefully.
+ * Does not necessarily return the correct result for short options
+ * when multiple flags are combined in the same option.
*
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
* @param mixed $default The default value to return if no result is found
/**
* Binds the current Input instance with the given arguments and options.
- *
- * @param InputDefinition $definition A InputDefinition instance
*/
public function bind(InputDefinition $definition);
private $description;
/**
- * Constructor.
- *
* @param string $name The option name
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
* @param int $mode The option mode: One of the VALUE_* constants
*
* @throws InvalidArgumentException If option mode is invalid or incompatible
*/
- public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
+ public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
{
if (0 === strpos($name, '--')) {
$name = substr($name, 2);
if (null === $mode) {
$mode = self::VALUE_NONE;
- } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
+ } elseif ($mode > 15 || $mode < 1) {
throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
}
/**
* Checks whether the given option equals this one.
*
- * @param InputOption $option option to compare
- *
* @return bool
*/
- public function equals(InputOption $option)
+ public function equals(self $option)
{
return $option->getName() === $this->getName()
&& $option->getShortcut() === $this->getShortcut()
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
/**
- * Constructor.
- *
- * @param string $input An array of parameters from the CLI (in the argv format)
+ * @param string $input A string representing the parameters from the CLI
*/
- public function __construct($input)
+ public function __construct(string $input)
{
parent::__construct(array());
-Copyright (c) 2004-2017 Fabien Potencier
+Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
const INFO = 'info';
const ERROR = 'error';
- /**
- * @var OutputInterface
- */
private $output;
- /**
- * @var array
- */
private $verbosityLevelMap = array(
LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
);
- /**
- * @var array
- */
private $formatLevelMap = array(
LogLevel::EMERGENCY => self::ERROR,
LogLevel::ALERT => self::ERROR,
);
private $errored = false;
- /**
- * @param OutputInterface $output
- * @param array $verbosityLevelMap
- * @param array $formatLevelMap
- */
public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
{
$this->output = $output;
$output = $this->output;
// Write to the error output if necessary and available
- if ($this->formatLevelMap[$level] === self::ERROR) {
+ if (self::ERROR === $this->formatLevelMap[$level]) {
if ($this->output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
/**
* Returns true when any messages have been logged at error levels.
+ *
+ * @return bool
*/
public function hasErrored()
{
* Interpolates context values into the message placeholders.
*
* @author PHP Framework Interoperability Group
- *
- * @param string $message
- * @param array $context
- *
- * @return string
*/
- private function interpolate($message, array $context)
+ private function interpolate(string $message, array $context): string
{
- // build a replacement array with braces around the context keys
- $replace = array();
+ if (false === strpos($message, '{')) {
+ return $message;
+ }
+
+ $replacements = array();
foreach ($context as $key => $val) {
- if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
- $replace[sprintf('{%s}', $key)] = $val;
+ if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) {
+ $replacements["{{$key}}"] = $val;
+ } elseif ($val instanceof \DateTimeInterface) {
+ $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339);
+ } elseif (\is_object($val)) {
+ $replacements["{{$key}}"] = '[object '.\get_class($val).']';
+ } else {
+ $replacements["{{$key}}"] = '['.\gettype($val).']';
}
}
- // interpolate replacement values into the message and return
- return strtr($message, $replace);
+ return strtr($message, $replacements);
}
}
*/
class BufferedOutput extends Output
{
- /**
- * @var string
- */
private $buffer = '';
/**
*/
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
{
- /**
- * @var StreamOutput
- */
private $stderr;
/**
- * Constructor.
- *
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
* @param bool|null $decorated Whether to decorate messages (null for auto-guessing)
* @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
*/
- public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
+ public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
{
parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
*/
public function getErrorOutput();
- /**
- * Sets the OutputInterface used for errors.
- *
- * @param OutputInterface $error
- */
public function setErrorOutput(OutputInterface $error);
}
private $formatter;
/**
- * Constructor.
- *
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
* @param bool $decorated Whether to decorate messages
* @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
*/
- public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
+ public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null)
{
$this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
$this->formatter = $formatter ?: new OutputFormatter();
*/
public function isDecorated();
- /**
- * Sets output formatter.
- *
- * @param OutputFormatterInterface $formatter
- */
public function setFormatter(OutputFormatterInterface $formatter);
/**
private $stream;
/**
- * Constructor.
- *
* @param resource $stream A stream resource
* @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
* @param bool|null $decorated Whether to decorate messages (null for auto-guessing)
*
* @throws InvalidArgumentException When first argument is not a real stream
*/
- public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
+ public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
{
if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
*
* Colorization is disabled if not supported by the stream:
*
- * - Windows != 10.0.10586 without Ansicon, ConEmu or Mintty
- * - non tty consoles
+ * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo
+ * terminals via named pipes, so we can only check the environment.
+ *
+ * Reference: Composer\XdebugHandler\Process::supportsColor
+ * https://github.com/composer/xdebug-handler
*
* @return bool true if the stream supports colorization, false otherwise
*/
protected function hasColorSupport()
{
if (DIRECTORY_SEPARATOR === '\\') {
- return
- '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
+ return (function_exists('sapi_windows_vt100_support')
+ && @sapi_windows_vt100_support($this->stream))
|| false !== getenv('ANSICON')
|| 'ON' === getenv('ConEmuANSI')
|| 'xterm' === getenv('TERM');
}
- return function_exists('posix_isatty') && @posix_isatty($this->stream);
+ if (function_exists('stream_isatty')) {
+ return @stream_isatty($this->stream);
+ }
+
+ if (function_exists('posix_isatty')) {
+ return @posix_isatty($this->stream);
+ }
+
+ $stat = @fstat($this->stream);
+ // Check if formatted mode is S_IFCHR
+ return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
}
}
private $errorMessage = 'Value "%s" is invalid';
/**
- * Constructor.
- *
* @param string $question The question to ask to the user
* @param array $choices The list of available choices
* @param mixed $default The default answer to return
*/
- public function __construct($question, array $choices, $default = null)
+ public function __construct(string $question, array $choices, $default = null)
{
if (!$choices) {
throw new \LogicException('Choice question must have at least 1 choice available.');
return $this;
}
- /**
- * Returns the default answer validator.
- *
- * @return callable
- */
- private function getDefaultValidator()
+ private function getDefaultValidator(): callable
{
$choices = $this->choices;
$errorMessage = $this->errorMessage;
private $trueAnswerRegex;
/**
- * Constructor.
- *
* @param string $question The question to ask to the user
* @param bool $default The default answer to return, true or false
* @param string $trueAnswerRegex A regex to match the "yes" answer
*/
- public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
+ public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i')
{
- parent::__construct($question, (bool) $default);
+ parent::__construct($question, $default);
$this->trueAnswerRegex = $trueAnswerRegex;
$this->setNormalizer($this->getDefaultNormalizer());
private $normalizer;
/**
- * Constructor.
- *
* @param string $question The question to ask to the user
* @param mixed $default The default answer to return if the user enters nothing
*/
- public function __construct($question, $default = null)
+ public function __construct(string $question, $default = null)
{
$this->question = $question;
$this->default = $default;
/**
* Gets values for the autocompleter.
*
- * @return null|array|\Traversable
+ * @return null|iterable
*/
public function getAutocompleterValues()
{
/**
* Sets values for the autocompleter.
*
- * @param null|array|\Traversable $values
+ * @param null|iterable $values
*
* @return $this
*
$values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
}
- if (null !== $values && !is_array($values)) {
- if (!$values instanceof \Traversable || !$values instanceof \Countable) {
- throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
- }
+ if (null !== $values && !is_array($values) && !$values instanceof \Traversable) {
+ throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
}
if ($this->hidden) {
*
* @return $this
*
- * @throws InvalidArgumentException In case the number of attempts is invalid.
+ * @throws InvalidArgumentException in case the number of attempts is invalid
*/
public function setMaxAttempts($attempts)
{
{
private $output;
- /**
- * @param OutputInterface $output
- */
public function __construct(OutputInterface $output)
{
$this->output = $output;
/**
* Formats a list.
- *
- * @param array $elements
*/
public function listing(array $elements);
/**
* Formats a table.
- *
- * @param array $headers
- * @param array $rows
*/
public function table(array $headers, array $rows);
* @param string|null $default
* @param callable|null $validator
*
- * @return string
+ * @return mixed
*/
public function ask($question, $default = null, $validator = null);
* @param string $question
* @param callable|null $validator
*
- * @return string
+ * @return mixed
*/
public function askHidden($question, $validator = null);
* @param array $choices
* @param string|int|null $default
*
- * @return string
+ * @return mixed
*/
public function choice($question, array $choices, $default = null);
private $lineLength;
private $bufferedOutput;
- /**
- * @param InputInterface $input
- * @param OutputInterface $output
- */
public function __construct(InputInterface $input, OutputInterface $output)
{
$this->input = $input;
}
/**
- * @param Question $question
- *
- * @return string
+ * @return mixed
*/
public function askQuestion(Question $question)
{
return new self($this->input, $this->getErrorOutput());
}
- /**
- * @return ProgressBar
- */
- private function getProgressBar()
+ private function getProgressBar(): ProgressBar
{
if (!$this->progressBar) {
throw new RuntimeException('The ProgressBar is not started.');
return $this->progressBar;
}
- private function autoPrependBlock()
+ private function autoPrependBlock(): void
{
$chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
if (!isset($chars[0])) {
- return $this->newLine(); //empty history, so we should start with a new line.
+ $this->newLine(); //empty history, so we should start with a new line.
+
+ return;
}
//Prepend new line for each non LF chars (This means no blank line was output before)
$this->newLine(2 - substr_count($chars, "\n"));
}
- private function autoPrependText()
+ private function autoPrependText(): void
{
$fetched = $this->bufferedOutput->fetch();
//Prepend new line if last char isn't EOL:
}
}
- private function reduceBuffer($messages)
+ private function reduceBuffer($messages): array
{
// We need to know if the two last chars are PHP_EOL
// Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer
}, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
}
- private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
+ private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false)
{
$indentLength = 0;
$prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
private $inputs = array();
private $statusCode;
- /**
- * Constructor.
- *
- * @param Command $command A Command instance to test
- */
public function __construct(Command $command)
{
$this->command = $command;
/**
* Sets the user inputs.
*
- * @param array An array of strings representing each input
- * passed to the command input stream.
+ * @param array $inputs An array of strings representing each input
+ * passed to the command input stream
*
* @return CommandTester
*/
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
+use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Tester\ApplicationTester;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
-use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\EventDispatcher\EventDispatcher;
class ApplicationTest extends TestCase
require_once self::$fixturesPath.'/Foo3Command.php';
require_once self::$fixturesPath.'/Foo4Command.php';
require_once self::$fixturesPath.'/Foo5Command.php';
+ require_once self::$fixturesPath.'/FooSameCaseUppercaseCommand.php';
+ require_once self::$fixturesPath.'/FooSameCaseLowercaseCommand.php';
require_once self::$fixturesPath.'/FoobarCommand.php';
require_once self::$fixturesPath.'/BarBucCommand.php';
require_once self::$fixturesPath.'/FooSubnamespaced1Command.php';
require_once self::$fixturesPath.'/FooSubnamespaced2Command.php';
+ require_once self::$fixturesPath.'/TestTiti.php';
+ require_once self::$fixturesPath.'/TestToto.php';
}
protected function normalizeLineBreaks($text)
$this->assertCount(1, $commands, '->all() takes a namespace as its first argument');
}
+ public function testAllWithCommandLoader()
+ {
+ $application = new Application();
+ $commands = $application->all();
+ $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands');
+
+ $application->add(new \FooCommand());
+ $commands = $application->all('foo');
+ $this->assertCount(1, $commands, '->all() takes a namespace as its first argument');
+
+ $application->setCommandLoader(new FactoryCommandLoader(array(
+ 'foo:bar1' => function () { return new \Foo1Command(); },
+ )));
+ $commands = $application->all('foo');
+ $this->assertCount(2, $commands, '->all() takes a namespace as its first argument');
+ $this->assertInstanceOf(\FooCommand::class, $commands['foo:bar'], '->all() returns the registered commands');
+ $this->assertInstanceOf(\Foo1Command::class, $commands['foo:bar1'], '->all() returns the registered commands');
+ }
+
public function testRegister()
{
$application = new Application();
$this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input');
}
+ public function testHasGetWithCommandLoader()
+ {
+ $application = new Application();
+ $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered');
+ $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered');
+
+ $application->add($foo = new \FooCommand());
+ $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered');
+ $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name');
+ $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias');
+
+ $application->setCommandLoader(new FactoryCommandLoader(array(
+ 'foo:bar1' => function () { return new \Foo1Command(); },
+ )));
+
+ $this->assertTrue($application->has('afoobar'), '->has() returns true if an instance is registered for an alias even with command loader');
+ $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns an instance by name even with command loader');
+ $this->assertEquals($foo, $application->get('afoobar'), '->get() returns an instance by alias even with command loader');
+ $this->assertTrue($application->has('foo:bar1'), '->has() returns true for commands registered in the loader');
+ $this->assertInstanceOf(\Foo1Command::class, $foo1 = $application->get('foo:bar1'), '->get() returns a command by name from the command loader');
+ $this->assertTrue($application->has('afoobar1'), '->has() returns true for commands registered in the loader');
+ $this->assertEquals($foo1, $application->get('afoobar1'), '->get() returns a command by name from the command loader');
+ }
+
public function testSilentHelp()
{
$application = new Application();
$application->findNamespace('f');
}
+ public function testFindNonAmbiguous()
+ {
+ $application = new Application();
+ $application->add(new \TestTiti());
+ $application->add(new \TestToto());
+ $this->assertEquals('test-toto', $application->find('test')->getName());
+ }
+
/**
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
* @expectedExceptionMessage There are no commands defined in the "bar" namespace.
$this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias');
}
+ public function testFindCaseSensitiveFirst()
+ {
+ $application = new Application();
+ $application->add(new \FooSameCaseUppercaseCommand());
+ $application->add(new \FooSameCaseLowercaseCommand());
+
+ $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:B'), '->find() returns a command if the abbreviation is the correct case');
+ $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:BAR'), '->find() returns a command if the abbreviation is the correct case');
+ $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case');
+ $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation is the correct case');
+ }
+
+ public function testFindCaseInsensitiveAsFallback()
+ {
+ $application = new Application();
+ $application->add(new \FooSameCaseLowercaseCommand());
+
+ $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case');
+ $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:B'), '->find() will fallback to case insensitivity');
+ $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will fallback to case insensitivity');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
+ * @expectedExceptionMessage Command "FoO:BaR" is ambiguous
+ */
+ public function testFindCaseInsensitiveSuggestions()
+ {
+ $application = new Application();
+ $application->add(new \FooSameCaseLowercaseCommand());
+ $application->add(new \FooSameCaseUppercaseCommand());
+
+ $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will find two suggestions with case insensitivity');
+ }
+
+ public function testFindWithCommandLoader()
+ {
+ $application = new Application();
+ $application->setCommandLoader(new FactoryCommandLoader(array(
+ 'foo:bar' => $f = function () { return new \FooCommand(); },
+ )));
+
+ $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists');
+ $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists');
+ $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists');
+ $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist');
+ $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias');
+ }
+
/**
* @dataProvider provideAmbiguousAbbreviations
*/
public function provideInvalidCommandNamesSingle()
{
return array(
- array('foo3:baR'),
- array('foO3:bar'),
+ array('foo3:barr'),
+ array('fooo3:bar'),
);
}
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true));
- $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
+ $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
$tester->run(array('command' => 'foo'), array('decorated' => true, 'capture_stderr_separately' => true));
- $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
+ $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
$application = new Application();
$application->setAutoExit(false);
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true));
- $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal');
+ $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal');
putenv('COLUMNS=120');
}
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'), array('decorated' => false));
- $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting');
+ $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting');
putenv('COLUMNS=120');
}
+ public function testRenderExceptionLineBreaks()
+ {
+ $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getTerminalWidth'))->getMock();
+ $application->setAutoExit(false);
+ $application->expects($this->any())
+ ->method('getTerminalWidth')
+ ->will($this->returnValue(120));
+ $application->register('foo')->setCode(function () {
+ throw new \InvalidArgumentException("\n\nline 1 with extra spaces \nline 2\n\nline 4\n");
+ });
+ $tester = new ApplicationTester($application);
+
+ $tester->run(array('command' => 'foo'), array('decorated' => false));
+ $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks');
+ }
+
public function testRun()
{
$application = new Application();
$this->assertEquals(1, $tester->getStatusCode());
}
- /**
- * @group legacy
- * @expectedDeprecation The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.
- */
- public function testLegacyExceptionListenersAreStillTriggered()
- {
- $dispatcher = $this->getDispatcher();
- $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
- $event->getOutput()->write('caught.');
-
- $event->setException(new \RuntimeException('replaced in caught.'));
- });
-
- $application = new Application();
- $application->setDispatcher($dispatcher);
- $application->setAutoExit(false);
-
- $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
- throw new \RuntimeException('foo');
- });
-
- $tester = new ApplicationTester($application);
- $tester->run(array('command' => 'foo'));
- $this->assertContains('before.caught.error.after.', $tester->getDisplay());
- $this->assertContains('replaced in caught.', $tester->getDisplay());
- }
-
- /**
- * @requires PHP 7
- */
public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent()
{
$application = new Application();
$this->assertEquals('some test value', $extraValue);
}
- /**
- * @group legacy
- */
- public function testTerminalDimensions()
- {
- $application = new Application();
- $originalDimensions = $application->getTerminalDimensions();
- $this->assertCount(2, $originalDimensions);
-
- $width = 80;
- if ($originalDimensions[0] == $width) {
- $width = 100;
- }
-
- $application->setTerminalDimensions($width, 80);
- $this->assertSame(array($width, 80), $application->getTerminalDimensions());
- }
-
public function testSetRunCustomDefaultCommand()
{
$command = new \FooCommand();
$this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream));
}
+ public function testRunLazyCommandService()
+ {
+ $container = new ContainerBuilder();
+ $container->addCompilerPass(new AddConsoleCommandPass());
+ $container
+ ->register('lazy-command', LazyCommand::class)
+ ->addTag('console.command', array('command' => 'lazy:command'))
+ ->addTag('console.command', array('command' => 'lazy:alias'))
+ ->addTag('console.command', array('command' => 'lazy:alias2'));
+ $container->compile();
+
+ $application = new Application();
+ $application->setCommandLoader($container->get('console.command_loader'));
+ $application->setAutoExit(false);
+
+ $tester = new ApplicationTester($application);
+
+ $tester->run(array('command' => 'lazy:command'));
+ $this->assertSame("lazy-command called\n", $tester->getDisplay(true));
+
+ $tester->run(array('command' => 'lazy:alias'));
+ $this->assertSame("lazy-command called\n", $tester->getDisplay(true));
+
+ $tester->run(array('command' => 'lazy:alias2'));
+ $this->assertSame("lazy-command called\n", $tester->getDisplay(true));
+
+ $command = $application->get('lazy:command');
+ $this->assertSame(array('lazy:alias', 'lazy:alias2'), $command->getAliases());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
+ */
+ public function testGetDisabledLazyCommand()
+ {
+ $application = new Application();
+ $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); })));
+ $application->get('disabled');
+ }
+
+ public function testHasReturnsFalseForDisabledLazyCommand()
+ {
+ $application = new Application();
+ $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); })));
+ $this->assertFalse($application->has('disabled'));
+ }
+
+ public function testAllExcludesDisabledLazyCommand()
+ {
+ $application = new Application();
+ $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); })));
+ $this->assertArrayNotHasKey('disabled', $application->all());
+ }
+
protected function getDispatcher($skipCommand = false)
{
$dispatcher = new EventDispatcher();
return $dispatcher;
}
- /**
- * @requires PHP 7
- */
public function testErrorIsRethrownIfNotHandledByConsoleErrorEventWithCatchingEnabled()
{
$application = new Application();
$this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found');
}
}
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage foo
+ */
+ public function testThrowingErrorListener()
+ {
+ $dispatcher = $this->getDispatcher();
+ $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) {
+ throw new \RuntimeException('foo');
+ });
+
+ $dispatcher->addListener('console.command', function () {
+ throw new \RuntimeException('bar');
+ });
+
+ $application = new Application();
+ $application->setDispatcher($dispatcher);
+ $application->setAutoExit(false);
+ $application->setCatchExceptions(false);
+
+ $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
+ $output->write('foo.');
+ });
+
+ $tester = new ApplicationTester($application);
+ $tester->run(array('command' => 'foo'));
+ }
+
+ protected function tearDown()
+ {
+ putenv('SHELL_VERBOSITY');
+ unset($_ENV['SHELL_VERBOSITY']);
+ unset($_SERVER['SHELL_VERBOSITY']);
+ }
}
class CustomApplication extends Application
$this->setDefaultCommand($command->getName());
}
}
+
+class LazyCommand extends Command
+{
+ public function execute(InputInterface $input, OutputInterface $output)
+ {
+ $output->writeln('lazy-command called');
+ }
+}
+
+class DisabledCommand extends Command
+{
+ public function isEnabled()
+ {
+ return false;
+ }
+}
*/
public function testCommandNameCannotBeEmpty()
{
- new Command();
+ (new Application())->add(new Command());
}
public function testSetApplication()
$tester = new CommandTester($command);
$tester->execute(array());
- if (\PHP_VERSION_ID < 70000) {
- // Cannot bind static closures in PHP 5
- $this->assertEquals('interact called'.PHP_EOL.'not bound'.PHP_EOL, $tester->getDisplay());
- } else {
- // Can bind static closures in PHP 7
- $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay());
- }
+ $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay());
}
private static function createClosure()
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Tester\CommandTester;
-use Symfony\Component\Filesystem\LockHandler;
+use Symfony\Component\Lock\Factory;
+use Symfony\Component\Lock\Store\FlockStore;
+use Symfony\Component\Lock\Store\SemaphoreStore;
class LockableTraitTest extends TestCase
{
{
$command = new \FooLockCommand();
- $lock = new LockHandler($command->getName());
- $lock->lock();
+ if (SemaphoreStore::isSupported()) {
+ $store = new SemaphoreStore();
+ } else {
+ $store = new FlockStore();
+ }
+
+ $lock = (new Factory($store))->createLock($command->getName());
+ $lock->acquire();
$tester = new CommandTester($command);
$this->assertSame(1, $tester->execute(array()));
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\CommandLoader;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+
+class ContainerCommandLoaderTest extends TestCase
+{
+ public function testHas()
+ {
+ $loader = new ContainerCommandLoader(new ServiceLocator(array(
+ 'foo-service' => function () { return new Command('foo'); },
+ 'bar-service' => function () { return new Command('bar'); },
+ )), array('foo' => 'foo-service', 'bar' => 'bar-service'));
+
+ $this->assertTrue($loader->has('foo'));
+ $this->assertTrue($loader->has('bar'));
+ $this->assertFalse($loader->has('baz'));
+ }
+
+ public function testGet()
+ {
+ $loader = new ContainerCommandLoader(new ServiceLocator(array(
+ 'foo-service' => function () { return new Command('foo'); },
+ 'bar-service' => function () { return new Command('bar'); },
+ )), array('foo' => 'foo-service', 'bar' => 'bar-service'));
+
+ $this->assertInstanceOf(Command::class, $loader->get('foo'));
+ $this->assertInstanceOf(Command::class, $loader->get('bar'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
+ */
+ public function testGetUnknownCommandThrows()
+ {
+ (new ContainerCommandLoader(new ServiceLocator(array()), array()))->get('unknown');
+ }
+
+ public function testGetCommandNames()
+ {
+ $loader = new ContainerCommandLoader(new ServiceLocator(array(
+ 'foo-service' => function () { return new Command('foo'); },
+ 'bar-service' => function () { return new Command('bar'); },
+ )), array('foo' => 'foo-service', 'bar' => 'bar-service'));
+
+ $this->assertSame(array('foo', 'bar'), $loader->getNames());
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\CommandLoader;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
+
+class FactoryCommandLoaderTest extends TestCase
+{
+ public function testHas()
+ {
+ $loader = new FactoryCommandLoader(array(
+ 'foo' => function () { return new Command('foo'); },
+ 'bar' => function () { return new Command('bar'); },
+ ));
+
+ $this->assertTrue($loader->has('foo'));
+ $this->assertTrue($loader->has('bar'));
+ $this->assertFalse($loader->has('baz'));
+ }
+
+ public function testGet()
+ {
+ $loader = new FactoryCommandLoader(array(
+ 'foo' => function () { return new Command('foo'); },
+ 'bar' => function () { return new Command('bar'); },
+ ));
+
+ $this->assertInstanceOf(Command::class, $loader->get('foo'));
+ $this->assertInstanceOf(Command::class, $loader->get('bar'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
+ */
+ public function testGetUnknownCommandThrows()
+ {
+ (new FactoryCommandLoader(array()))->get('unknown');
+ }
+
+ public function testGetCommandNames()
+ {
+ $loader = new FactoryCommandLoader(array(
+ 'foo' => function () { return new Command('foo'); },
+ 'bar' => function () { return new Command('bar'); },
+ ));
+
+ $this->assertSame(array('foo', 'bar'), $loader->getNames());
+ }
+}
namespace Symfony\Component\Console\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
+use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
use Symfony\Component\Console\Command\Command;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\DependencyInjection\TypedReference;
class AddConsoleCommandPassTest extends TestCase
{
$container->addCompilerPass(new AddConsoleCommandPass());
$container->setParameter('my-command.class', 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand');
+ $id = 'my-command';
$definition = new Definition('%my-command.class%');
$definition->setPublic($public);
$definition->addTag('console.command');
- $container->setDefinition('my-command', $definition);
+ $container->setDefinition($id, $definition);
$container->compile();
- $alias = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand';
+ $alias = 'console.command.public_alias.my-command';
if ($public) {
$this->assertFalse($container->hasAlias($alias));
- $id = 'my-command';
} else {
- $id = $alias;
// The alias is replaced by a Definition by the ReplaceAliasByActualDefinitionPass
// in case the original service is private
- $this->assertFalse($container->hasDefinition('my-command'));
+ $this->assertFalse($container->hasDefinition($id));
$this->assertTrue($container->hasDefinition($alias));
}
$this->assertTrue($container->hasParameter('console.command.ids'));
- $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids'));
+ $this->assertSame(array($public ? $id : $alias), $container->getParameter('console.command.ids'));
+ }
+
+ public function testProcessRegistersLazyCommands()
+ {
+ $container = new ContainerBuilder();
+ $command = $container
+ ->register('my-command', MyCommand::class)
+ ->setPublic(false)
+ ->addTag('console.command', array('command' => 'my:command'))
+ ->addTag('console.command', array('command' => 'my:alias'))
+ ;
+
+ (new AddConsoleCommandPass())->process($container);
+
+ $commandLoader = $container->getDefinition('console.command_loader');
+ $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0));
+
+ $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass());
+ $this->assertSame(array('my:command' => 'my-command', 'my:alias' => 'my-command'), $commandLoader->getArgument(1));
+ $this->assertEquals(array(array('my-command' => new ServiceClosureArgument(new TypedReference('my-command', MyCommand::class)))), $commandLocator->getArguments());
+ $this->assertSame(array(), $container->getParameter('console.command.ids'));
+ $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls());
+ }
+
+ public function testProcessFallsBackToDefaultName()
+ {
+ $container = new ContainerBuilder();
+ $container
+ ->register('with-default-name', NamedCommand::class)
+ ->setPublic(false)
+ ->addTag('console.command')
+ ;
+
+ $pass = new AddConsoleCommandPass();
+ $pass->process($container);
+
+ $commandLoader = $container->getDefinition('console.command_loader');
+ $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0));
+
+ $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass());
+ $this->assertSame(array('default' => 'with-default-name'), $commandLoader->getArgument(1));
+ $this->assertEquals(array(array('with-default-name' => new ServiceClosureArgument(new TypedReference('with-default-name', NamedCommand::class)))), $commandLocator->getArguments());
+ $this->assertSame(array(), $container->getParameter('console.command.ids'));
+
+ $container = new ContainerBuilder();
+ $container
+ ->register('with-default-name', NamedCommand::class)
+ ->setPublic(false)
+ ->addTag('console.command', array('command' => 'new-name'))
+ ;
+
+ $pass->process($container);
+
+ $this->assertSame(array('new-name' => 'with-default-name'), $container->getDefinition('console.command_loader')->getArgument(1));
}
public function visibilityProvider()
(new AddConsoleCommandPass())->process($container);
- $alias1 = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand';
- $alias2 = $alias1.'_my-command2';
- $this->assertTrue($container->hasAlias($alias1));
- $this->assertTrue($container->hasAlias($alias2));
+ $aliasPrefix = 'console.command.public_alias.';
+ $this->assertTrue($container->hasAlias($aliasPrefix.'my-command1'));
+ $this->assertTrue($container->hasAlias($aliasPrefix.'my-command2'));
}
}
{
}
-class ExtensionPresentBundle extends Bundle
+class NamedCommand extends Command
{
+ protected static $defaultName = 'default';
}
$logger
->expects($this->once())
->method('error')
- ->with('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred'))
+ ->with('Error thrown while running command "{command}". Message: "{message}"', array('exception' => $error, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred'))
;
$listener = new ErrorListener($logger);
$logger
->expects($this->once())
->method('error')
- ->with('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => 'An error occurred'))
+ ->with('An error occurred while using the console. Message: "{message}"', array('exception' => $error, 'message' => 'An error occurred'))
;
$listener = new ErrorListener($logger);
$logger = $this->getLogger();
$logger
->expects($this->once())
- ->method('error')
+ ->method('debug')
->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255))
;
$logger = $this->getLogger();
$logger
->expects($this->never())
- ->method('error')
+ ->method('debug')
;
$listener = new ErrorListener($logger);
$logger = $this->getLogger();
$logger
->expects($this->exactly(3))
- ->method('error')
+ ->method('debug')
->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run --foo=bar', 'code' => 255))
;
$logger = $this->getLogger();
$logger
->expects($this->once())
- ->method('error')
+ ->method('debug')
->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255))
;
--- /dev/null
+<?php
+
+use Symfony\Component\Console\Command\Command;
+
+class FooSameCaseLowercaseCommand extends Command
+{
+ protected function configure()
+ {
+ $this->setName('foo:bar')->setDescription('foo:bar command');
+ }
+}
--- /dev/null
+<?php
+
+use Symfony\Component\Console\Command\Command;
+
+class FooSameCaseUppercaseCommand extends Command
+{
+ protected function configure()
+ {
+ $this->setName('foo:BAR')->setDescription('foo:BAR command');
+ }
+}
--- /dev/null
+<?php
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class TestTiti extends Command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('test-titi')
+ ->setDescription('The test:titi command')
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $output->write('test-titi');
+ }
+}
--- /dev/null
+<?php
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class TestToto extends Command
+{
+ protected function configure()
+ {
+ $this
+ ->setName('test-toto')
+ ->setDescription('The test-toto command')
+ ->setAliases(array('test'))
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $output->write('test-toto');
+ }
+}
-
- [Symfony\Component\Console\Exception\CommandNotFoundException]
- Command "foo" is not defined.
-
+
+ Command "foo" is not defined.
+
-
- [Symfony\Component\Console\Exception\InvalidOptionException]
- The "--foo" option does not exist.
-
+
+ The "--foo" option does not exist.
+
list [--raw] [--format FORMAT] [--] [<namespace>]
+In Foo3Command.php line 26:
- [Exception]
Third exception <fg=blue;bg=red>comment</>
+In Foo3Command.php line 23:
- [Exception]
Second exception <comment>comment</comment>
+In Foo3Command.php line 21:
- [Exception]
First exception <p>this is html</p>
+\e[33mIn Foo3Command.php line 26:\e[39m
\e[37;41m \e[39;49m
-\e[37;41m [Exception] \e[39;49m
\e[37;41m Third exception <fg=blue;bg=red>comment</> \e[39;49m
\e[37;41m \e[39;49m
+\e[33mIn Foo3Command.php line 23:\e[39m
\e[37;41m \e[39;49m
-\e[37;41m [Exception] \e[39;49m
\e[37;41m Second exception <comment>comment</comment> \e[39;49m
\e[37;41m \e[39;49m
+\e[33mIn Foo3Command.php line 21:\e[39m
\e[37;41m \e[39;49m
-\e[37;41m [Exception] \e[39;49m
\e[37;41m First exception <p>this is html</p> \e[39;49m
\e[37;41m \e[39;49m
-
- [Symfony\Component\Console\Exception\CommandNotFoundException]
- Command "foo" is not define
- d.
-
+
+ Command "foo" is not define
+ d.
+
+In ApplicationTest.php line %d:
- [Exception]
エラーメッセージ
+\e[33mIn ApplicationTest.php line %d:\e[39m
\e[37;41m \e[39;49m
-\e[37;41m [Exception] \e[39;49m
\e[37;41m エラーメッセージ \e[39;49m
\e[37;41m \e[39;49m
+In ApplicationTest.php line %d:
- [Exception]
コマンドの実行中にエラーが
発生しました。
+In ApplicationTest.php line %d:
- [Exception]
dont break here <
info>!</info>
--- /dev/null
+
+In ApplicationTest.php line %d:
+
+ line 1 with extra spaces
+ line 2
+
+ line 4
+
+
+foo
+
<comment>Usage:</comment>
- descriptor:command2 [options] [--] <argument_name>
- descriptor:command2 -o|--option_name <argument_name>
- descriptor:command2 <argument_name>
+ descriptor:command2 [options] [--] \<argument_name>
+ descriptor:command2 -o|--option_name \<argument_name>
+ descriptor:command2 \<argument_name>
<comment>Arguments:</comment>
<info>argument_name</info>
<comment>Usage:</comment>
- descriptor:åèä [options] [--] <argument_åèä>
- descriptor:åèä -o|--option_name <argument_name>
- descriptor:åèä <argument_name>
+ descriptor:åèä [options] [--] \<argument_åèä>
+ descriptor:åèä -o|--option_name \<argument_name>
+ descriptor:åèä \<argument_name>
<comment>Arguments:</comment>
<info>argument_åèä</info>
$formatter = new OutputFormatter(true);
$this->assertEquals('foo<bar', $formatter->format('foo\\<bar'));
+ $this->assertEquals('foo << bar', $formatter->format('foo << bar'));
+ $this->assertEquals('foo << bar \\', $formatter->format('foo << bar \\'));
+ $this->assertEquals("foo << \033[32mbar \\ baz\033[39m \\", $formatter->format('foo << <info>bar \\ baz</info> \\'));
$this->assertEquals('<info>some info</info>', $formatter->format('\\<info>some info\\</info>'));
$this->assertEquals('\\<info>some info\\</info>', OutputFormatter::escape('<info>some info</info>'));
);
}
- /**
- * @group legacy
- * @dataProvider provideInlineStyleTagsWithUnknownOptions
- * @expectedDeprecation Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "Invalid option specified: "%s". Expected one of (bold, underscore, blink, reverse, conceal)".
- */
- public function testInlineStyleOptionsUnknownAreDeprecated($tag, $option)
- {
- $formatter = new OutputFormatter(true);
- $formatter->format($tag);
- }
-
public function provideInlineStyleTagsWithUnknownOptions()
{
return array(
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Helper\ProcessHelper;
use Symfony\Component\Process\Process;
-use Symfony\Component\Process\ProcessBuilder;
class ProcessHelperTest extends TestCase
{
EOT;
$errorMessage = 'An error occurred';
- $args = new ProcessBuilder(array('php', '-r', 'echo 42;'));
- $args = $args->getProcess()->getCommandLine();
+ $args = new Process(array('php', '-r', 'echo 42;'));
+ $args = $args->getCommandLine();
$successOutputProcessDebug = str_replace("'php' '-r' 'echo 42;'", $args, $successOutputProcessDebug);
return array(
$question->setMultiselect(true);
$this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+
+ $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, 0);
+ // We are supposed to get the default value since we are not in interactive mode
+ $this->assertEquals('Superman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, true), $this->createOutputInterface(), $question));
}
public function testAsk()
$this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
}
+ public function testAskWithAutocompleteWithExactMatch()
+ {
+ if (!$this->hasSttyAvailable()) {
+ $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+ }
+
+ $inputStream = $this->getInputStream("b\n");
+
+ $possibleChoices = array(
+ 'a' => 'berlin',
+ 'b' => 'copenhagen',
+ 'c' => 'amsterdam',
+ );
+
+ $dialog = new QuestionHelper();
+ $dialog->setHelperSet(new HelperSet(array(new FormatterHelper())));
+
+ $question = new ChoiceQuestion('Please select a city', $possibleChoices);
+ $question->setMaxAttempts(1);
+
+ $this->assertSame('b', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ }
+
+ public function testAutocompleteWithTrailingBackslash()
+ {
+ if (!$this->hasSttyAvailable()) {
+ $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+ }
+
+ $inputStream = $this->getInputStream('E');
+
+ $dialog = new QuestionHelper();
+ $helperSet = new HelperSet(array(new FormatterHelper()));
+ $dialog->setHelperSet($helperSet);
+
+ $question = new Question('');
+ $expectedCompletion = 'ExampleNamespace\\';
+ $question->setAutocompleterValues(array($expectedCompletion));
+
+ $output = $this->createOutputInterface();
+ $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output, $question);
+
+ $outputStream = $output->getStream();
+ rewind($outputStream);
+ $actualOutput = stream_get_contents($outputStream);
+
+ // Shell control (esc) sequences are not so important: we only care that
+ // <hl> tag is interpreted correctly and replaced
+ $irrelevantEscSequences = array(
+ "\0337" => '', // Save cursor position
+ "\0338" => '', // Restore cursor position
+ "\033[K" => '', // Clear line from cursor till the end
+ );
+
+ $importantActualOutput = strtr($actualOutput, $irrelevantEscSequences);
+
+ // Remove colors (e.g. "\033[30m", "\033[31;41m")
+ $importantActualOutput = preg_replace('/\033\[\d+(;\d+)?m/', '', $importantActualOutput);
+
+ $this->assertEquals($expectedCompletion, $importantActualOutput);
+ }
+
public function testAskHiddenResponse()
{
if ('\\' === DIRECTORY_SEPARATOR) {
}
/**
- * @group legacy
+ * @expectedException \Symfony\Component\Console\Exception\RuntimeException
+ * @expectedExceptionMessage Aborted
*/
- public function testLegacyAskChoice()
+ public function testAskThrowsExceptionOnMissingInput()
{
- $questionHelper = new QuestionHelper();
-
- $helperSet = new HelperSet(array(new FormatterHelper()));
- $questionHelper->setHelperSet($helperSet);
-
- $heroes = array('Superman', 'Batman', 'Spiderman');
-
- $questionHelper->setInputStream($this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n"));
-
- $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2');
- $question->setMaxAttempts(1);
- // first answer is an empty answer, we're supposed to receive the default value
- $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-
- $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
- $question->setMaxAttempts(1);
- $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-
- $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
- $question->setErrorMessage('Input "%s" is not a superhero!');
- $question->setMaxAttempts(2);
- $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
-
- rewind($output->getStream());
- $stream = stream_get_contents($output->getStream());
- $this->assertContains('Input "Fabien" is not a superhero!', $stream);
-
- try {
- $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1');
- $question->setMaxAttempts(1);
- $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question);
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
- }
-
- $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null);
- $question->setMaxAttempts(1);
- $question->setMultiselect(true);
-
- $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-
- $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1');
- $question->setMaxAttempts(1);
- $question->setMultiselect(true);
-
- $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-
- $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 ');
- $question->setMaxAttempts(1);
- $question->setMultiselect(true);
-
- $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+ $dialog = new QuestionHelper();
+ $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?'));
}
/**
- * @group legacy
+ * @expectedException \Symfony\Component\Console\Exception\RuntimeException
+ * @expectedExceptionMessage Aborted
*/
- public function testLegacyAsk()
+ public function testAskThrowsExceptionOnMissingInputWithValidator()
{
$dialog = new QuestionHelper();
- $dialog->setInputStream($this->getInputStream("\n8AM\n"));
-
- $question = new Question('What time is it?', '2PM');
- $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-
- $question = new Question('What time is it?', '2PM');
- $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
+ $question = new Question('What\'s your name?');
+ $question->setValidator(function () {
+ if (!$value) {
+ throw new \Exception('A value is required.');
+ }
+ });
- rewind($output->getStream());
- $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
+ $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question);
}
/**
- * @group legacy
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Choice question must have at least 1 choice available.
*/
- public function testLegacyAskWithAutocomplete()
+ public function testEmptyChoices()
+ {
+ new ChoiceQuestion('Question', array(), 'irrelevant');
+ }
+
+ public function testTraversableAutocomplete()
{
if (!$this->hasSttyAvailable()) {
$this->markTestSkipped('`stty` is required to test autocomplete functionality');
$inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n");
$dialog = new QuestionHelper();
- $dialog->setInputStream($inputStream);
$helperSet = new HelperSet(array(new FormatterHelper()));
$dialog->setHelperSet($helperSet);
$question = new Question('Please select a bundle', 'FrameworkBundle');
- $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'));
-
- $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- }
-
- /**
- * @group legacy
- */
- public function testLegacyAskWithAutocompleteWithNonSequentialKeys()
- {
- if (!$this->hasSttyAvailable()) {
- $this->markTestSkipped('`stty` is required to test autocomplete functionality');
- }
-
- // <UP ARROW><UP ARROW><NEWLINE><DOWN ARROW><DOWN ARROW><NEWLINE>
- $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n");
-
- $dialog = new QuestionHelper();
- $dialog->setInputStream($inputStream);
- $dialog->setHelperSet(new HelperSet(array(new FormatterHelper())));
-
- $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle'));
- $question->setMaxAttempts(1);
-
- $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- }
-
- /**
- * @group legacy
- */
- public function testLegacyAskHiddenResponse()
- {
- if ('\\' === DIRECTORY_SEPARATOR) {
- $this->markTestSkipped('This test is not supported on Windows');
- }
-
- $dialog = new QuestionHelper();
- $dialog->setInputStream($this->getInputStream("8AM\n"));
-
- $question = new Question('What time is it?');
- $question->setHidden(true);
-
- $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- }
-
- /**
- * @group legacy
- * @dataProvider getAskConfirmationData
- */
- public function testLegacyAskConfirmation($question, $expected, $default = true)
- {
- $dialog = new QuestionHelper();
-
- $dialog->setInputStream($this->getInputStream($question."\n"));
- $question = new ConfirmationQuestion('Do you like French fries?', $default);
- $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel'));
- }
-
- /**
- * @group legacy
- */
- public function testLegacyAskConfirmationWithCustomTrueAnswer()
- {
- $dialog = new QuestionHelper();
-
- $dialog->setInputStream($this->getInputStream("j\ny\n"));
- $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
- $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
- $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- }
-
- /**
- * @group legacy
- */
- public function testLegacyAskAndValidate()
- {
- $dialog = new QuestionHelper();
- $helperSet = new HelperSet(array(new FormatterHelper()));
- $dialog->setHelperSet($helperSet);
+ $question->setAutocompleterValues(new AutocompleteValues(array('irrelevant' => 'AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')));
- $error = 'This is not a color!';
- $validator = function ($color) use ($error) {
- if (!in_array($color, array('white', 'black'))) {
- throw new \InvalidArgumentException($error);
- }
-
- return $color;
- };
-
- $question = new Question('What color was the white horse of Henry IV?', 'white');
- $question->setValidator($validator);
- $question->setMaxAttempts(2);
-
- $dialog->setInputStream($this->getInputStream("\nblack\n"));
- $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
- $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-
- $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n"));
- try {
- $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertEquals($error, $e->getMessage());
- }
- }
-
- /**
- * @group legacy
- * @dataProvider simpleAnswerProvider
- */
- public function testLegacySelectChoiceFromSimpleChoices($providedAnswer, $expectedValue)
- {
- $possibleChoices = array(
- 'My environment 1',
- 'My environment 2',
- 'My environment 3',
- );
-
- $dialog = new QuestionHelper();
- $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
- $helperSet = new HelperSet(array(new FormatterHelper()));
- $dialog->setHelperSet($helperSet);
-
- $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
- $question->setMaxAttempts(1);
- $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
-
- $this->assertSame($expectedValue, $answer);
- }
-
- /**
- * @group legacy
- * @dataProvider mixedKeysChoiceListAnswerProvider
- */
- public function testLegacyChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue)
- {
- $possibleChoices = array(
- '0' => 'No environment',
- '1' => 'My environment 1',
- 'env_2' => 'My environment 2',
- 3 => 'My environment 3',
- );
-
- $dialog = new QuestionHelper();
- $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
- $helperSet = new HelperSet(array(new FormatterHelper()));
- $dialog->setHelperSet($helperSet);
-
- $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
- $question->setMaxAttempts(1);
- $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
-
- $this->assertSame($expectedValue, $answer);
- }
-
- /**
- * @group legacy
- * @dataProvider answerProvider
- */
- public function testLegacySelectChoiceFromChoiceList($providedAnswer, $expectedValue)
- {
- $possibleChoices = array(
- 'env_1' => 'My environment 1',
- 'env_2' => 'My environment',
- 'env_3' => 'My environment',
- );
-
- $dialog = new QuestionHelper();
- $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
- $helperSet = new HelperSet(array(new FormatterHelper()));
- $dialog->setHelperSet($helperSet);
-
- $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
- $question->setMaxAttempts(1);
- $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
-
- $this->assertSame($expectedValue, $answer);
- }
-
- /**
- * @group legacy
- * @expectedException \InvalidArgumentException
- * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3.
- */
- public function testLegacyAmbiguousChoiceFromChoicelist()
- {
- $possibleChoices = array(
- 'env_1' => 'My first environment',
- 'env_2' => 'My environment',
- 'env_3' => 'My environment',
- );
-
- $dialog = new QuestionHelper();
- $dialog->setInputStream($this->getInputStream("My environment\n"));
- $helperSet = new HelperSet(array(new FormatterHelper()));
- $dialog->setHelperSet($helperSet);
-
- $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
- $question->setMaxAttempts(1);
-
- $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
- }
-
- /**
- * @requires function mb_strwidth
- * @group legacy
- */
- public function testLegacyChoiceOutputFormattingQuestionForUtf8Keys()
- {
- $question = 'Lorem ipsum?';
- $possibleChoices = array(
- 'foo' => 'foo',
- 'żółw' => 'bar',
- 'łabądź' => 'baz',
- );
- $outputShown = array(
- $question,
- ' [<info>foo </info>] foo',
- ' [<info>żółw </info>] bar',
- ' [<info>łabądź</info>] baz',
- );
- $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock();
- $output->method('getFormatter')->willReturn(new OutputFormatter());
-
- $dialog = new QuestionHelper();
- $dialog->setInputStream($this->getInputStream("\n"));
- $helperSet = new HelperSet(array(new FormatterHelper()));
- $dialog->setHelperSet($helperSet);
-
- $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown));
-
- $question = new ChoiceQuestion($question, $possibleChoices, 'foo');
- $dialog->ask($this->createInputInterfaceMock(), $output, $question);
- }
-
- /**
- * @expectedException \Symfony\Component\Console\Exception\RuntimeException
- * @expectedExceptionMessage Aborted
- */
- public function testAskThrowsExceptionOnMissingInput()
- {
- $dialog = new QuestionHelper();
- $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?'));
- }
-
- /**
- * @expectedException \Symfony\Component\Console\Exception\RuntimeException
- * @expectedExceptionMessage Aborted
- */
- public function testAskThrowsExceptionOnMissingInputWithValidator()
- {
- $dialog = new QuestionHelper();
-
- $question = new Question('What\'s your name?');
- $question->setValidator(function () {
- if (!$value) {
- throw new \Exception('A value is required.');
- }
- });
-
- $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question);
- }
-
- /**
- * @expectedException \LogicException
- * @expectedExceptionMessage Choice question must have at least 1 choice available.
- */
- public function testEmptyChoices()
- {
- new ChoiceQuestion('Question', array(), 'irrelevant');
+ $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+ $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
}
protected function getInputStream($input)
{
exec('stty 2>&1', $output, $exitcode);
- return $exitcode === 0;
+ return 0 === $exitcode;
+ }
+}
+
+class AutocompleteValues implements \IteratorAggregate
+{
+ private $values;
+
+ public function __construct(array $values)
+ {
+ $this->values = $values;
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->values);
}
}
$this->assertEquals($expected, $this->getOutputContent($output));
}
+ /**
+ * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException
+ * @expectedExceptionMessage A cell must be a TableCell, a scalar or an object implementing __toString, array given.
+ */
+ public function testThrowsWhenTheCellInAnArray()
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders(array('ISBN', 'Title', 'Author', 'Price'))
+ ->setRows(array(
+ array('99921-58-10-7', array(), 'Dante Alighieri', '9.95'),
+ ));
+
+ $table->render();
+ }
+
public function testColumnWith()
{
$table = new Table($output = $this->getOutputStream());
$input = new ArgvInput(array('cli.php', '-f', 'foo'));
$this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input');
+ $input = new ArgvInput(array('cli.php', '-etest'));
+ $this->assertTrue($input->hasParameterOption('-e'), '->hasParameterOption() returns true if the given short option is in the raw input');
+ $this->assertFalse($input->hasParameterOption('-s'), '->hasParameterOption() returns true if the given short option is in the raw input');
+
$input = new ArgvInput(array('cli.php', '--foo', 'foo'));
$this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input');
$this->assertFalse($input->hasParameterOption('--foo', true), '->hasParameterOption() returns false if the given option is in the raw input but after an end of options signal');
}
+ public function testHasParameterOptionEdgeCasesAndLimitations()
+ {
+ $input = new ArgvInput(array('cli.php', '-fh'));
+ // hasParameterOption does not know if the previous short option, -f,
+ // takes a value or not. If -f takes a value, then -fh does NOT include
+ // -h; Otherwise it does. Since we do not know which short options take
+ // values, hasParameterOption does not support this use-case.
+ $this->assertFalse($input->hasParameterOption('-h'), '->hasParameterOption() returns true if the given short option is in the raw input');
+ // hasParameterOption does detect that `-fh` contains `-f`, since
+ // `-f` is the first short option in the set.
+ $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input');
+ // The test below happens to pass, although it might make more sense
+ // to disallow it, and require the use of
+ // $input->hasParameterOption('-f') && $input->hasParameterOption('-h')
+ // instead.
+ $this->assertTrue($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input');
+ // In theory, if -fh is supported, then -hf should also work.
+ // However, this is not supported.
+ $this->assertFalse($input->hasParameterOption('-hf'), '->hasParameterOption() returns true if the given short option is in the raw input');
+
+ $input = new ArgvInput(array('cli.php', '-f', '-h'));
+ // If hasParameterOption('-fh') is supported for 'cli.php -fh', then
+ // one might also expect that it should also be supported for
+ // 'cli.php -f -h'. However, this is not supported.
+ $this->assertFalse($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input');
+ }
+
+ public function testNoWarningOnInvalidParameterOption()
+ {
+ $input = new ArgvInput(array('cli.php', '-edev'));
+
+ $this->assertTrue($input->hasParameterOption(array('-e', '')));
+ // No warning thrown
+ $this->assertFalse($input->hasParameterOption(array('-m', '')));
+
+ $this->assertEquals('dev', $input->getParameterOption(array('-e', '')));
+ // No warning thrown
+ $this->assertFalse($input->getParameterOption(array('-m', '')));
+ }
+
public function testToString()
{
$input = new ArgvInput(array('cli.php', '-f', 'foo'));
{
$input = new ArrayInput(array('-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C"));
$this->assertEquals('-f -b=bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input);
+
+ $input = new ArrayInput(array('-b' => array('bval_1', 'bval_2'), '--f' => array('fval_1', 'fval_2')));
+ $this->assertSame('-b=bval_1 -b=bval_2 --f=fval_1 --f=fval_2', (string) $input);
+
+ $input = new ArrayInput(array('array_arg' => array('val_1', 'val_2')));
+ $this->assertSame('val_1 val_2', (string) $input);
}
}
}
/**
- * @dataProvider provideInvalidModes
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Argument mode "-1" is not valid.
*/
- public function testInvalidModes($mode)
+ public function testInvalidModes()
{
- if (method_exists($this, 'expectException')) {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage(sprintf('Argument mode "%s" is not valid.', $mode));
- } else {
- $this->setExpectedException('InvalidArgumentException', sprintf('Argument mode "%s" is not valid.', $mode));
- }
-
- new InputArgument('foo', $mode);
- }
-
- public function provideInvalidModes()
- {
- return array(
- array('ANOTHER_ONE'),
- array(-1),
- );
+ new InputArgument('foo', '-1');
}
public function testIsArray()
}
/**
- * @dataProvider provideInvalidModes
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Option mode "-1" is not valid.
*/
- public function testInvalidModes($mode)
- {
- if (method_exists($this, 'expectException')) {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage(sprintf('Option mode "%s" is not valid.', $mode));
- } else {
- $this->setExpectedException('InvalidArgumentException', sprintf('Option mode "%s" is not valid.', $mode));
- }
-
- new InputOption('foo', 'f', $mode);
- }
-
- public function provideInvalidModes()
+ public function testInvalidModes()
{
- return array(
- array('ANOTHER_ONE'),
- array(-1),
- );
+ new InputOption('foo', 'f', '-1');
}
/**
} else {
$dummy = $this->getMock('Symfony\Component\Console\Tests\Logger\DummyTest', array('__toString'));
}
- $dummy->expects($this->once())
- ->method('__toString')
- ->will($this->returnValue('DUMMY'));
+ $dummy->method('__toString')->will($this->returnValue('DUMMY'));
$this->getLogger()->warning($dummy);
}
],
"require": {
- "php": ">=5.5.9",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/debug": "~2.8|~3.0"
+ "php": "^7.1.3",
+ "symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
- "symfony/config": "~3.3",
- "symfony/http-kernel": "~2.8|~3.0",
- "symfony/event-dispatcher": "~2.8|~3.0",
- "symfony/dependency-injection": "~3.3",
- "symfony/filesystem": "~2.8|~3.0",
- "symfony/process": "~2.8|~3.0",
+ "symfony/config": "~3.4|~4.0",
+ "symfony/event-dispatcher": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/lock": "~3.4|~4.0",
+ "symfony/process": "~3.4|~4.0",
"psr/log": "~1.0"
},
"suggest": {
"symfony/event-dispatcher": "",
- "symfony/filesystem": "",
+ "symfony/lock": "",
"symfony/process": "",
- "psr/log": "For using the console logger"
+ "psr/log-implementation": "For using the console logger"
},
"conflict": {
- "symfony/dependency-injection": "<3.3"
+ "symfony/dependency-injection": "<3.4",
+ "symfony/process": "<3.3"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Console\\": "" },
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
}
}
CHANGELOG
=========
+4.0.0
+-----
+
+* removed the symfony_debug extension
+* removed `ContextErrorException`
+
+3.4.0
+-----
+
+* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()`
+
3.3.0
-----
*
* This method registers an error handler and an exception handler.
*
- * If the Symfony ClassLoader component is available, a special
- * class loader is also registered.
- *
* @param int $errorReportingLevel The level of error reporting you want
* @param bool $displayErrors Whether to display errors (for development) or just log them (for production)
*/
error_reporting(E_ALL);
}
- if ('cli' !== PHP_SAPI) {
+ if (!\in_array(PHP_SAPI, array('cli', 'phpdbg'), true)) {
ini_set('display_errors', 0);
ExceptionHandler::register();
} elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
{
private $classLoader;
private $isFinder;
+ private $loaded = array();
private static $caseCheck;
+ private static $checkedClasses = array();
private static $final = array();
private static $finalMethods = array();
private static $deprecated = array();
- private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
+ private static $internal = array();
+ private static $internalMethods = array();
private static $darwinCache = array('/' => array('/', array()));
- /**
- * Constructor.
- *
- * @param callable $classLoader A class loader
- */
public function __construct(callable $classLoader)
{
$this->classLoader = $classLoader;
*/
public function loadClass($class)
{
- ErrorHandler::stackErrors();
+ $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
try {
- if ($this->isFinder) {
- if ($file = $this->classLoader[0]->findFile($class)) {
- require_once $file;
+ if ($this->isFinder && !isset($this->loaded[$class])) {
+ $this->loaded[$class] = true;
+ if ($file = $this->classLoader[0]->findFile($class) ?: false) {
+ $wasCached = \function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file);
+
+ require $file;
+
+ if ($wasCached) {
+ return;
+ }
}
} else {
call_user_func($this->classLoader, $class);
$file = false;
}
} finally {
- ErrorHandler::unstackErrors();
+ error_reporting($e);
}
- $exists = class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
+ $this->checkClass($class, $file);
+ }
+
+ private function checkClass($class, $file = null)
+ {
+ $exists = null === $file || \class_exists($class, false) || \interface_exists($class, false) || \trait_exists($class, false);
- if ($class && '\\' === $class[0]) {
+ if (null !== $file && $class && '\\' === $class[0]) {
$class = substr($class, 1);
}
if ($exists) {
+ if (isset(self::$checkedClasses[$class])) {
+ return;
+ }
+ self::$checkedClasses[$class] = true;
+
$refl = new \ReflectionClass($class);
+ if (null === $file && $refl->isInternal()) {
+ return;
+ }
$name = $refl->getName();
- if ($name !== $class && 0 === strcasecmp($name, $class)) {
+ if ($name !== $class && 0 === \strcasecmp($name, $class)) {
throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
}
- $parent = get_parent_class($class);
+ // Don't trigger deprecations for classes in the same vendor
+ if (2 > $len = 1 + (\strpos($name, '\\') ?: \strpos($name, '_'))) {
+ $len = 0;
+ $ns = '';
+ } else {
+ $ns = \substr($name, 0, $len);
+ }
+
+ // Detect annotations on the class
+ if (false !== $doc = $refl->getDocComment()) {
+ foreach (array('final', 'deprecated', 'internal') as $annotation) {
+ if (false !== \strpos($doc, $annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) {
+ self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
+ }
+ }
+ }
- // Not an interface nor a trait
- if (class_exists($name, false)) {
- if (preg_match('#\n \* @final(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
- self::$final[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
+ $parentAndTraits = \class_uses($name, false);
+ if ($parent = \get_parent_class($class)) {
+ $parentAndTraits[] = $parent;
+
+ if (!isset(self::$checkedClasses[$parent])) {
+ $this->checkClass($parent);
}
- if ($parent && isset(self::$final[$parent])) {
+ if (isset(self::$final[$parent])) {
@trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED);
}
+ }
- // Inherit @final annotations
- self::$finalMethods[$name] = $parent && isset(self::$finalMethods[$parent]) ? self::$finalMethods[$parent] : array();
-
- foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
- if ($method->class !== $name) {
- continue;
- }
-
- if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
- @trigger_error(sprintf('%s It may change without further notice as of its next major version. You should not extend it from "%s".', self::$finalMethods[$parent][$method->name], $name), E_USER_DEPRECATED);
- }
+ // Detect if the parent is annotated
+ foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) {
+ if (!isset(self::$checkedClasses[$use])) {
+ $this->checkClass($use);
+ }
+ if (isset(self::$deprecated[$use]) && \strncmp($ns, $use, $len)) {
+ $type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait');
+ $verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
- $doc = $method->getDocComment();
- if (false === $doc || false === strpos($doc, '@final')) {
- continue;
- }
+ @trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED);
+ }
+ if (isset(self::$internal[$use]) && \strncmp($ns, $use, $len)) {
+ @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED);
+ }
+ }
- if (preg_match('#\n\s+\* @final(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
- $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
- self::$finalMethods[$name][$method->name] = sprintf('The "%s::%s()" method is considered final%s.', $name, $method->name, $message);
+ // Inherit @final and @internal annotations for methods
+ self::$finalMethods[$name] = array();
+ self::$internalMethods[$name] = array();
+ foreach ($parentAndTraits as $use) {
+ foreach (array('finalMethods', 'internalMethods') as $property) {
+ if (isset(self::${$property}[$use])) {
+ self::${$property}[$name] = self::${$property}[$name] ? self::${$property}[$use] + self::${$property}[$name] : self::${$property}[$use];
}
}
}
- if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
- @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
- } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
- self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
- } else {
- // Don't trigger deprecations for classes in the same vendor
- if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) {
- $len = 0;
- $ns = '';
- } else {
- switch ($ns = substr($name, 0, $len)) {
- case 'Symfony\Bridge\\':
- case 'Symfony\Bundle\\':
- case 'Symfony\Component\\':
- $ns = 'Symfony\\';
- $len = strlen($ns);
- break;
- }
+ $isClass = \class_exists($name, false);
+ foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
+ if ($method->class !== $name) {
+ continue;
}
- if (!$parent || strncmp($ns, $parent, $len)) {
- if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
- @trigger_error(sprintf('The "%s" class extends "%s" that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
- }
+ // Method from a trait
+ if ($method->getFilename() !== $refl->getFileName()) {
+ continue;
+ }
- $parentInterfaces = array();
- $deprecatedInterfaces = array();
- if ($parent) {
- foreach (class_implements($parent) as $interface) {
- $parentInterfaces[$interface] = 1;
- }
- }
+ if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) {
+ list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
+ @trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
+ }
- foreach ($refl->getInterfaceNames() as $interface) {
- if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
- $deprecatedInterfaces[] = $interface;
- }
- foreach (class_implements($interface) as $interface) {
- $parentInterfaces[$interface] = 1;
+ foreach ($parentAndTraits as $use) {
+ if (isset(self::$internalMethods[$use][$method->name])) {
+ list($declaringClass, $message) = self::$internalMethods[$use][$method->name];
+ if (\strncmp($ns, $declaringClass, $len)) {
+ @trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
}
}
+ }
- foreach ($deprecatedInterfaces as $interface) {
- if (!isset($parentInterfaces[$interface])) {
- @trigger_error(sprintf('The "%s" %s "%s" that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
- }
+ // Detect method annotations
+ if (false === $doc = $method->getDocComment()) {
+ continue;
+ }
+
+ foreach (array('final', 'internal') as $annotation) {
+ if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
+ $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
+ self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message);
}
}
}
throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)));
}
}
+ }
+ }
+
+ /**
+ * `class_implements` includes interfaces from the parents so we have to manually exclude them.
+ *
+ * @param string $class
+ * @param string|false $parent
+ *
+ * @return string[]
+ */
+ private function getOwnInterfaces($class, $parent)
+ {
+ $ownInterfaces = class_implements($class, false);
+
+ if ($parent) {
+ foreach (class_implements($parent, false) as $interface) {
+ unset($ownInterfaces[$interface]);
+ }
+ }
- return true;
+ foreach ($ownInterfaces as $interface) {
+ foreach (class_implements($interface) as $interface) {
+ unset($ownInterfaces[$interface]);
+ }
}
+
+ return $ownInterfaces;
}
}
use Psr\Log\LogLevel;
use Psr\Log\LoggerInterface;
-use Symfony\Component\Debug\Exception\ContextErrorException;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Symfony\Component\Debug\Exception\OutOfMemoryException;
private $bootstrappingLogger;
private static $reservedMemory;
- private static $stackedErrors = array();
- private static $stackedErrorLevels = array();
private static $toStringException = null;
private static $silencedErrorCache = array();
private static $silencedErrorCount = 0;
$handler = $prev[0];
$replace = false;
}
- if ($replace || !$prev) {
- $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
- } else {
+ if (!$replace && $prev) {
restore_error_handler();
+ $handlerIsRegistered = is_array($prev) && $handler === $prev[0];
+ } else {
+ $handlerIsRegistered = true;
+ }
+ if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
+ restore_exception_handler();
+ if (!$handlerIsRegistered) {
+ $handler = $prev[0];
+ } elseif ($handler !== $prev[0] && $replace) {
+ set_exception_handler(array($handler, 'handleException'));
+ $p = $prev[0]->setExceptionHandler(null);
+ $handler->setExceptionHandler($p);
+ $prev[0]->setExceptionHandler($p);
+ }
+ } else {
+ $handler->setExceptionHandler($prev);
}
$handler->throwAt(E_ALL & $handler->thrownErrors, true);
if (4 < $numArgs = func_num_args()) {
$context = $scope ? (func_get_arg(4) ?: array()) : array();
- $backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM
} else {
$context = array();
- $backtrace = null;
}
if (isset($context['GLOBALS']) && $scope) {
$context = $e;
}
- if (null !== $backtrace && $type & E_ERROR) {
- // E_ERROR fatal errors are triggered on HHVM when
- // hhvm.error_handling.call_user_handler_on_fatals=1
- // which is the way to get their backtrace.
- $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
-
- return true;
- }
-
$logMessage = $this->levels[$type].': '.$message;
if (null !== self::$toStringException) {
$errorAsException = self::$toStringException;
self::$toStringException = null;
} elseif (!$throw && !($type & $level)) {
- if (isset(self::$silencedErrorCache[$message])) {
+ if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
+ $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array();
+ $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
+ } elseif (isset(self::$silencedErrorCache[$id][$message])) {
$lightTrace = null;
- $errorAsException = self::$silencedErrorCache[$message];
+ $errorAsException = self::$silencedErrorCache[$id][$message];
++$errorAsException->count;
} else {
- $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array();
- $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
+ $lightTrace = array();
+ $errorAsException = null;
}
if (100 < ++self::$silencedErrorCount) {
self::$silencedErrorCache = $lightTrace = array();
self::$silencedErrorCount = 1;
}
- self::$silencedErrorCache[$message] = $errorAsException;
-
+ if ($errorAsException) {
+ self::$silencedErrorCache[$id][$message] = $errorAsException;
+ }
if (null === $lightTrace) {
return;
}
} else {
- if ($scope) {
- $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context);
- } else {
- $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
- }
+ $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
// Clean the trace by removing function arguments and the first frames added by the error handler itself.
if ($throw || $this->tracedErrors & $type) {
- $backtrace = $backtrace ?: $errorAsException->getTrace();
+ $backtrace = $errorAsException->getTrace();
$lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
$this->traceReflector->setValue($errorAsException, $lightTrace);
} else {
$this->traceReflector->setValue($errorAsException, array());
+ $backtrace = array();
}
}
&& ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
) {
// Here, we know trigger_error() has been called from __toString().
- // HHVM is fine with throwing from __toString() but PHP triggers a fatal error instead.
+ // PHP triggers a fatal error when throwing from __toString().
// A small convention allows working around the limitation:
// given a caught $e exception in __toString(), quitting the method with
// `return trigger_error($e, E_USER_ERROR);` allows this error handler
// to make $e get through the __toString() barrier.
foreach ($context as $e) {
- if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
- if (1 === $i) {
- // On HHVM
- $errorAsException = $e;
- break;
- }
+ if ($e instanceof \Throwable && $e->__toString() === $message) {
self::$toStringException = $e;
return true;
}
}
- if (1 < $i) {
- // On PHP (not on HHVM), display the original error message instead of the default one.
- $this->handleException($errorAsException);
+ // Display the original error message instead of the default one.
+ $this->handleException($errorAsException);
- // Stop the process by giving back the error to the native handler.
- return false;
- }
+ // Stop the process by giving back the error to the native handler.
+ return false;
}
}
}
if ($this->isRecursive) {
$log = 0;
- } elseif (self::$stackedErrorLevels) {
- self::$stackedErrors[] = array(
- $this->loggers[$type][0],
- ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG,
- $logMessage,
- array('exception' => $errorAsException),
- );
} else {
try {
$this->isRecursive = true;
$level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG;
- $this->loggers[$type][0]->log($level, $logMessage, array('exception' => $errorAsException));
+ $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array());
} finally {
$this->isRecursive = false;
}
$exception = new FatalThrowableError($exception);
}
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
+ $handlerException = null;
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
if ($exception instanceof FatalErrorException) {
if ($this->loggedErrors & $type) {
try {
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception));
- } catch (\Exception $handlerException) {
} catch (\Throwable $handlerException) {
}
}
}
}
}
- if (empty($this->exceptionHandler)) {
- throw $exception; // Give back $exception to the native handler
- }
+ $exceptionHandler = $this->exceptionHandler;
+ $this->exceptionHandler = null;
try {
- call_user_func($this->exceptionHandler, $exception);
- } catch (\Exception $handlerException) {
+ if (null !== $exceptionHandler) {
+ return \call_user_func($exceptionHandler, $exception);
+ }
+ $handlerException = $handlerException ?: $exception;
} catch (\Throwable $handlerException) {
}
- if (isset($handlerException)) {
- $this->exceptionHandler = null;
- $this->handleException($handlerException);
+ if ($exception === $handlerException) {
+ self::$reservedMemory = null; // Disable the fatal error handler
+ throw $exception; // Give back $exception to the native handler
}
+ $this->handleException($handlerException);
}
/**
return;
}
- self::$reservedMemory = null;
+ $handler = self::$reservedMemory = null;
+ $handlers = array();
+ $previousHandler = null;
+ $sameHandlerLimit = 10;
- $handler = set_error_handler('var_dump');
- $handler = is_array($handler) ? $handler[0] : null;
- restore_error_handler();
+ while (!is_array($handler) || !$handler[0] instanceof self) {
+ $handler = set_exception_handler('var_dump');
+ restore_exception_handler();
- if (!$handler instanceof self) {
+ if (!$handler) {
+ break;
+ }
+ restore_exception_handler();
+
+ if ($handler !== $previousHandler) {
+ array_unshift($handlers, $handler);
+ $previousHandler = $handler;
+ } elseif (0 === --$sameHandlerLimit) {
+ $handler = null;
+ break;
+ }
+ }
+ foreach ($handlers as $h) {
+ set_exception_handler($h);
+ }
+ if (!$handler) {
return;
}
+ if ($handler !== $h) {
+ $handler[0]->setExceptionHandler($h);
+ }
+ $handler = $handler[0];
+ $handlers = array();
if ($exit = null === $error) {
$error = error_get_last();
}
- try {
- while (self::$stackedErrorLevels) {
- static::unstackErrors();
- }
- } catch (\Exception $exception) {
- // Handled below
- } catch (\Throwable $exception) {
- // Handled below
- }
-
if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
// Let's not throw anymore but keep logging
$handler->throwAt(0, true);
} else {
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
}
+ } else {
+ $exception = null;
}
try {
- if (isset($exception)) {
+ if (null !== $exception) {
self::$exitCode = 255;
$handler->handleException($exception, $error);
}
}
}
- /**
- * Configures the error handler for delayed handling.
- * Ensures also that non-catchable fatal errors are never silenced.
- *
- * As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724
- * PHP has a compile stage where it behaves unusually. To workaround it,
- * we plug an error handler that only stacks errors for later.
- *
- * The most important feature of this is to prevent
- * autoloading until unstackErrors() is called.
- */
- public static function stackErrors()
- {
- self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
- }
-
- /**
- * Unstacks stacked errors and forwards to the logger.
- */
- public static function unstackErrors()
- {
- $level = array_pop(self::$stackedErrorLevels);
-
- if (null !== $level) {
- $errorReportingLevel = error_reporting($level);
- if ($errorReportingLevel !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
- // If the user changed the error level, do not overwrite it
- error_reporting($errorReportingLevel);
- }
- }
-
- if (empty(self::$stackedErrorLevels)) {
- $errors = self::$stackedErrors;
- self::$stackedErrors = array();
-
- foreach ($errors as $error) {
- $error[0]->log($error[1], $error[2], $error[3]);
- }
- }
- }
-
/**
* Gets the fatal error handlers.
*
}
if (!($throw || $this->scopedErrors & $type)) {
for ($i = 0; isset($lightTrace[$i]); ++$i) {
- unset($lightTrace[$i]['args']);
+ unset($lightTrace[$i]['args'], $lightTrace[$i]['object']);
}
}
*/
class ClassNotFoundException extends FatalErrorException
{
- public function __construct($message, \ErrorException $previous)
+ public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Debug\Exception;
-
-/**
- * Error Exception with Variable Context.
- *
- * @author Christian Sciberras <uuf6429@gmail.com>
- *
- * @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0.
- */
-class ContextErrorException extends \ErrorException
-{
- private $context = array();
-
- public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
- {
- parent::__construct($message, $code, $severity, $filename, $lineno);
- $this->context = $context;
- }
-
- /**
- * @return array Array of variables that existed when the exception occurred
- */
- public function getContext()
- {
- @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
-
- return $this->context;
- }
-}
*/
class FatalErrorException extends \ErrorException
{
- public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
+ public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null)
{
parent::__construct($message, $code, $severity, $filename, $lineno);
unset($frame);
$trace = array_reverse($trace);
- } elseif (function_exists('symfony_debug_backtrace')) {
- $trace = symfony_debug_backtrace();
- if (0 < $traceOffset) {
- array_splice($trace, 0, $traceOffset);
- }
} else {
$trace = array();
}
$e->getCode(),
$severity,
$e->getFile(),
- $e->getLine()
+ $e->getLine(),
+ $e->getPrevious()
);
$this->setTrace($e->getTrace());
private $line;
private $trace;
- public function __construct($severity, $file, $line, array $trace = array(), $count = 1)
+ public function __construct(int $severity, string $file, int $line, array $trace = array(), int $count = 1)
{
$this->severity = $severity;
$this->file = $file;
*/
class UndefinedFunctionException extends FatalErrorException
{
- public function __construct($message, \ErrorException $previous)
+ public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,
*/
class UndefinedMethodException extends FatalErrorException
{
- public function __construct($message, \ErrorException $previous)
+ public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,
private $caughtLength;
private $fileLinkFormat;
- public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
+ public function __construct(bool $debug = true, string $charset = null, $fileLinkFormat = null)
{
$this->debug = $debug;
$this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
- $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
+ $this->fileLinkFormat = $fileLinkFormat;
}
/**
/**
* Gets the HTML content associated with the given exception.
*
- * @param FlattenException $exception A FlattenException instance
- *
* @return string The content as a string
*/
public function getContent(FlattenException $exception)
/**
* Gets the stylesheet associated with the given exception.
*
- * @param FlattenException $exception A FlattenException instance
- *
* @return string The stylesheet as a string
*/
public function getStylesheet(FlattenException $exception)
.exception-message { flex-grow: 1; padding: 30px 0; }
.exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; }
.exception-message.long { font-size: 18px; }
- .exception-message a { text-decoration: none; }
- .exception-message a:hover { text-decoration: underline; }
+ .exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; }
+ .exception-message a:hover { border-bottom-color: #ffffff; }
.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }
.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; }
- .trace-file-path, .trace-file-path a { margin-top: 3px; color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; }
+ .trace-file-path, .trace-file-path a { color: #222; margin-top: 3px; font-size: 13px; }
.trace-class { color: #B0413E; }
.trace-type { padding: 0 2px; }
- .trace-method { color: #B0413E; color: #222; font-weight: bold; color: #B0413E; }
- .trace-arguments { color: #222; color: #999; font-weight: normal; color: #795da3; color: #777; padding-left: 2px; }
+ .trace-method { color: #B0413E; font-weight: bold; }
+ .trace-arguments { color: #777; font-weight: normal; padding-left: 2px; }
@media (min-width: 575px) {
.hidden-xs-down { display: initial; }
private function formatPath($path, $line)
{
$file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path);
- $fmt = $this->fileLinkFormat;
+ $fmt = $this->fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
+
+ if (!$fmt) {
+ return sprintf('<span class="block trace-file-path">in <a title="%s%3$s"><strong>%s</strong>%s</a></span>', $this->escapeHtml($path), $file, 0 < $line ? ' line '.$line : '');
+ }
+
+ if (\is_string($fmt)) {
+ $i = strpos($f = $fmt, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f);
+ $fmt = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE);
+
+ for ($i = 1; isset($fmt[$i]); ++$i) {
+ if (0 === strpos($path, $k = $fmt[$i++])) {
+ $path = substr_replace($path, $fmt[$i], 0, strlen($k));
+ break;
+ }
+ }
- if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $path, '%l' => $line)) : $fmt->format($path, $line)) {
- return sprintf('<span class="block trace-file-path">in <a href="%s" title="Go to source">%s (line %d)</a></span>', $this->escapeHtml($link), $file, $line);
+ $link = strtr($fmt[0], array('%f' => $path, '%l' => $line));
+ } else {
+ $link = $fmt->format($path, $line);
}
- return sprintf('<span class="block trace-file-path">in <a title="%s line %3$d"><strong>%s</strong> (line %d)</a></span>', $this->escapeHtml($path), $file, $line);
+ return sprintf('<span class="block trace-file-path">in <a href="%s" title="Go to source"><strong>%s</string>%s</a></span>', $this->escapeHtml($link), $file, 0 < $line ? ' line '.$line : '');
}
/**
*
* @return array An array of possible fully qualified class names
*/
- private function getClassCandidates($class)
+ private function getClassCandidates(string $class): array
{
if (!is_array($functions = spl_autoload_functions())) {
return array();
return array_unique($classes);
}
- /**
- * @param string $path
- * @param string $class
- * @param string $prefix
- *
- * @return array
- */
- private function findClassInPath($path, $class, $prefix)
+ private function findClassInPath(string $path, string $class, string $prefix): array
{
if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
return array();
return $classes;
}
- /**
- * @param string $path
- * @param string $file
- * @param string $prefix
- *
- * @return string|null
- */
- private function convertFileToClass($path, $file, $prefix)
+ private function convertFileToClass(string $path, string $file, string $prefix): ?string
{
$candidates = array(
// namespaced class
return $candidate;
}
}
+
+ return null;
}
- /**
- * @param string $class
- *
- * @return bool
- */
- private function classExists($class)
+ private function classExists(string $class): bool
{
return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
}
-Copyright (c) 2004-2017 Fabien Potencier
+Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+++ /dev/null
-Symfony Debug Extension for PHP 5
-=================================
-
-This extension publishes several functions to help building powerful debugging tools.
-It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes.
-It is not required thus not provided for PHP 7.
-
-symfony_zval_info()
--------------------
-
-- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP,
-- does work with references, preventing memory copying.
-
-Its behavior is about the same as:
-
-```php
-<?php
-
-function symfony_zval_info($key, $array, $options = 0)
-{
-
- // $options is currently not used, but could be in future version.
-
- if (!array_key_exists($key, $array)) {
- return null;
- }
-
- $info = array(
- 'type' => gettype($array[$key]),
- 'zval_hash' => /* hashed memory address of $array[$key] */,
- 'zval_refcount' => /* internal zval refcount of $array[$key] */,
- 'zval_isref' => /* is_ref status of $array[$key] */,
- );
-
- switch ($info['type']) {
- case 'object':
- $info += array(
- 'object_class' => get_class($array[$key]),
- 'object_refcount' => /* internal object refcount of $array[$key] */,
- 'object_hash' => spl_object_hash($array[$key]),
- 'object_handle' => /* internal object handle $array[$key] */,
- );
- break;
-
- case 'resource':
- $info += array(
- 'resource_handle' => (int) $array[$key],
- 'resource_type' => get_resource_type($array[$key]),
- 'resource_refcount' => /* internal resource refcount of $array[$key] */,
- );
- break;
-
- case 'array':
- $info += array(
- 'array_count' => count($array[$key]),
- );
- break;
-
- case 'string':
- $info += array(
- 'strlen' => strlen($array[$key]),
- );
- break;
- }
-
- return $info;
-}
-```
-
-symfony_debug_backtrace()
--------------------------
-
-This function works like debug_backtrace(), except that it can fetch the full backtrace in case of fatal errors:
-
-```php
-function foo() { fatal(); }
-function bar() { foo(); }
-
-function sd() { var_dump(symfony_debug_backtrace()); }
-
-register_shutdown_function('sd');
-
-bar();
-
-/* Will output
-Fatal error: Call to undefined function fatal() in foo.php on line 42
-array(3) {
- [0]=>
- array(2) {
- ["function"]=>
- string(2) "sd"
- ["args"]=>
- array(0) {
- }
- }
- [1]=>
- array(4) {
- ["file"]=>
- string(7) "foo.php"
- ["line"]=>
- int(1)
- ["function"]=>
- string(3) "foo"
- ["args"]=>
- array(0) {
- }
- }
- [2]=>
- array(4) {
- ["file"]=>
- string(102) "foo.php"
- ["line"]=>
- int(2)
- ["function"]=>
- string(3) "bar"
- ["args"]=>
- array(0) {
- }
- }
-}
-*/
-```
-
-Usage
------
-
-To enable the extension from source, run:
-
-```
- phpize
- ./configure
- make
- sudo make install
-```
+++ /dev/null
-dnl $Id$
-dnl config.m4 for extension symfony_debug
-
-dnl Comments in this file start with the string 'dnl'.
-dnl Remove where necessary. This file will not work
-dnl without editing.
-
-dnl If your extension references something external, use with:
-
-dnl PHP_ARG_WITH(symfony_debug, for symfony_debug support,
-dnl Make sure that the comment is aligned:
-dnl [ --with-symfony_debug Include symfony_debug support])
-
-dnl Otherwise use enable:
-
-PHP_ARG_ENABLE(symfony_debug, whether to enable symfony_debug support,
-dnl Make sure that the comment is aligned:
-[ --enable-symfony_debug Enable symfony_debug support])
-
-if test "$PHP_SYMFONY_DEBUG" != "no"; then
- dnl Write more examples of tests here...
-
- dnl # --with-symfony_debug -> check with-path
- dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
- dnl SEARCH_FOR="/include/symfony_debug.h" # you most likely want to change this
- dnl if test -r $PHP_SYMFONY_DEBUG/$SEARCH_FOR; then # path given as parameter
- dnl SYMFONY_DEBUG_DIR=$PHP_SYMFONY_DEBUG
- dnl else # search default path list
- dnl AC_MSG_CHECKING([for symfony_debug files in default path])
- dnl for i in $SEARCH_PATH ; do
- dnl if test -r $i/$SEARCH_FOR; then
- dnl SYMFONY_DEBUG_DIR=$i
- dnl AC_MSG_RESULT(found in $i)
- dnl fi
- dnl done
- dnl fi
- dnl
- dnl if test -z "$SYMFONY_DEBUG_DIR"; then
- dnl AC_MSG_RESULT([not found])
- dnl AC_MSG_ERROR([Please reinstall the symfony_debug distribution])
- dnl fi
-
- dnl # --with-symfony_debug -> add include path
- dnl PHP_ADD_INCLUDE($SYMFONY_DEBUG_DIR/include)
-
- dnl # --with-symfony_debug -> check for lib and symbol presence
- dnl LIBNAME=symfony_debug # you may want to change this
- dnl LIBSYMBOL=symfony_debug # you most likely want to change this
-
- dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
- dnl [
- dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DEBUG_DIR/lib, SYMFONY_DEBUG_SHARED_LIBADD)
- dnl AC_DEFINE(HAVE_SYMFONY_DEBUGLIB,1,[ ])
- dnl ],[
- dnl AC_MSG_ERROR([wrong symfony_debug lib version or lib not found])
- dnl ],[
- dnl -L$SYMFONY_DEBUG_DIR/lib -lm
- dnl ])
- dnl
- dnl PHP_SUBST(SYMFONY_DEBUG_SHARED_LIBADD)
-
- PHP_NEW_EXTENSION(symfony_debug, symfony_debug.c, $ext_shared)
-fi
+++ /dev/null
-// $Id$
-// vim:ft=javascript
-
-// If your extension references something external, use ARG_WITH
-// ARG_WITH("symfony_debug", "for symfony_debug support", "no");
-
-// Otherwise, use ARG_ENABLE
-// ARG_ENABLE("symfony_debug", "enable symfony_debug support", "no");
-
-if (PHP_SYMFONY_DEBUG != "no") {
- EXTENSION("symfony_debug", "symfony_debug.c");
-}
-
+++ /dev/null
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-#ifndef PHP_SYMFONY_DEBUG_H
-#define PHP_SYMFONY_DEBUG_H
-
-extern zend_module_entry symfony_debug_module_entry;
-#define phpext_symfony_debug_ptr &symfony_debug_module_entry
-
-#define PHP_SYMFONY_DEBUG_VERSION "2.7"
-
-#ifdef PHP_WIN32
-# define PHP_SYMFONY_DEBUG_API __declspec(dllexport)
-#elif defined(__GNUC__) && __GNUC__ >= 4
-# define PHP_SYMFONY_DEBUG_API __attribute__ ((visibility("default")))
-#else
-# define PHP_SYMFONY_DEBUG_API
-#endif
-
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-ZEND_BEGIN_MODULE_GLOBALS(symfony_debug)
- intptr_t req_rand_init;
- void (*old_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
- zval *debug_bt;
-ZEND_END_MODULE_GLOBALS(symfony_debug)
-
-PHP_MINIT_FUNCTION(symfony_debug);
-PHP_MSHUTDOWN_FUNCTION(symfony_debug);
-PHP_RINIT_FUNCTION(symfony_debug);
-PHP_RSHUTDOWN_FUNCTION(symfony_debug);
-PHP_MINFO_FUNCTION(symfony_debug);
-PHP_GINIT_FUNCTION(symfony_debug);
-PHP_GSHUTDOWN_FUNCTION(symfony_debug);
-
-PHP_FUNCTION(symfony_zval_info);
-PHP_FUNCTION(symfony_debug_backtrace);
-
-static char *_symfony_debug_memory_address_hash(void * TSRMLS_DC);
-static const char *_symfony_debug_zval_type(zval *);
-static const char* _symfony_debug_get_resource_type(long TSRMLS_DC);
-static int _symfony_debug_get_resource_refcount(long TSRMLS_DC);
-
-void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
-
-#ifdef ZTS
-#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v)
-#else
-#define SYMFONY_DEBUG_G(v) (symfony_debug_globals.v)
-#endif
-
-#endif /* PHP_SYMFONY_DEBUG_H */
+++ /dev/null
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-#include "php_ini.h"
-#include "ext/standard/info.h"
-#include "php_symfony_debug.h"
-#include "ext/standard/php_rand.h"
-#include "ext/standard/php_lcg.h"
-#include "ext/spl/php_spl.h"
-#include "Zend/zend_gc.h"
-#include "Zend/zend_builtin_functions.h"
-#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */
-#include "ext/standard/php_array.h"
-#include "Zend/zend_interfaces.h"
-#include "SAPI.h"
-
-#define IS_PHP_53 ZEND_EXTENSION_API_NO == 220090626
-
-ZEND_DECLARE_MODULE_GLOBALS(symfony_debug)
-
-ZEND_BEGIN_ARG_INFO_EX(symfony_zval_arginfo, 0, 0, 2)
- ZEND_ARG_INFO(0, key)
- ZEND_ARG_ARRAY_INFO(0, array, 0)
- ZEND_ARG_INFO(0, options)
-ZEND_END_ARG_INFO()
-
-const zend_function_entry symfony_debug_functions[] = {
- PHP_FE(symfony_zval_info, symfony_zval_arginfo)
- PHP_FE(symfony_debug_backtrace, NULL)
- PHP_FE_END
-};
-
-PHP_FUNCTION(symfony_debug_backtrace)
-{
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-#if IS_PHP_53
- zend_fetch_debug_backtrace(return_value, 1, 0 TSRMLS_CC);
-#else
- zend_fetch_debug_backtrace(return_value, 1, 0, 0 TSRMLS_CC);
-#endif
-
- if (!SYMFONY_DEBUG_G(debug_bt)) {
- return;
- }
-
- php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(SYMFONY_DEBUG_G(debug_bt)), 0 TSRMLS_CC);
-}
-
-PHP_FUNCTION(symfony_zval_info)
-{
- zval *key = NULL, *arg = NULL;
- zval **data = NULL;
- HashTable *array = NULL;
- long options = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zh|l", &key, &array, &options) == FAILURE) {
- return;
- }
-
- switch (Z_TYPE_P(key)) {
- case IS_STRING:
- if (zend_symtable_find(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&data) == FAILURE) {
- return;
- }
- break;
- case IS_LONG:
- if (zend_hash_index_find(array, Z_LVAL_P(key), (void **)&data)) {
- return;
- }
- break;
- }
-
- arg = *data;
-
- array_init(return_value);
-
- add_assoc_string(return_value, "type", (char *)_symfony_debug_zval_type(arg), 1);
- add_assoc_stringl(return_value, "zval_hash", _symfony_debug_memory_address_hash((void *)arg TSRMLS_CC), 16, 0);
- add_assoc_long(return_value, "zval_refcount", Z_REFCOUNT_P(arg));
- add_assoc_bool(return_value, "zval_isref", (zend_bool)Z_ISREF_P(arg));
-
- if (Z_TYPE_P(arg) == IS_OBJECT) {
- char hash[33] = {0};
-
- php_spl_object_hash(arg, (char *)hash TSRMLS_CC);
- add_assoc_stringl(return_value, "object_class", (char *)Z_OBJCE_P(arg)->name, Z_OBJCE_P(arg)->name_length, 1);
- add_assoc_long(return_value, "object_refcount", EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(arg)].bucket.obj.refcount);
- add_assoc_string(return_value, "object_hash", hash, 1);
- add_assoc_long(return_value, "object_handle", Z_OBJ_HANDLE_P(arg));
- } else if (Z_TYPE_P(arg) == IS_ARRAY) {
- add_assoc_long(return_value, "array_count", zend_hash_num_elements(Z_ARRVAL_P(arg)));
- } else if(Z_TYPE_P(arg) == IS_RESOURCE) {
- add_assoc_long(return_value, "resource_handle", Z_LVAL_P(arg));
- add_assoc_string(return_value, "resource_type", (char *)_symfony_debug_get_resource_type(Z_LVAL_P(arg) TSRMLS_CC), 1);
- add_assoc_long(return_value, "resource_refcount", _symfony_debug_get_resource_refcount(Z_LVAL_P(arg) TSRMLS_CC));
- } else if (Z_TYPE_P(arg) == IS_STRING) {
- add_assoc_long(return_value, "strlen", Z_STRLEN_P(arg));
- }
-}
-
-void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args)
-{
- TSRMLS_FETCH();
- zval *retval;
-
- switch (type) {
- case E_ERROR:
- case E_PARSE:
- case E_CORE_ERROR:
- case E_CORE_WARNING:
- case E_COMPILE_ERROR:
- case E_COMPILE_WARNING:
- ALLOC_INIT_ZVAL(retval);
-#if IS_PHP_53
- zend_fetch_debug_backtrace(retval, 1, 0 TSRMLS_CC);
-#else
- zend_fetch_debug_backtrace(retval, 1, 0, 0 TSRMLS_CC);
-#endif
- SYMFONY_DEBUG_G(debug_bt) = retval;
- }
-
- SYMFONY_DEBUG_G(old_error_cb)(type, error_filename, error_lineno, format, args);
-}
-
-static const char* _symfony_debug_get_resource_type(long rsid TSRMLS_DC)
-{
- const char *res_type;
- res_type = zend_rsrc_list_get_rsrc_type(rsid TSRMLS_CC);
-
- if (!res_type) {
- return "Unknown";
- }
-
- return res_type;
-}
-
-static int _symfony_debug_get_resource_refcount(long rsid TSRMLS_DC)
-{
- zend_rsrc_list_entry *le;
-
- if (zend_hash_index_find(&EG(regular_list), rsid, (void **) &le)==SUCCESS) {
- return le->refcount;
- }
-
- return 0;
-}
-
-static char *_symfony_debug_memory_address_hash(void *address TSRMLS_DC)
-{
- char *result = NULL;
- intptr_t address_rand;
-
- if (!SYMFONY_DEBUG_G(req_rand_init)) {
- if (!BG(mt_rand_is_seeded)) {
- php_mt_srand(GENERATE_SEED() TSRMLS_CC);
- }
- SYMFONY_DEBUG_G(req_rand_init) = (intptr_t)php_mt_rand(TSRMLS_C);
- }
-
- address_rand = (intptr_t)address ^ SYMFONY_DEBUG_G(req_rand_init);
-
- spprintf(&result, 17, "%016zx", address_rand);
-
- return result;
-}
-
-static const char *_symfony_debug_zval_type(zval *zv)
-{
- switch (Z_TYPE_P(zv)) {
- case IS_NULL:
- return "NULL";
- break;
-
- case IS_BOOL:
- return "boolean";
- break;
-
- case IS_LONG:
- return "integer";
- break;
-
- case IS_DOUBLE:
- return "double";
- break;
-
- case IS_STRING:
- return "string";
- break;
-
- case IS_ARRAY:
- return "array";
- break;
-
- case IS_OBJECT:
- return "object";
-
- case IS_RESOURCE:
- return "resource";
-
- default:
- return "unknown type";
- }
-}
-
-zend_module_entry symfony_debug_module_entry = {
- STANDARD_MODULE_HEADER,
- "symfony_debug",
- symfony_debug_functions,
- PHP_MINIT(symfony_debug),
- PHP_MSHUTDOWN(symfony_debug),
- PHP_RINIT(symfony_debug),
- PHP_RSHUTDOWN(symfony_debug),
- PHP_MINFO(symfony_debug),
- PHP_SYMFONY_DEBUG_VERSION,
- PHP_MODULE_GLOBALS(symfony_debug),
- PHP_GINIT(symfony_debug),
- PHP_GSHUTDOWN(symfony_debug),
- NULL,
- STANDARD_MODULE_PROPERTIES_EX
-};
-
-#ifdef COMPILE_DL_SYMFONY_DEBUG
-ZEND_GET_MODULE(symfony_debug)
-#endif
-
-PHP_GINIT_FUNCTION(symfony_debug)
-{
- memset(symfony_debug_globals, 0 , sizeof(*symfony_debug_globals));
-}
-
-PHP_GSHUTDOWN_FUNCTION(symfony_debug)
-{
-
-}
-
-PHP_MINIT_FUNCTION(symfony_debug)
-{
- SYMFONY_DEBUG_G(old_error_cb) = zend_error_cb;
- zend_error_cb = symfony_debug_error_cb;
-
- return SUCCESS;
-}
-
-PHP_MSHUTDOWN_FUNCTION(symfony_debug)
-{
- zend_error_cb = SYMFONY_DEBUG_G(old_error_cb);
-
- return SUCCESS;
-}
-
-PHP_RINIT_FUNCTION(symfony_debug)
-{
- return SUCCESS;
-}
-
-PHP_RSHUTDOWN_FUNCTION(symfony_debug)
-{
- return SUCCESS;
-}
-
-PHP_MINFO_FUNCTION(symfony_debug)
-{
- php_info_print_table_start();
- php_info_print_table_header(2, "Symfony Debug support", "enabled");
- php_info_print_table_header(2, "Symfony Debug version", PHP_SYMFONY_DEBUG_VERSION);
- php_info_print_table_end();
-}
+++ /dev/null
---TEST--
-Test symfony_zval_info API
---SKIPIF--
-<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
---FILE--
-<?php
-
-$int = 42;
-$float = 42.42;
-$str = 'foobar';
-$object = new StdClass();
-$array = array('foo', 'bar');
-$resource = tmpfile();
-$null = null;
-$bool = true;
-
-$anotherint = 42;
-$refcount2 = &$anotherint;
-
-$var = array(
- 'int' => $int,
- 'float' => $float,
- 'str' => $str,
- 'object' => $object,
- 'array' => $array,
- 'resource' => $resource,
- 'null' => $null,
- 'bool' => $bool,
- 'refcount' => &$refcount2,
-);
-
-var_dump(symfony_zval_info('int', $var));
-var_dump(symfony_zval_info('float', $var));
-var_dump(symfony_zval_info('str', $var));
-var_dump(symfony_zval_info('object', $var));
-var_dump(symfony_zval_info('array', $var));
-var_dump(symfony_zval_info('resource', $var));
-var_dump(symfony_zval_info('null', $var));
-var_dump(symfony_zval_info('bool', $var));
-
-var_dump(symfony_zval_info('refcount', $var));
-var_dump(symfony_zval_info('not-exist', $var));
-?>
---EXPECTF--
-array(4) {
- ["type"]=>
- string(7) "integer"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
-}
-array(4) {
- ["type"]=>
- string(6) "double"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
-}
-array(5) {
- ["type"]=>
- string(6) "string"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
- ["strlen"]=>
- int(6)
-}
-array(8) {
- ["type"]=>
- string(6) "object"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
- ["object_class"]=>
- string(8) "stdClass"
- ["object_refcount"]=>
- int(1)
- ["object_hash"]=>
- string(32) "%s"
- ["object_handle"]=>
- int(%d)
-}
-array(5) {
- ["type"]=>
- string(5) "array"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
- ["array_count"]=>
- int(2)
-}
-array(7) {
- ["type"]=>
- string(8) "resource"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
- ["resource_handle"]=>
- int(%d)
- ["resource_type"]=>
- string(6) "stream"
- ["resource_refcount"]=>
- int(1)
-}
-array(4) {
- ["type"]=>
- string(4) "NULL"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
-}
-array(4) {
- ["type"]=>
- string(7) "boolean"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(2)
- ["zval_isref"]=>
- bool(false)
-}
-array(4) {
- ["type"]=>
- string(7) "integer"
- ["zval_hash"]=>
- string(16) "%s"
- ["zval_refcount"]=>
- int(3)
- ["zval_isref"]=>
- bool(true)
-}
-NULL
+++ /dev/null
---TEST--
-Test symfony_debug_backtrace in case of fatal error
---SKIPIF--
-<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
---FILE--
-<?php
-
-function bar()
-{
- foo();
-}
-
-function foo()
-{
- notexist();
-}
-
-function bt()
-{
- print_r(symfony_debug_backtrace());
-}
-
-register_shutdown_function('bt');
-
-bar();
-
-?>
---EXPECTF--
-Fatal error: Call to undefined function notexist() in %s on line %d
-Array
-(
- [0] => Array
- (
- [function] => bt
- [args] => Array
- (
- )
-
- )
-
- [1] => Array
- (
- [file] => %s
- [line] => %d
- [function] => foo
- [args] => Array
- (
- )
-
- )
-
- [2] => Array
- (
- [file] => %s
- [line] => %d
- [function] => bar
- [args] => Array
- (
- )
-
- )
-
-)
+++ /dev/null
---TEST--
-Test symfony_debug_backtrace in case of non fatal error
---SKIPIF--
-<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
---FILE--
-<?php
-
-function bar()
-{
- bt();
-}
-
-function bt()
-{
- print_r(symfony_debug_backtrace());
-}
-
-bar();
-
-?>
---EXPECTF--
-Array
-(
- [0] => Array
- (
- [file] => %s
- [line] => %d
- [function] => bt
- [args] => Array
- (
- )
-
- )
-
- [1] => Array
- (
- [file] => %s
- [line] => %d
- [function] => bar
- [args] => Array
- (
- )
-
- )
-
-)
+++ /dev/null
---TEST--
-Test ErrorHandler in case of fatal error
---SKIPIF--
-<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
---FILE--
-<?php
-
-namespace Psr\Log;
-
-class LogLevel
-{
- const EMERGENCY = 'emergency';
- const ALERT = 'alert';
- const CRITICAL = 'critical';
- const ERROR = 'error';
- const WARNING = 'warning';
- const NOTICE = 'notice';
- const INFO = 'info';
- const DEBUG = 'debug';
-}
-
-namespace Symfony\Component\Debug;
-
-$dir = __DIR__.'/../../../';
-require $dir.'ErrorHandler.php';
-require $dir.'Exception/FatalErrorException.php';
-require $dir.'Exception/UndefinedFunctionException.php';
-require $dir.'FatalErrorHandler/FatalErrorHandlerInterface.php';
-require $dir.'FatalErrorHandler/ClassNotFoundFatalErrorHandler.php';
-require $dir.'FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php';
-require $dir.'FatalErrorHandler/UndefinedMethodFatalErrorHandler.php';
-
-function bar()
-{
- foo();
-}
-
-function foo()
-{
- notexist();
-}
-
-$handler = ErrorHandler::register();
-$handler->setExceptionHandler('print_r');
-
-if (function_exists('xdebug_disable')) {
- xdebug_disable();
-}
-
-bar();
-?>
---EXPECTF--
-Fatal error: Call to undefined function Symfony\Component\Debug\notexist() in %s on line %d
-Symfony\Component\Debug\Exception\UndefinedFunctionException Object
-(
- [message:protected] => Attempted to call function "notexist" from namespace "Symfony\Component\Debug".
- [string:Exception:private] =>
- [code:protected] => 0
- [file:protected] => %s
- [line:protected] => %d
- [trace:Exception:private] => Array
- (
- [0] => Array
- (
-%A [function] => Symfony\Component\Debug\foo
-%A [args] => Array
- (
- )
-
- )
-
- [1] => Array
- (
-%A [function] => Symfony\Component\Debug\bar
-%A [args] => Array
- (
- )
-
- )
-%A
- )
-
- [previous:Exception:private] =>
- [severity:protected] => 1
-)
use PHPUnit\Framework\TestCase;
use Symfony\Component\Debug\DebugClassLoader;
-use Symfony\Component\Debug\ErrorHandler;
class DebugClassLoaderTest extends TestCase
{
$this->fail('DebugClassLoader did not register');
}
- public function testUnsilencing()
- {
- if (\PHP_VERSION_ID >= 70000) {
- $this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.');
- }
- if (defined('HHVM_VERSION')) {
- $this->markTestSkipped('HHVM is not handled in this test case.');
- }
-
- ob_start();
-
- $this->iniSet('log_errors', 0);
- $this->iniSet('display_errors', 1);
-
- // See below: this will fail with parse error
- // but this should not be @-silenced.
- @class_exists(__NAMESPACE__.'\TestingUnsilencing', true);
-
- $output = ob_get_clean();
-
- $this->assertStringMatchesFormat('%aParse error%a', $output);
- }
-
- public function testStacking()
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage boo
+ */
+ public function testThrowingClass()
{
- // the ContextErrorException must not be loaded to test the workaround
- // for https://bugs.php.net/65322.
- if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) {
- $this->markTestSkipped('The ContextErrorException class is already loaded.');
- }
- if (defined('HHVM_VERSION')) {
- $this->markTestSkipped('HHVM is not handled in this test case.');
- }
-
- ErrorHandler::register();
-
try {
- // Trigger autoloading + E_STRICT at compile time
- // which in turn triggers $errorHandler->handle()
- // that again triggers autoloading for ContextErrorException.
- // Error stacking works around the bug above and everything is fine.
-
- eval('
- namespace '.__NAMESPACE__.';
- class ChildTestingStacking extends TestingStacking { function foo($bar) {} }
- ');
- $this->fail('ContextErrorException expected');
- } catch (\ErrorException $exception) {
- // if an exception is thrown, the test passed
- $this->assertStringStartsWith(__FILE__, $exception->getFile());
- if (\PHP_VERSION_ID < 70000) {
- $this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage());
- $this->assertEquals(E_STRICT, $exception->getSeverity());
- } else {
- $this->assertRegExp('/^Warning: Declaration/', $exception->getMessage());
- $this->assertEquals(E_WARNING, $exception->getSeverity());
- }
- } finally {
- restore_error_handler();
- restore_exception_handler();
+ class_exists(__NAMESPACE__.'\Fixtures\Throwing');
+ $this->fail('Exception expected');
+ } catch (\Exception $e) {
+ $this->assertSame('boo', $e->getMessage());
}
+
+ // the second call also should throw
+ class_exists(__NAMESPACE__.'\Fixtures\Throwing');
}
/**
$this->assertSame($xError, $lastError);
}
- public function testReservedForPhp7()
+ public function testExtendedFinalClass()
{
- if (\PHP_VERSION_ID >= 70000) {
- $this->markTestSkipped('PHP7 already prevents using reserved names.');
- }
-
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
- class_exists('Test\\'.__NAMESPACE__.'\\Float', true);
+ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true);
error_reporting($e);
restore_error_handler();
$xError = array(
'type' => E_USER_DEPRECATED,
- 'message' => 'The "Test\Symfony\Component\Debug\Tests\Float" class uses the reserved name "Float", it will break on PHP 7 and higher',
+ 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".',
);
$this->assertSame($xError, $lastError);
}
- public function testExtendedFinalClass()
+ public function testExtendedFinalMethod()
{
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
- class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true);
+ class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true);
error_reporting($e);
restore_error_handler();
$xError = array(
'type' => E_USER_DEPRECATED,
- 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".',
+ 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".',
);
$this->assertSame($xError, $lastError);
}
- public function testExtendedFinalMethod()
+ public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice()
{
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
- class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true);
+ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true);
error_reporting($e);
restore_error_handler();
$lastError = error_get_last();
unset($lastError['file'], $lastError['line']);
- $xError = array(
- 'type' => E_USER_DEPRECATED,
- 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".',
- );
+ $this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError);
+ }
- $this->assertSame($xError, $lastError);
+ public function testInternalsUse()
+ {
+ $deprecations = array();
+ set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
+ $e = error_reporting(E_USER_DEPRECATED);
+
+ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $this->assertSame($deprecations, array(
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
+ ));
}
}
eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }');
} elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
- } elseif (__NAMESPACE__.'\Fixtures\CaseMismatch' === $class) {
- return $fixtureDir.'CaseMismatch.php';
} elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) {
return $fixtureDir.'reallyNotPsr0.php';
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) {
return $fixtureDir.'notPsr0Bis.php';
- } elseif (__NAMESPACE__.'\Fixtures\DeprecatedInterface' === $class) {
- return $fixtureDir.'DeprecatedInterface.php';
- } elseif (__NAMESPACE__.'\Fixtures\FinalClass' === $class) {
- return $fixtureDir.'FinalClass.php';
- } elseif (__NAMESPACE__.'\Fixtures\FinalMethod' === $class) {
- return $fixtureDir.'FinalMethod.php';
- } elseif (__NAMESPACE__.'\Fixtures\ExtendedFinalMethod' === $class) {
- return $fixtureDir.'ExtendedFinalMethod.php';
} elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) {
eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}');
} elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}');
+ } elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass {
+ public function deprecatedMethod() { }
+ }');
+ } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent {
+ use \\'.__NAMESPACE__.'\Fixtures\InternalTrait;
+
+ public function internalMethod() { }
+ }');
+ } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }');
}
}
}
$newHandler = new ErrorHandler();
- $this->assertSame($newHandler, ErrorHandler::register($newHandler, false));
+ $this->assertSame($handler, ErrorHandler::register($newHandler, false));
$h = set_error_handler('var_dump');
restore_error_handler();
$this->assertSame(array($handler, 'handleError'), $h);
// dummy function to test trace in error handler.
private static function triggerNotice($that)
{
- // dummy variable to check for in error handler.
- $foobar = 123;
$that->assertSame('', $foo.$foo.$bar);
}
}
}
- public function testErrorStacking()
- {
- try {
- $handler = ErrorHandler::register();
- $handler->screamAt(E_USER_WARNING);
-
- $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
-
- $logger
- ->expects($this->exactly(2))
- ->method('log')
- ->withConsecutive(
- array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')),
- array($this->equalTo(LogLevel::DEBUG), $this->equalTo('User Warning: Silenced warning'))
- )
- ;
-
- $handler->setDefaultLogger($logger, array(E_USER_WARNING => LogLevel::WARNING));
-
- ErrorHandler::stackErrors();
- @trigger_error('Silenced warning', E_USER_WARNING);
- $logger->log(LogLevel::WARNING, 'Dummy log');
- ErrorHandler::unstackErrors();
- } finally {
- restore_error_handler();
- restore_exception_handler();
- }
- }
-
public function testBootstrappingLogger()
{
$bootLogger = new BufferingLogger();
}
}
- /**
- * @requires PHP 7
- */
public function testHandleErrorException()
{
$exception = new \Error("Class 'Foo' not found");
$this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
}
- public function testHandleFatalErrorOnHHVM()
+ /**
+ * @expectedException \Exception
+ */
+ public function testCustomExceptionHandler()
{
- try {
- $handler = ErrorHandler::register();
-
- $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
- $logger
- ->expects($this->once())
- ->method('log')
- ->with(
- $this->equalTo(LogLevel::CRITICAL),
- $this->equalTo('Fatal Error: foo')
- )
- ;
-
- $handler->setDefaultLogger($logger, E_ERROR);
-
- $error = array(
- 'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors
- 'message' => 'foo',
- 'file' => 'bar',
- 'line' => 123,
- 'context' => array(123),
- 'backtrace' => array(456),
- );
+ $handler = new ErrorHandler();
+ $handler->setExceptionHandler(function ($e) use ($handler) {
+ $handler->handleException($e);
+ });
- call_user_func_array(array($handler, 'handleError'), $error);
- $handler->handleFatalError($error);
- } finally {
- restore_error_handler();
- restore_exception_handler();
- }
+ $handler->handleException(new \Exception());
}
}
/**
* @dataProvider flattenDataProvider
*/
- public function testFlattenHttpException(\Exception $exception, $statusCode)
+ public function testFlattenHttpException(\Exception $exception)
{
$flattened = FlattenException::create($exception);
$flattened2 = FlattenException::create($exception);
/**
* @dataProvider flattenDataProvider
*/
- public function testPrevious(\Exception $exception, $statusCode)
+ public function testPrevious(\Exception $exception)
{
$flattened = FlattenException::create($exception);
$flattened2 = FlattenException::create($exception);
$this->assertSame(array($flattened2), $flattened->getAllPrevious());
}
- /**
- * @requires PHP 7.0
- */
public function testPreviousError()
{
$exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42));
/**
* @dataProvider flattenDataProvider
*/
- public function testToArray(\Exception $exception, $statusCode)
+ public function testToArray(\Exception $exception)
{
$flattened = FlattenException::create($exception);
$flattened->setTrace(array(), 'foo.php', 123);
public function flattenDataProvider()
{
return array(
- array(new \Exception('test', 123), 500),
+ array(new \Exception('test', 123)),
);
}
$this->assertSame(array('object', 'stdClass'), $array[$i++]);
$this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]);
$this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]);
- $this->assertSame(array('resource', defined('HHVM_VERSION') ? 'Directory' : 'stream'), $array[$i++]);
+ $this->assertSame(array('resource', 'stream'), $array[$i++]);
$this->assertSame(array('resource', 'stream'), $array[$i++]);
$args = $array[$i++];
public function testRecursionInArguments()
{
+ $a = null;
$a = array('foo', array(2, &$a));
$exception = $this->createException($a);
$exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
$this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception);
- // class names are case insensitive and PHP/HHVM do not return the same
+ // class names are case insensitive and PHP do not return the same
$this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage()));
$this->assertSame($error['type'], $exception->getSeverity());
$this->assertSame($error['file'], $exception->getFile());
--- /dev/null
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class AnnotatedClass
+{
+ /**
+ * @deprecated
+ */
+ public function deprecatedMethod()
+ {
+ }
+}
/**
* @deprecated but this is a test
- * deprecation notice.
+ * deprecation notice
* @foobar
*/
class DeprecatedClass
/**
* @deprecated but this is a test
- * deprecation notice.
+ * deprecation notice
* @foobar
*/
interface DeprecatedInterface
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
- * @final since version 3.3.
+ * @final
*/
class FinalClass
{
class FinalMethod
{
/**
- * @final since version 3.3.
+ * @final
*/
public function finalMethod()
{
--- /dev/null
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal
+ */
+class InternalClass
+{
+ use InternalTrait2;
+
+ public function usedInInternalClass()
+ {
+ }
+}
--- /dev/null
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal
+ */
+interface InternalInterface
+{
+}
--- /dev/null
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal
+ */
+trait InternalTrait
+{
+}
--- /dev/null
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal
+ */
+trait InternalTrait2
+{
+ /**
+ * @internal
+ */
+ public function internalMethod()
+ {
+ }
+
+ /**
+ * @internal but should not trigger a deprecation
+ */
+ public function usedInInternalClass()
+ {
+ }
+}
--- /dev/null
+<?php
+
+throw new \Exception('boo');
--- /dev/null
+--TEST--
+Test DebugClassLoader with previously loaded parents
+--FILE--
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+use Symfony\Component\Debug\DebugClassLoader;
+
+$vendor = __DIR__;
+while (!file_exists($vendor.'/vendor')) {
+ $vendor = dirname($vendor);
+}
+require $vendor.'/vendor/autoload.php';
+
+class_exists(FinalMethod::class);
+
+set_error_handler(function ($type, $msg) { echo $msg, "\n"; });
+
+DebugClassLoader::enable();
+
+class_exists(ExtendedFinalMethod::class);
+
+?>
+--EXPECTF--
+The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".
--- /dev/null
+--TEST--
+Test catching fatal errors when handlers are nested
+--FILE--
+<?php
+
+namespace Symfony\Component\Debug;
+
+$vendor = __DIR__;
+while (!file_exists($vendor.'/vendor')) {
+ $vendor = dirname($vendor);
+}
+require $vendor.'/vendor/autoload.php';
+
+set_error_handler('var_dump');
+set_exception_handler('var_dump');
+
+ErrorHandler::register(null, false);
+
+if (true) {
+ class foo extends missing
+ {
+ }
+}
+
+?>
+--EXPECTF--
+Fatal error: Class 'Symfony\Component\Debug\missing' not found in %s on line %d
+object(Symfony\Component\Debug\Exception\ClassNotFoundException)#%d (8) {
+ ["message":protected]=>
+ string(131) "Attempted to load class "missing" from namespace "Symfony\Component\Debug".
+Did you forget a "use" statement for another namespace?"
+ ["string":"Exception":private]=>
+ string(0) ""
+ ["code":protected]=>
+ int(0)
+ ["file":protected]=>
+ string(%d) "%s"
+ ["line":protected]=>
+ int(%d)
+ ["trace":"Exception":private]=>
+ array(0) {
+ }
+ ["previous":"Exception":private]=>
+ NULL
+ ["severity":protected]=>
+ int(1)
+}
--- /dev/null
+--TEST--
+Test rethrowing in custom exception handler
+--FILE--
+<?php
+
+namespace Symfony\Component\Debug;
+
+$vendor = __DIR__;
+while (!file_exists($vendor.'/vendor')) {
+ $vendor = dirname($vendor);
+}
+require $vendor.'/vendor/autoload.php';
+
+if (true) {
+ class TestLogger extends \Psr\Log\AbstractLogger
+ {
+ public function log($level, $message, array $context = array())
+ {
+ echo $message, "\n";
+ }
+ }
+}
+
+set_exception_handler(function ($e) { echo 123; throw $e; });
+ErrorHandler::register()->setDefaultLogger(new TestLogger());
+ini_set('display_errors', 1);
+
+throw new \Exception('foo');
+?>
+--EXPECTF--
+Uncaught Exception: foo
+123
+Fatal error: Uncaught %s:25
+Stack trace:
+%a
--- /dev/null
+--TEST--
+Test catching fatal errors when handlers are nested
+--FILE--
+<?php
+
+namespace Symfony\Component\Debug;
+
+$vendor = __DIR__;
+while (!file_exists($vendor.'/vendor')) {
+ $vendor = dirname($vendor);
+}
+require $vendor.'/vendor/autoload.php';
+
+Debug::enable();
+ini_set('display_errors', 0);
+
+$eHandler = set_error_handler('var_dump');
+$xHandler = set_exception_handler('var_dump');
+
+var_dump(array(
+ $eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different',
+));
+
+$eHandler[0]->setExceptionHandler('print_r');
+
+if (true) {
+ class Broken implements \Serializable
+ {
+ }
+}
+
+?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ string(37) "Error and exception handlers do match"
+}
+object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) {
+ ["message":protected]=>
+ string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)"
+%a
+}
}
],
"require": {
- "php": ">=5.5.9",
+ "php": "^7.1.3",
"psr/log": "~1.0"
},
"conflict": {
- "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ "symfony/http-kernel": "<3.4"
},
"require-dev": {
- "symfony/http-kernel": "~2.8|~3.0"
+ "symfony/http-kernel": "~3.4|~4.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Debug\\": "" },
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
}
}
CHANGELOG
=========
+4.0.0
+-----
+
+ * removed `ExceptionInterface`
+ * removed `Symfony\Component\Finder\Iterator\FilterIterator`
+
+3.4.0
+-----
+
+ * deprecated `Symfony\Component\Finder\Iterator\FilterIterator`
+ * added Finder::hasResults() method to check if any results were found
+
3.3.0
-----
class DateComparator extends Comparator
{
/**
- * Constructor.
- *
* @param string $test A comparison string
*
* @throws \InvalidArgumentException If the test is not understood
*/
- public function __construct($test)
+ public function __construct(string $test)
{
if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
class NumberComparator extends Comparator
{
/**
- * Constructor.
- *
* @param string|int $test A comparison string or an integer
*
* @throws \InvalidArgumentException If the test is not understood
*/
- public function __construct($test)
+ public function __construct(?string $test)
{
if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Exception;
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 3.3, to be removed in 4.0.
- */
-interface ExceptionInterface
-{
- /**
- * @return \Symfony\Component\Finder\Adapter\AdapterInterface
- */
- public function getAdapter();
-}
private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
- /**
- * Constructor.
- */
public function __construct()
{
$this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
/**
* Excludes directories.
*
+ * Directories passed as argument must be relative to the ones defined with the `in()` method. For example:
+ *
+ * $finder->in(__DIR__)->exclude('ruby');
+ *
* @param string|array $dirs A directory path or an array of directories
*
* @return $this
/**
* Excludes "hidden" directories and files (starting with a dot).
*
+ * This option is enabled by default.
+ *
* @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
*
* @return $this
/**
* Forces the finder to ignore version control directories.
*
+ * This option is enabled by default.
+ *
* @param bool $ignoreVCS Whether to exclude VCS files or not
*
* @return $this
*
* This can be slow as all the matching files and directories must be retrieved for comparison.
*
- * @param \Closure $closure An anonymous function
- *
* @return $this
*
* @see SortableIterator
* The anonymous function receives a \SplFileInfo and must return false
* to remove files.
*
- * @param \Closure $closure An anonymous function
- *
* @return $this
*
* @see CustomFilterIterator
foreach ((array) $dirs as $dir) {
if (is_dir($dir)) {
- $resolvedDirs[] = $dir;
+ $resolvedDirs[] = $this->normalizeDir($dir);
} elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
- $resolvedDirs = array_merge($resolvedDirs, $glob);
+ $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob));
} else {
throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
}
*
* @return $this
*
- * @throws \InvalidArgumentException When the given argument is not iterable.
+ * @throws \InvalidArgumentException when the given argument is not iterable
*/
public function append($iterator)
{
return $this;
}
+ /**
+ * Check if the any results were found.
+ *
+ * @return bool
+ */
+ public function hasResults()
+ {
+ foreach ($this->getIterator() as $_) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Counts all the results collected by the iterators.
*
return iterator_count($this->getIterator());
}
- /**
- * @param $dir
- *
- * @return \Iterator
- */
- private function searchInDirectory($dir)
+ private function searchInDirectory(string $dir): \Iterator
{
if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
$this->exclude = array_merge($this->exclude, self::$vcsPatterns);
return $iterator;
}
+
+ /**
+ * Normalizes given directory names by removing trailing slashes.
+ *
+ * @param string $dir
+ *
+ * @return string
+ */
+ private function normalizeDir($dir)
+ {
+ return rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
+ }
}
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class CustomFilterIterator extends FilterIterator
+class CustomFilterIterator extends \FilterIterator
{
private $filters = array();
/**
- * Constructor.
- *
* @param \Iterator $iterator The Iterator to filter
* @param callable[] $filters An array of PHP callbacks
*
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class DateRangeFilterIterator extends FilterIterator
+class DateRangeFilterIterator extends \FilterIterator
{
private $comparators = array();
/**
- * Constructor.
- *
* @param \Iterator $iterator The Iterator to filter
* @param DateComparator[] $comparators An array of DateComparator instances
*/
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class DepthRangeFilterIterator extends FilterIterator
+class DepthRangeFilterIterator extends \FilterIterator
{
private $minDepth = 0;
/**
- * Constructor.
- *
* @param \RecursiveIteratorIterator $iterator The Iterator to filter
* @param int $minDepth The min depth
* @param int $maxDepth The max depth
*/
- public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
+ public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = PHP_INT_MAX)
{
$this->minDepth = $minDepth;
$iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
+class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator
{
private $iterator;
private $isRecursive;
private $excludedPattern;
/**
- * Constructor.
- *
* @param \Iterator $iterator The Iterator to filter
* @param array $directories An array of directories to exclude
*/
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class FileTypeFilterIterator extends FilterIterator
+class FileTypeFilterIterator extends \FilterIterator
{
const ONLY_FILES = 1;
const ONLY_DIRECTORIES = 2;
private $mode;
/**
- * Constructor.
- *
* @param \Iterator $iterator The Iterator to filter
* @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
*/
- public function __construct(\Iterator $iterator, $mode)
+ public function __construct(\Iterator $iterator, int $mode)
{
$this->mode = $mode;
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Iterator;
-
-/**
- * This iterator just overrides the rewind method in order to correct a PHP bug,
- * which existed before version 5.5.23/5.6.7.
- *
- * @see https://bugs.php.net/68557
- *
- * @author Alex Bogomazov
- */
-abstract class FilterIterator extends \FilterIterator
-{
- /**
- * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
- * rewind in some cases.
- *
- * @see FilterIterator::rewind()
- */
- public function rewind()
- {
- if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
- parent::rewind();
-
- return;
- }
-
- $iterator = $this;
- while ($iterator instanceof \OuterIterator) {
- $innerIterator = $iterator->getInnerIterator();
-
- if ($innerIterator instanceof RecursiveDirectoryIterator) {
- // this condition is necessary for iterators to work properly with non-local filesystems like ftp
- if ($innerIterator->isRewindable()) {
- $innerIterator->next();
- $innerIterator->rewind();
- }
- } elseif ($innerIterator instanceof \FilesystemIterator) {
- $innerIterator->next();
- $innerIterator->rewind();
- }
-
- $iterator = $innerIterator;
- }
-
- parent::rewind();
- }
-}
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-abstract class MultiplePcreFilterIterator extends FilterIterator
+abstract class MultiplePcreFilterIterator extends \FilterIterator
{
protected $matchRegexps = array();
protected $noMatchRegexps = array();
/**
- * Constructor.
- *
* @param \Iterator $iterator The Iterator to filter
* @param array $matchPatterns An array of patterns that need to match
* @param array $noMatchPatterns An array of patterns that need to not match
private $directorySeparator = '/';
/**
- * Constructor.
- *
- * @param string $path
- * @param int $flags
- * @param bool $ignoreUnreadableDirs
- *
* @throws \RuntimeException
*/
- public function __construct($path, $flags, $ignoreUnreadableDirs = false)
+ public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false)
{
if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
throw new \RuntimeException('This iterator only support returning current as fileinfo.');
return;
}
- // @see https://bugs.php.net/68557
- if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
- parent::next();
- }
-
parent::rewind();
}
return $this->rewindable;
}
- // workaround for an HHVM bug, should be removed when https://github.com/facebook/hhvm/issues/7281 is fixed
- if ('' === $this->getPath()) {
- return $this->rewindable = false;
- }
-
if (false !== $stream = @opendir($this->getPath())) {
$infos = stream_get_meta_data($stream);
closedir($stream);
*
* @author Fabien Potencier <fabien@symfony.com>
*/
-class SizeRangeFilterIterator extends FilterIterator
+class SizeRangeFilterIterator extends \FilterIterator
{
private $comparators = array();
/**
- * Constructor.
- *
* @param \Iterator $iterator The Iterator to filter
* @param NumberComparator[] $comparators An array of NumberComparator instances
*/
private $sort;
/**
- * Constructor.
- *
* @param \Traversable $iterator The Iterator to filter
* @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
*
-Copyright (c) 2004-2017 Fabien Potencier
+Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
private $relativePathname;
/**
- * Constructor.
- *
* @param string $file The file name
* @param string $relativePath The relative path
* @param string $relativePathname The relative path name
*/
- public function __construct($file, $relativePath, $relativePathname)
+ public function __construct(string $file, string $relativePath, string $relativePathname)
{
parent::__construct($file);
$this->relativePath = $relativePath;
$this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
}
+ public function testRemoveTrailingSlash()
+ {
+ $finder = $this->buildFinder();
+
+ $expected = $this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar'));
+ $in = self::$tmpDir.'//';
+
+ $this->assertIterator($expected, $finder->in($in)->files()->getIterator());
+ }
+
+ public function testSymlinksNotResolved()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('symlinks are not supported on Windows');
+ }
+
+ $finder = $this->buildFinder();
+
+ symlink($this->toAbsolute('foo'), $this->toAbsolute('baz'));
+ $expected = $this->toAbsolute(array('baz/bar.tmp'));
+ $in = self::$tmpDir.'/baz/';
+ try {
+ $this->assertIterator($expected, $finder->in($in)->files()->getIterator());
+ unlink($this->toAbsolute('baz'));
+ } catch (\Exception $e) {
+ unlink($this->toAbsolute('baz'));
+ throw $e;
+ }
+ }
+
+ public function testBackPathNotNormalized()
+ {
+ $finder = $this->buildFinder();
+
+ $expected = $this->toAbsolute(array('foo/../foo/bar.tmp'));
+ $in = self::$tmpDir.'/foo/../foo/';
+ $this->assertIterator($expected, $finder->in($in)->files()->getIterator());
+ }
+
public function testDepth()
{
$finder = $this->buildFinder();
public function testInWithGlob()
{
$finder = $this->buildFinder();
- $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator();
+ $finder->in(array(__DIR__.'/Fixtures/*/B/C/', __DIR__.'/Fixtures/*/*/B/C/'))->getIterator();
$this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
}
count($finder);
}
+ public function testHasResults()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__);
+ $this->assertTrue($finder->hasResults());
+ }
+
+ public function testNoResults()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__)->name('DoesNotExist');
+ $this->assertFalse($finder->hasResults());
+ }
+
/**
* @dataProvider getContainsTestData
*/
+++ /dev/null
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Tests\Iterator;
-
-/**
- * @author Alex Bogomazov
- */
-class FilterIteratorTest extends RealIteratorTestCase
-{
- public function testFilterFilesystemIterators()
- {
- $i = new \FilesystemIterator($this->toAbsolute());
-
- // it is expected that there are test.py test.php in the tmpDir
- $i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i));
- $i->expects($this->any())
- ->method('accept')
- ->will($this->returnCallback(function () use ($i) {
- return (bool) preg_match('/\.php/', (string) $i->current());
- })
- );
-
- $c = 0;
- foreach ($i as $item) {
- ++$c;
- }
-
- $this->assertEquals(1, $c);
-
- $i->rewind();
-
- $c = 0;
- foreach ($i as $item) {
- ++$c;
- }
-
- // This would fail in php older than 5.5.23/5.6.7 with \FilterIterator
- // but works with Symfony\Component\Finder\Iterator\FilterIterator
- // see https://bugs.php.net/68557
- $this->assertEquals(1, $c);
- }
-}
class MockSplFileInfo extends \SplFileInfo
{
- const TYPE_DIRECTORY = 1;
- const TYPE_FILE = 2;
- const TYPE_UNKNOWN = 3;
+ const TYPE_DIRECTORY = 1;
+ const TYPE_FILE = 2;
+ const TYPE_UNKNOWN = 3;
private $contents = null;
private $mode = null;
$iterator = new SortableIterator($inner, $mode);
- if ($mode === SortableIterator::SORT_BY_ACCESSED_TIME
- || $mode === SortableIterator::SORT_BY_CHANGED_TIME
- || $mode === SortableIterator::SORT_BY_MODIFIED_TIME
+ if (SortableIterator::SORT_BY_ACCESSED_TIME === $mode
+ || SortableIterator::SORT_BY_CHANGED_TIME === $mode
+ || SortableIterator::SORT_BY_MODIFIED_TIME === $mode
) {
if ('\\' === DIRECTORY_SEPARATOR && SortableIterator::SORT_BY_MODIFIED_TIME !== $mode) {
$this->markTestSkipped('Sorting by atime or ctime is not supported on Windows');
}
],
"require": {
- "php": ">=5.5.9"
+ "php": "^7.1.3"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Finder\\": "" },
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
}
}
-Copyright (c) 2014-2016 Fabien Potencier
+Copyright (c) 2015-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
* - mb_convert_variables - Convert character code in variable(s)
* - mb_decode_mimeheader - Decode string in MIME header field
* - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
+ * - mb_decode_numericentity - Decode HTML numeric string reference to character
+ * - mb_encode_numericentity - Encode character to HTML numeric string reference
* - mb_convert_case - Perform case folding on a string
+ * - mb_detect_encoding - Detect character encoding
* - mb_get_info - Get internal settings of mbstring
* - mb_http_input - Detect HTTP input character encoding
* - mb_http_output - Set/Get HTTP output character encoding
*
* Not implemented:
* - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
- * - mb_decode_numericentity - Decode HTML numeric string reference to character
- * - mb_encode_numericentity - Encode character to HTML numeric string reference
* - mb_ereg_* - Regular expression with multibyte support
* - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
* - mb_preferred_mime_name - Get MIME charset string
public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
{
- if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
+ if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
$fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
} else {
$fromEncoding = self::getEncoding($fromEncoding);
trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
}
+ public static function mb_decode_numericentity($s, $convmap, $encoding = null)
+ {
+ if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
+ trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING);
+ return null;
+ }
+
+ if (!\is_array($convmap) || !$convmap) {
+ return false;
+ }
+
+ if (null !== $encoding && !\is_scalar($encoding)) {
+ trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING);
+ return ''; // Instead of null (cf. mb_encode_numericentity).
+ }
+
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ $cnt = floor(\count($convmap) / 4) * 4;
+
+ for ($i = 0; $i < $cnt; $i += 4) {
+ // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
+ $convmap[$i] += $convmap[$i + 2];
+ $convmap[$i + 1] += $convmap[$i + 2];
+ }
+
+ $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
+ $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
+ for ($i = 0; $i < $cnt; $i += 4) {
+ if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
+ return Mbstring::mb_chr($c - $convmap[$i + 2]);
+ }
+ }
+ return $m[0];
+ }, $s);
+
+ if (null === $encoding) {
+ return $s;
+ }
+
+ return iconv('UTF-8', $encoding.'//IGNORE', $s);
+ }
+
+ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
+ {
+ if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
+ trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING);
+ return null;
+ }
+
+ if (!\is_array($convmap) || !$convmap) {
+ return false;
+ }
+
+ if (null !== $encoding && !\is_scalar($encoding)) {
+ trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING);
+ return null; // Instead of '' (cf. mb_decode_numericentity).
+ }
+
+ if (null !== $is_hex && !\is_scalar($is_hex)) {
+ trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.gettype($s).' given', E_USER_WARNING);
+ return null;
+ }
+
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
+
+ $cnt = floor(\count($convmap) / 4) * 4;
+ $i = 0;
+ $len = \strlen($s);
+ $result = '';
+
+ while ($i < $len) {
+ $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
+ $uchr = substr($s, $i, $ulen);
+ $i += $ulen;
+ $c = self::mb_ord($uchr);
+
+ for ($j = 0; $j < $cnt; $j += 4) {
+ if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
+ $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
+ $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
+ continue 2;
+ }
+ }
+ $result .= $uchr;
+ }
+
+ if (null === $encoding) {
+ return $result;
+ }
+
+ return iconv('UTF-8', $encoding.'//IGNORE', $result);
+ }
+
public static function mb_convert_case($s, $mode, $encoding = null)
{
- if ('' === $s .= '') {
+ $s = (string) $s;
+ if ('' === $s) {
return '';
}
static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
$i = 0;
- $len = strlen($s);
+ $len = \strlen($s);
while ($i < $len) {
$ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
if (isset($map[$uchr])) {
$uchr = $map[$uchr];
- $nlen = strlen($uchr);
+ $nlen = \strlen($uchr);
if ($nlen == $ulen) {
$nlen = $i;
if (null === $encodingList) {
$encodingList = self::$encodingList;
} else {
- if (!is_array($encodingList)) {
+ if (!\is_array($encodingList)) {
$encodingList = array_map('trim', explode(',', $encodingList));
}
$encodingList = array_map('strtoupper', $encodingList);
return self::$encodingList;
}
- if (!is_array($encodingList)) {
+ if (!\is_array($encodingList)) {
$encodingList = array_map('trim', explode(',', $encodingList));
}
$encodingList = array_map('strtoupper', $encodingList);
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
- return strlen($s);
+ return \strlen($s);
}
return @iconv_strlen($s, $encoding);
return strpos($haystack, $needle, $offset);
}
- if ('' === $needle .= '') {
+ $needle = (string) $needle;
+ if ('' === $needle) {
trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
return false;
}
}
- return iconv_substr($s, $start, $length, $encoding).'';
+ return (string) iconv_substr($s, $start, $length, $encoding);
}
public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
public static function mb_chr($code, $encoding = null)
{
if (0x80 > $code %= 0x200000) {
- $s = chr($code);
+ $s = \chr($code);
} elseif (0x800 > $code) {
- $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
+ $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
} elseif (0x10000 > $code) {
- $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
+ $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
} else {
- $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
+ $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
}
if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
return self::mb_substr($haystack, $pos, null, $encoding);
}
- private static function html_encoding_callback($m)
+ private static function html_encoding_callback(array $m)
{
$i = 1;
$entities = '';
while (isset($m[$i])) {
if (0x80 > $m[$i]) {
- $entities .= chr($m[$i++]);
+ $entities .= \chr($m[$i++]);
continue;
}
if (0xF0 <= $m[$i]) {
return $entities;
}
- private static function title_case_lower($s)
+ private static function title_case_lower(array $s)
{
return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
}
- private static function title_case_upper($s)
+ private static function title_case_upper(array $s)
{
return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
}
function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
+ function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
+ function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "1.5-dev"
+ "dev-master": "1.8-dev"
}
}
}
CHANGELOG
=========
+3.4.0
+-----
+
+ * deprecated the ProcessBuilder class
+ * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor)
+
3.3.0
-----
public function isGeneralTimeout()
{
- return $this->timeoutType === self::TYPE_GENERAL;
+ return self::TYPE_GENERAL === $this->timeoutType;
}
public function isIdleTimeout()
{
- return $this->timeoutType === self::TYPE_IDLE;
+ return self::TYPE_IDLE === $this->timeoutType;
}
public function getExceededTimeout()
/**
* Replaces default suffixes of executable.
- *
- * @param array $suffixes
*/
public function setSuffixes(array $suffixes)
{
*/
class InputStream implements \IteratorAggregate
{
+ /** @var null|callable */
private $onEmpty = null;
private $input = array();
private $open = true;
/**
* Appends an input to the write buffer.
*
- * @param resource|scalar|\Traversable|null The input to append as stream resource, scalar or \Traversable
+ * @param resource|string|int|float|bool|\Traversable|null The input to append as scalar,
+ * stream resource or \Traversable
*/
public function write($input)
{
-Copyright (c) 2004-2017 Fabien Potencier
+Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
}
// PHP_BINARY return the current sapi executable
- if (PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) {
+ if (PHP_BINARY && \in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) {
return PHP_BINARY.$args;
}
}
}
+ if (is_executable($php = PHP_BINDIR.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
+ return $php;
+ }
+
$dirs = array(PHP_BINDIR);
if ('\\' === DIRECTORY_SEPARATOR) {
$dirs[] = 'C:\xampp\php\\';
class PhpProcess extends Process
{
/**
- * Constructor.
- *
* @param string $script The PHP script to run (as a string)
* @param string|null $cwd The working directory or null to use the working dir of the current PHP process
* @param array|null $env The environment variables or null to use the same environment as the current PHP process
$script = null;
}
if (null !== $options) {
- @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
}
parent::__construct($php, $cwd, $env, $script, $timeout, $options);
*/
abstract class AbstractPipes implements PipesInterface
{
- /** @var array */
public $pipes = array();
- /** @var string */
private $inputBuffer = '';
- /** @var resource|scalar|\Iterator|null */
private $input;
- /** @var bool */
private $blocked = true;
+ /**
+ * @param resource|string|int|float|bool|\Iterator|null $input
+ */
public function __construct($input)
{
if (is_resource($input) || $input instanceof \Iterator) {
$w = array($this->pipes[0]);
// let's have a look if something changed in streams
- if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
+ if (false === @stream_select($r, $w, $e, 0, 0)) {
return;
}
*/
class UnixPipes extends AbstractPipes
{
- /** @var bool */
private $ttyMode;
- /** @var bool */
private $ptyMode;
- /** @var bool */
private $haveReadSupport;
public function __construct($ttyMode, $ptyMode, $input, $haveReadSupport)
unset($r[0]);
// let's have a look if something changed in streams
- if (($r || $w) && false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
+ if (($r || $w) && false === @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
// if a system call has been interrupted, forget about it, let's try again
// otherwise, an error occurred, let's reset pipes
if (!$this->hasSystemCallBeenInterrupted()) {
*/
class WindowsPipes extends AbstractPipes
{
- /** @var array */
private $files = array();
- /** @var array */
private $fileHandles = array();
- /** @var array */
private $readBytes = array(
Process::STDOUT => 0,
Process::STDERR => 0,
);
- /** @var bool */
private $haveReadSupport;
public function __construct($input, $haveReadSupport)
* Exit codes translation table.
*
* User-defined errors must use exit codes in the 64-113 range.
- *
- * @var array
*/
public static $exitCodes = array(
0 => 'OK',
);
/**
- * Constructor.
- *
* @param string|array $commandline The command line to run
* @param string|null $cwd The working directory or null to use the working dir of the current PHP process
* @param array|null $env The environment variables or null to use the same environment as the current PHP process
$this->pty = false;
$this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
if (null !== $options) {
- @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
$this->options = array_replace($this->options, $options);
}
}
if (__CLASS__ !== static::class) {
$r = new \ReflectionMethod($this, __FUNCTION__);
if (__CLASS__ !== $r->getDeclaringClass()->getName() && (2 > $r->getNumberOfParameters() || 'env' !== $r->getParameters()[0]->name)) {
- @trigger_error(sprintf('The %s::start() method expects a second "$env" argument since version 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s::start() method expects a second "$env" argument since Symfony 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED);
}
}
$env = null;
$inheritEnv = true;
}
- $envBackup = array();
if (null !== $env && $inheritEnv) {
- foreach ($env as $k => $v) {
- $envBackup[$k] = getenv($k);
- putenv(false === $v || null === $v ? $k : "$k=$v");
- }
- $env = null;
+ $env += $this->getDefaultEnv();
} elseif (null !== $env) {
@trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED);
+ } else {
+ $env = $this->getDefaultEnv();
}
if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
$this->options['bypass_shell'] = true;
- $commandline = $this->prepareWindowsCommandLine($commandline, $envBackup, $env);
+ $commandline = $this->prepareWindowsCommandLine($commandline, $env);
} elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
$descriptors[3] = array('pipe', 'w');
// @see : https://bugs.php.net/69442
$ptsWorkaround = fopen(__FILE__, 'r');
}
+ if (defined('HHVM_VERSION')) {
+ $envPairs = $env;
+ } else {
+ $envPairs = array();
+ foreach ($env as $k => $v) {
+ if (false !== $v) {
+ $envPairs[] = $k.'='.$v;
+ }
+ }
+ }
- $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $this->options);
-
- foreach ($envBackup as $k => $v) {
- putenv(false === $v ? $k : "$k=$v");
+ if (!is_dir($this->cwd)) {
+ @trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
}
+ $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
+
if (!is_resource($this->process)) {
throw new RuntimeException('Unable to launch a new process.');
}
*/
public function isStarted()
{
- return $this->status != self::STATUS_READY;
+ return self::STATUS_READY != $this->status;
}
/**
{
$this->updateStatus(false);
- return $this->status == self::STATUS_TERMINATED;
+ return self::STATUS_TERMINATED == $this->status;
}
/**
/**
* Sets the environment variables.
*
- * An environment variable value should be a string.
+ * Each environment variable value should be a string.
* If it is an array, the variable is ignored.
* If it is false or null, it will be removed when
* env vars are otherwise inherited.
*
* This content will be passed to the underlying process standard input.
*
- * @param resource|scalar|\Traversable|null $input The content
+ * @param string|int|float|bool|resource|\Traversable|null $input The content
*
* @return self The current Process instance
*
*/
public function getOptions()
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
return $this->options;
}
*/
public function setOptions(array $options)
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
$this->options = $options;
*/
public function getEnhanceWindowsCompatibility()
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
return $this->enhanceWindowsCompatibility;
}
*/
public function setEnhanceWindowsCompatibility($enhance)
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
$this->enhanceWindowsCompatibility = (bool) $enhance;
*/
public function getEnhanceSigchildCompatibility()
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
return $this->enhanceSigchildCompatibility;
}
*/
public function setEnhanceSigchildCompatibility($enhance)
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
$this->enhanceSigchildCompatibility = (bool) $enhance;
*/
public function areEnvironmentVariablesInherited()
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Environment variables will always be inherited.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Environment variables will always be inherited.', __METHOD__), E_USER_DEPRECATED);
return $this->inheritEnv;
}
*/
public function checkTimeout()
{
- if ($this->status !== self::STATUS_STARTED) {
+ if (self::STATUS_STARTED !== $this->status) {
return;
}
$callback = $this->callback;
foreach ($result as $type => $data) {
if (3 !== $type) {
- $callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
+ $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
} elseif (!isset($this->fallbackStatus['signaled'])) {
$this->fallbackStatus['exitcode'] = (int) $data;
}
return true;
}
- private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env = null)
+ private function prepareWindowsCommandLine($cmd, array &$env)
{
$uid = uniqid('', true);
$varCount = 0;
[^"%!^]*+
)++
) | [^"]*+ )"/x',
- function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) {
+ function ($m) use (&$env, &$varCache, &$varCount, $uid) {
if (!isset($m[1])) {
return $m[0];
}
$value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"';
$var = $uid.++$varCount;
- if (null === $env) {
- putenv("$var=$value");
- } else {
- $env[$var] = $value;
- }
-
- $envBackup[$var] = false;
+ $env[$var] = $value;
return $varCache[$m[0]] = '!'.$var.'!';
},
*
* @param string $functionName The function name that was called
*
- * @throws LogicException If the process has not run.
+ * @throws LogicException if the process has not run
*/
private function requireProcessIsStarted($functionName)
{
*
* @param string $functionName The function name that was called
*
- * @throws LogicException If the process is not yet terminated.
+ * @throws LogicException if the process is not yet terminated
*/
private function requireProcessIsTerminated($functionName)
{
return '"'.str_replace(array('"', '^', '%', '!', "\n"), array('""', '"^^"', '"^%"', '"^!"', '!LF!'), $argument).'"';
}
+
+ private function getDefaultEnv()
+ {
+ $env = array();
+
+ foreach ($_SERVER as $k => $v) {
+ if (is_string($v) && false !== $v = getenv($k)) {
+ $env[$k] = $v;
+ }
+ }
+
+ foreach ($_ENV as $k => $v) {
+ if (is_string($v)) {
+ $env[$k] = $v;
+ }
+ }
+
+ return $env;
+ }
}
namespace Symfony\Component\Process;
+@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the Process class instead.', ProcessBuilder::class), E_USER_DEPRECATED);
+
use Symfony\Component\Process\Exception\InvalidArgumentException;
use Symfony\Component\Process\Exception\LogicException;
/**
- * Process builder.
- *
* @author Kris Wallsmith <kris@symfony.com>
+ *
+ * @deprecated since version 3.4, to be removed in 4.0. Use the Process class instead.
*/
class ProcessBuilder
{
private $outputDisabled = false;
/**
- * Constructor.
- *
* @param string[] $arguments An array of arguments
*/
public function __construct(array $arguments = array())
* @param bool $inheritEnv
*
* @return $this
- *
- * @deprecated since version 3.3, to be removed in 4.0.
*/
public function inheritEnvironmentVariables($inheritEnv = true)
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
-
$this->inheritEnv = $inheritEnv;
return $this;
/**
* Sets the input of the process.
*
- * @param resource|scalar|\Traversable|null $input The input content
+ * @param resource|string|int|float|bool|\Traversable|null $input The input content
*
* @return $this
*
* @param string $value The option value
*
* @return $this
- *
- * @deprecated since version 3.3, to be removed in 4.0.
*/
public function setOption($name, $value)
{
- @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
-
$this->options[$name] = $value;
return $this;
*/
public static function escapeArgument($argument)
{
- @trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 and will be removed in 4.0. Use a command line array or give env vars to the Process::start/run() method instead.', E_USER_DEPRECATED);
+ @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use a command line array or give env vars to the Process::start/run() method instead.', E_USER_DEPRECATED);
//Fix for PHP bug #43784 escapeshellarg removes % from given string
//Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
$process->wait();
$this->assertContains($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after wait');
- $this->assertSame(phpversion().PHP_SAPI, $process->getOutput());
+ $this->assertSame(PHP_VERSION.PHP_SAPI, $process->getOutput());
}
}
use PHPUnit\Framework\TestCase;
use Symfony\Component\Process\ProcessBuilder;
+/**
+ * @group legacy
+ */
class ProcessBuilderTest extends TestCase
{
- /**
- * @group legacy
- */
public function testInheritEnvironmentVars()
{
$proc = ProcessBuilder::create()
->method('isSuccessful')
->will($this->returnValue(true));
- $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(
- '\InvalidArgumentException',
- 'Expected a failed process, but the given process was successful.'
- );
+ if (method_exists($this, 'expectException')) {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Expected a failed process, but the given process was successful.');
+ } else {
+ $this->setExpectedException(\InvalidArgumentException::class, 'Expected a failed process, but the given process was successful.');
+ }
new ProcessFailedException($process);
}
}
}
+ /**
+ * @group legacy
+ * @expectedDeprecation The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since Symfony 3.4 and will be removed in 4.0.
+ */
+ public function testInvalidCwd()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('False-positive on Windows/appveyor.');
+ }
+
+ // Check that it works fine if the CWD exists
+ $cmd = new Process('echo test', __DIR__);
+ $cmd->run();
+
+ $cmd = new Process('echo test', __DIR__.'/notfound/');
+ $cmd->run();
+ }
+
public function testThatProcessDoesNotThrowWarningDuringRun()
{
if ('\\' === DIRECTORY_SEPARATOR) {
$called = false;
$p->run(function ($type, $buffer) use (&$called) {
- $called = $buffer === 'foo';
+ $called = 'foo' === $buffer;
});
$this->assertTrue($called, 'The callback should be executed with the output');
$called = false;
$p->run(function ($type, $buffer) use (&$called) {
- $called = $buffer === 'foo';
+ $called = 'foo' === $buffer;
});
$this->assertTrue($called, 'The callback should be executed with the output');
{
$process = $this->getProcess('echo foo');
$process->run();
- $this->assertTrue(strlen($process->getOutput()) > 0);
+ $this->assertGreaterThan(0, strlen($process->getOutput()));
}
public function testGetExitCodeIsNullOnStart()
{
$input = new InputStream();
- $process = $this->getProcessForCode('echo \'ping\'; stream_copy_to_stream(STDIN, STDOUT);');
+ $process = $this->getProcessForCode('echo \'ping\'; echo fread(STDIN, 4); echo fread(STDIN, 4);');
$process->setInput($input);
$process->start(function ($type, $data) use ($input) {
public function testEnvBackupDoesNotDeleteExistingVars()
{
putenv('existing_var=foo');
+ $_ENV['existing_var'] = 'foo';
$process = $this->getProcess('php -r "echo getenv(\'new_test_var\');"');
$process->setEnv(array('existing_var' => 'bar', 'new_test_var' => 'foo'));
$process->inheritEnvironmentVariables();
$this->assertSame('foo', $process->getOutput());
$this->assertSame('foo', getenv('existing_var'));
$this->assertFalse(getenv('new_test_var'));
+
+ putenv('existing_var');
+ unset($_ENV['existing_var']);
}
public function testEnvIsInherited()
{
- $process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ'));
+ $process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ', 'EMPTY' => ''));
putenv('FOO=BAR');
+ $_ENV['FOO'] = 'BAR';
$process->run();
- $expected = array('BAR' => 'BAZ', 'FOO' => 'BAR');
+ $expected = array('BAR' => 'BAZ', 'EMPTY' => '', 'FOO' => 'BAR');
$env = array_intersect_key(unserialize($process->getOutput()), $expected);
$this->assertEquals($expected, $env);
+
+ putenv('FOO');
+ unset($_ENV['FOO']);
}
/**
$process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ'));
putenv('FOO=BAR');
+ $_ENV['FOO'] = 'BAR';
$this->assertSame($process, $process->inheritEnvironmentVariables(false));
$this->assertFalse($process->areEnvironmentVariablesInherited());
unset($expected['FOO']);
$this->assertSame($expected, $env);
+
+ putenv('FOO');
+ unset($_ENV['FOO']);
}
public function testGetCommandLine()
)
EOTXT;
- $this->assertSame($expected, $p->getOutput());
+ $this->assertSame($expected, str_replace('Standard input code', '-', $p->getOutput()));
}
public function provideEscapeArgument()
}
],
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Process\\": "" },
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "3.4-dev"
}
}
}
CHANGELOG
=========
+4.0.0
+-----
+
+ * removed the backup feature of the `FileDumper` class
+ * removed `TranslationWriter::writeTranslations()` method
+ * removed support for passing `MessageSelector` instances to the constructor of the `Translator` class
+
+3.4.0
+-----
+
+ * Added `TranslationDumperPass`
+ * Added `TranslationExtractorPass`
+ * Added `TranslatorPass`
+ * Added `TranslationReader` and `TranslationReaderInterface`
+ * Added `<notes>` section to the Xliff 2.0 dumper.
+ * Improved Xliff 2.0 loader to load `<notes>` section.
+ * Added `TranslationWriterInterface`
+ * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write`
+ * added support for adding custom message formatter and decoupling the default one.
+ * Added `PhpExtractor`
+ * Added `PhpStringTokenParser`
+
3.2.0
-----
*/
abstract class AbstractOperation implements OperationInterface
{
- /**
- * @var MessageCatalogueInterface The source catalogue
- */
protected $source;
-
- /**
- * @var MessageCatalogueInterface The target catalogue
- */
protected $target;
-
- /**
- * @var MessageCatalogue The result catalogue
- */
protected $result;
/**
protected $messages;
/**
- * @param MessageCatalogueInterface $source The source catalogue
- * @param MessageCatalogueInterface $target The target catalogue
- *
* @throws LogicException
*/
public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
*/
class XliffLintCommand extends Command
{
+ protected static $defaultName = 'lint:xliff';
+
private $format;
private $displayCorrectFiles;
private $directoryIteratorProvider;
private $isReadableProvider;
- public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null)
+ public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null)
{
parent::__construct($name);
protected function configure()
{
$this
- ->setName('lint:xliff')
->setDescription('Lints a XLIFF file and outputs encountered errors')
->addArgument('filename', null, 'A file or a directory or STDIN')
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
*/
class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface
{
- /**
- * @var DataCollectorTranslator
- */
private $translator;
- /**
- * @param DataCollectorTranslator $translator
- */
public function __construct(DataCollectorTranslator $translator)
{
$this->translator = $translator;
$this->data = $this->computeCount($messages);
$this->data['messages'] = $messages;
+ $this->data['locale'] = $this->translator->getLocale();
+ $this->data['fallback_locales'] = $this->translator->getFallbackLocales();
+
$this->data = $this->cloneVar($this->data);
}
{
}
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ $this->data = array();
+ }
+
/**
* @return array
*/
return isset($this->data[DataCollectorTranslator::MESSAGE_DEFINED]) ? $this->data[DataCollectorTranslator::MESSAGE_DEFINED] : 0;
}
+ public function getLocale()
+ {
+ return !empty($this->data['locale']) ? $this->data['locale'] : null;
+ }
+
+ public function getFallbackLocales()
+ {
+ return (isset($this->data['fallback_locales']) && count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : array();
+ }
+
/**
* {@inheritdoc}
*/
*/
private $translator;
- /**
- * @var array
- */
private $messages = array();
/**
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+/**
+ * Adds tagged translation.formatter services to translation writer.
+ */
+class TranslationDumperPass implements CompilerPassInterface
+{
+ private $writerServiceId;
+ private $dumperTag;
+
+ public function __construct(string $writerServiceId = 'translation.writer', string $dumperTag = 'translation.dumper')
+ {
+ $this->writerServiceId = $writerServiceId;
+ $this->dumperTag = $dumperTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->writerServiceId)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($this->writerServiceId);
+
+ foreach ($container->findTaggedServiceIds($this->dumperTag, true) as $id => $attributes) {
+ $definition->addMethodCall('addDumper', array($attributes[0]['alias'], new Reference($id)));
+ }
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * Adds tagged translation.extractor services to translation extractor.
+ */
+class TranslationExtractorPass implements CompilerPassInterface
+{
+ private $extractorServiceId;
+ private $extractorTag;
+
+ public function __construct(string $extractorServiceId = 'translation.extractor', string $extractorTag = 'translation.extractor')
+ {
+ $this->extractorServiceId = $extractorServiceId;
+ $this->extractorTag = $extractorTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->extractorServiceId)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($this->extractorServiceId);
+
+ foreach ($container->findTaggedServiceIds($this->extractorTag, true) as $id => $attributes) {
+ if (!isset($attributes[0]['alias'])) {
+ throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
+ }
+
+ $definition->addMethodCall('addExtractor', array($attributes[0]['alias'], new Reference($id)));
+ }
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
+
+class TranslatorPass implements CompilerPassInterface
+{
+ private $translatorServiceId;
+ private $readerServiceId;
+ private $loaderTag;
+ private $debugCommandServiceId;
+ private $updateCommandServiceId;
+
+ public function __construct(string $translatorServiceId = 'translator.default', string $readerServiceId = 'translation.reader', string $loaderTag = 'translation.loader', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update')
+ {
+ $this->translatorServiceId = $translatorServiceId;
+ $this->readerServiceId = $readerServiceId;
+ $this->loaderTag = $loaderTag;
+ $this->debugCommandServiceId = $debugCommandServiceId;
+ $this->updateCommandServiceId = $updateCommandServiceId;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->translatorServiceId)) {
+ return;
+ }
+
+ $loaders = array();
+ $loaderRefs = array();
+ foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) {
+ $loaderRefs[$id] = new Reference($id);
+ $loaders[$id][] = $attributes[0]['alias'];
+ if (isset($attributes[0]['legacy-alias'])) {
+ $loaders[$id][] = $attributes[0]['legacy-alias'];
+ }
+ }
+
+ if ($container->hasDefinition($this->readerServiceId)) {
+ $definition = $container->getDefinition($this->readerServiceId);
+ foreach ($loaders as $id => $formats) {
+ foreach ($formats as $format) {
+ $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id]));
+ }
+ }
+ }
+
+ $container
+ ->findDefinition($this->translatorServiceId)
+ ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
+ ->replaceArgument(3, $loaders)
+ ;
+
+ if (!$container->hasParameter('twig.default_path')) {
+ return;
+ }
+
+ if ($container->hasDefinition($this->debugCommandServiceId)) {
+ $container->getDefinition($this->debugCommandServiceId)->replaceArgument(4, $container->getParameter('twig.default_path'));
+ }
+
+ if ($container->hasDefinition($this->updateCommandServiceId)) {
+ $container->getDefinition($this->updateCommandServiceId)->replaceArgument(5, $container->getParameter('twig.default_path'));
+ }
+ }
+}
/**
* Sets the delimiter and escape character for CSV.
*
- * @param string $delimiter delimiter character
- * @param string $enclosure enclosure character
+ * @param string $delimiter Delimiter character
+ * @param string $enclosure Enclosure character
*/
public function setCsvControl($delimiter = ';', $enclosure = '"')
{
/**
* FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
- * Performs backup of already existing files.
*
* Options:
* - path (mandatory): the directory where the files should be saved
*/
protected $relativePathTemplate = '%domain%.%locale%.%extension%';
- /**
- * Make file backup before the dump.
- *
- * @var bool
- */
- private $backup = true;
-
/**
* Sets the template for the relative paths to files.
*
*/
public function setBackup($backup)
{
- $this->backup = $backup;
+ if (false !== $backup) {
+ throw new \LogicException('The backup feature is no longer supported.');
+ }
+
+ // the method is only present to not break BC
+ // to be deprecated in 4.1
}
/**
// save a file for each domain
foreach ($messages->getDomains() as $domain) {
- // backup
$fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
- if (file_exists($fullpath)) {
- if ($this->backup) {
- @trigger_error('Creating a backup while dumping a message catalogue is deprecated since version 3.1 and will be removed in 4.0. Use TranslationWriter::disableBackup() to disable the backup.', E_USER_DEPRECATED);
- copy($fullpath, $fullpath.'~');
- }
- } else {
+ if (!file_exists($fullpath)) {
$directory = dirname($fullpath);
if (!file_exists($directory) && !@mkdir($directory, 0777, true)) {
throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory));
/**
* Gets the relative file path using the template.
- *
- * @param string $domain The domain
- * @param string $locale The locale
- *
- * @return string The relative file path
*/
- private function getRelativePath($domain, $locale)
+ private function getRelativePath(string $domain, string $locale): string
{
return strtr($this->relativePathTemplate, array(
'%domain%' => $domain,
if (isset($options['json_encoding'])) {
$flags = $options['json_encoding'];
} else {
- $flags = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
+ $flags = JSON_PRETTY_PRINT;
}
return json_encode($messages->all($domain), $flags);
foreach ($messages->all($domain) as $source => $target) {
$translation = $dom->createElement('trans-unit');
- $translation->setAttribute('id', md5($source));
+ $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
$translation->setAttribute('resname', $source);
$s = $translation->appendChild($dom->createElement('source'));
foreach ($messages->all($domain) as $source => $target) {
$translation = $dom->createElement('unit');
- $translation->setAttribute('id', md5($source));
+ $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
+ $metadata = $messages->getMetadata($source, $domain);
+
+ // Add notes section
+ if ($this->hasMetadataArrayInfo('notes', $metadata)) {
+ $notesElement = $dom->createElement('notes');
+ foreach ($metadata['notes'] as $note) {
+ $n = $dom->createElement('note');
+ $n->appendChild($dom->createTextNode(isset($note['content']) ? $note['content'] : ''));
+ unset($note['content']);
+
+ foreach ($note as $name => $value) {
+ $n->setAttribute($name, $value);
+ }
+ $notesElement->appendChild($n);
+ }
+ $translation->appendChild($notesElement);
+ }
$segment = $translation->appendChild($dom->createElement('segment'));
$text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
$targetElement = $dom->createElement('target');
- $metadata = $messages->getMetadata($source, $domain);
if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
foreach ($metadata['target-attributes'] as $name => $value) {
$targetElement->setAttribute($name, $value);
*/
class YamlFileDumper extends FileDumper
{
+ private $extension;
+
+ public function __construct(string $extension = 'yml')
+ {
+ $this->extension = $extension;
+ }
+
/**
* {@inheritdoc}
*/
*/
protected function getExtension()
{
- return 'yml';
+ return $this->extension;
}
}
abstract class AbstractFileExtractor
{
/**
- * @param string|array $resource files, a file or a directory
+ * @param string|array $resource Files, a file or a directory
*
* @return array
*/
return $files;
}
- /**
- * @param string $file
- *
- * @return \SplFileInfo
- */
- private function toSplFileInfo($file)
+ private function toSplFileInfo(string $file): \SplFileInfo
{
return ($file instanceof \SplFileInfo) ? $file : new \SplFileInfo($file);
}
abstract protected function canBeExtracted($file);
/**
- * @param string|array $resource files, a file or a directory
+ * @param string|array $resource Files, a file or a directory
*
* @return array files to be extracted
*/
/**
* Extracts translation messages from files, a file or a directory to the catalogue.
*
- * @param string|array $resource files, a file or a directory
+ * @param string|array $resource Files, a file or a directory
* @param MessageCatalogue $catalogue The catalogue
*/
public function extract($resource, MessageCatalogue $catalogue);
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PhpExtractor extracts translation messages from a PHP template.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface
+{
+ const MESSAGE_TOKEN = 300;
+ const METHOD_ARGUMENTS_TOKEN = 1000;
+ const DOMAIN_TOKEN = 1001;
+
+ /**
+ * Prefix for new found message.
+ *
+ * @var string
+ */
+ private $prefix = '';
+
+ /**
+ * The sequence that captures translation messages.
+ *
+ * @var array
+ */
+ protected $sequences = array(
+ array(
+ '->',
+ 'trans',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ),
+ array(
+ '->',
+ 'transChoice',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ),
+ array(
+ '->',
+ 'trans',
+ '(',
+ self::MESSAGE_TOKEN,
+ ),
+ array(
+ '->',
+ 'transChoice',
+ '(',
+ self::MESSAGE_TOKEN,
+ ),
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ public function extract($resource, MessageCatalogue $catalog)
+ {
+ $files = $this->extractFiles($resource);
+ foreach ($files as $file) {
+ $this->parseTokens(token_get_all(file_get_contents($file)), $catalog);
+
+ // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
+ gc_mem_caches();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPrefix($prefix)
+ {
+ $this->prefix = $prefix;
+ }
+
+ /**
+ * Normalizes a token.
+ *
+ * @param mixed $token
+ *
+ * @return string
+ */
+ protected function normalizeToken($token)
+ {
+ if (isset($token[1]) && 'b"' !== $token) {
+ return $token[1];
+ }
+
+ return $token;
+ }
+
+ /**
+ * Seeks to a non-whitespace token.
+ */
+ private function seekToNextRelevantToken(\Iterator $tokenIterator)
+ {
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+ if (T_WHITESPACE !== $t[0]) {
+ break;
+ }
+ }
+ }
+
+ private function skipMethodArgument(\Iterator $tokenIterator)
+ {
+ $openBraces = 0;
+
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+
+ if ('[' === $t[0] || '(' === $t[0]) {
+ ++$openBraces;
+ }
+
+ if (']' === $t[0] || ')' === $t[0]) {
+ --$openBraces;
+ }
+
+ if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Extracts the message from the iterator while the tokens
+ * match allowed message tokens.
+ */
+ private function getValue(\Iterator $tokenIterator)
+ {
+ $message = '';
+ $docToken = '';
+
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+ if (!isset($t[1])) {
+ break;
+ }
+
+ switch ($t[0]) {
+ case T_START_HEREDOC:
+ $docToken = $t[1];
+ break;
+ case T_ENCAPSED_AND_WHITESPACE:
+ case T_CONSTANT_ENCAPSED_STRING:
+ $message .= $t[1];
+ break;
+ case T_END_HEREDOC:
+ return PhpStringTokenParser::parseDocString($docToken, $message);
+ default:
+ break 2;
+ }
+ }
+
+ if ($message) {
+ $message = PhpStringTokenParser::parse($message);
+ }
+
+ return $message;
+ }
+
+ /**
+ * Extracts trans message from PHP tokens.
+ *
+ * @param array $tokens
+ * @param MessageCatalogue $catalog
+ */
+ protected function parseTokens($tokens, MessageCatalogue $catalog)
+ {
+ $tokenIterator = new \ArrayIterator($tokens);
+
+ for ($key = 0; $key < $tokenIterator->count(); ++$key) {
+ foreach ($this->sequences as $sequence) {
+ $message = '';
+ $domain = 'messages';
+ $tokenIterator->seek($key);
+
+ foreach ($sequence as $sequenceKey => $item) {
+ $this->seekToNextRelevantToken($tokenIterator);
+
+ if ($this->normalizeToken($tokenIterator->current()) === $item) {
+ $tokenIterator->next();
+ continue;
+ } elseif (self::MESSAGE_TOKEN === $item) {
+ $message = $this->getValue($tokenIterator);
+
+ if (count($sequence) === ($sequenceKey + 1)) {
+ break;
+ }
+ } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) {
+ $this->skipMethodArgument($tokenIterator);
+ } elseif (self::DOMAIN_TOKEN === $item) {
+ $domain = $this->getValue($tokenIterator);
+
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if ($message) {
+ $catalog->set($message, $this->prefix.$message, $domain);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * @param string $file
+ *
+ * @return bool
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected function canBeExtracted($file)
+ {
+ return $this->isFile($file) && 'php' === pathinfo($file, PATHINFO_EXTENSION);
+ }
+
+ /**
+ * @param string|array $directory
+ *
+ * @return array
+ */
+ protected function extractFromDirectory($directory)
+ {
+ $finder = new Finder();
+
+ return $finder->files()->name('*.php')->in($directory);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+/*
+ * The following is derived from code at http://github.com/nikic/PHP-Parser
+ *
+ * Copyright (c) 2011 by Nikita Popov
+ *
+ * Some rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * * The names of the contributors may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class PhpStringTokenParser
+{
+ protected static $replacements = array(
+ '\\' => '\\',
+ '$' => '$',
+ 'n' => "\n",
+ 'r' => "\r",
+ 't' => "\t",
+ 'f' => "\f",
+ 'v' => "\v",
+ 'e' => "\x1B",
+ );
+
+ /**
+ * Parses a string token.
+ *
+ * @param string $str String token content
+ *
+ * @return string The parsed string
+ */
+ public static function parse($str)
+ {
+ $bLength = 0;
+ if ('b' === $str[0]) {
+ $bLength = 1;
+ }
+
+ if ('\'' === $str[$bLength]) {
+ return str_replace(
+ array('\\\\', '\\\''),
+ array('\\', '\''),
+ substr($str, $bLength + 1, -1)
+ );
+ } else {
+ return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"');
+ }
+ }
+
+ /**
+ * Parses escape sequences in strings (all string types apart from single quoted).
+ *
+ * @param string $str String without quotes
+ * @param null|string $quote Quote type
+ *
+ * @return string String with escape sequences parsed
+ */
+ public static function parseEscapeSequences($str, $quote)
+ {
+ if (null !== $quote) {
+ $str = str_replace('\\'.$quote, $quote, $str);
+ }
+
+ return preg_replace_callback(
+ '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~',
+ array(__CLASS__, 'parseCallback'),
+ $str
+ );
+ }
+
+ private static function parseCallback($matches)
+ {
+ $str = $matches[1];
+
+ if (isset(self::$replacements[$str])) {
+ return self::$replacements[$str];
+ } elseif ('x' === $str[0] || 'X' === $str[0]) {
+ return chr(hexdec($str));
+ } else {
+ return chr(octdec($str));
+ }
+ }
+
+ /**
+ * Parses a constant doc string.
+ *
+ * @param string $startToken Doc string start token content (<<<SMTHG)
+ * @param string $str String token content
+ *
+ * @return string Parsed string
+ */
+ public static function parseDocString($startToken, $str)
+ {
+ // strip last newline (thanks tokenizer for sticking it into the string!)
+ $str = preg_replace('~(\r\n|\n|\r)$~', '', $str);
+
+ // nowdoc string
+ if (false !== strpos($startToken, '\'')) {
+ return $str;
+ }
+
+ return self::parseEscapeSequences($str, null);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+interface ChoiceMessageFormatterInterface
+{
+ /**
+ * Formats a localized message pattern with given arguments.
+ *
+ * @param string $message The message (may also be an object that can be cast to string)
+ * @param int $number The number to use to find the indice of the message
+ * @param string $locale The message locale
+ * @param array $parameters An array of parameters for the message
+ *
+ * @return string
+ */
+ public function choiceFormat($message, $number, $locale, array $parameters = array());
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+use Symfony\Component\Translation\MessageSelector;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class MessageFormatter implements MessageFormatterInterface, ChoiceMessageFormatterInterface
+{
+ private $selector;
+
+ /**
+ * @param MessageSelector|null $selector The message selector for pluralization
+ */
+ public function __construct(MessageSelector $selector = null)
+ {
+ $this->selector = $selector ?: new MessageSelector();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function format($message, $locale, array $parameters = array())
+ {
+ return strtr($message, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function choiceFormat($message, $number, $locale, array $parameters = array())
+ {
+ $parameters = array_merge(array('%count%' => $number), $parameters);
+
+ return $this->format($this->selector->choose($message, (int) $number, $locale), $locale, $parameters);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+interface MessageFormatterInterface
+{
+ /**
+ * Formats a localized message pattern with given arguments.
+ *
+ * @param string $message The message (may also be an object that can be cast to string)
+ * @param string $locale The message locale
+ * @param array $parameters An array of parameters for the message
+ *
+ * @return string
+ */
+ public function format($message, $locale, array $parameters = array());
+}
private $locale;
/**
- * Constructor.
- *
* @param MessageSelector|null $selector The message selector for pluralization
*/
public function __construct(MessageSelector $selector = null)
-Copyright (c) 2004-2017 Fabien Potencier
+Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
/**
* Sets the delimiter, enclosure, and escape character for CSV.
*
- * @param string $delimiter delimiter character
- * @param string $enclosure enclosure character
- * @param string $escape escape character
+ * @param string $delimiter Delimiter character
+ * @param string $enclosure Enclosure character
+ * @param string $escape Escape character
*/
public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\')
{
*
* @return array
*
- * @throws InvalidResourceException If stream content has an invalid format.
+ * @throws InvalidResourceException if stream content has an invalid format
*/
abstract protected function loadResource($resource);
}
try {
$rb = new \ResourceBundle($locale, $resource);
} catch (\Exception $e) {
- // HHVM compatibility: constructor throws on invalid resource
$rb = null;
}
try {
$rb = new \ResourceBundle($locale, $resource);
} catch (\Exception $e) {
- // HHVM compatibility: constructor throws on invalid resource
$rb = null;
}
*
* This function takes an array by reference and will modify it
*
- * @param \ResourceBundle $rb the ResourceBundle that will be flattened
- * @param array $messages used internally for recursive calls
- * @param string $path current path being parsed, used internally for recursive calls
+ * @param \ResourceBundle $rb The ResourceBundle that will be flattened
+ * @param array $messages Used internally for recursive calls
+ * @param string $path Current path being parsed, used internally for recursive calls
*
* @return array the flattened ResourceBundle
*/
/**
* Magic used for validating the format of a MO file as well as
* detecting if the machine used to create that file was little endian.
- *
- * @var float
*/
const MO_LITTLE_ENDIAN_MAGIC = 0x950412de;
/**
* Magic used for validating the format of a MO file as well as
* detecting if the machine used to create that file was big endian.
- *
- * @var float
*/
const MO_BIG_ENDIAN_MAGIC = 0xde120495;
/**
* The size of the header of a MO file in bytes.
- *
- * @var int Number of bytes
*/
const MO_HEADER_SIZE = 28;
$magic = unpack('V1', fread($stream, 4));
$magic = hexdec(substr(dechex(current($magic)), -8));
- if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) {
+ if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) {
$isBigEndian = false;
- } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) {
+ } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) {
$isBigEndian = true;
} else {
throw new InvalidResourceException('MO stream content has an invalid format.');
fseek($stream, $offset);
$singularId = fread($stream, $length);
- if (strpos($singularId, "\000") !== false) {
+ if (false !== strpos($singularId, "\000")) {
list($singularId, $pluralId) = explode("\000", $singularId);
}
fseek($stream, $offset);
$translated = fread($stream, $length);
- if (strpos($translated, "\000") !== false) {
+ if (false !== strpos($translated, "\000")) {
$translated = explode("\000", $translated);
}
* Reads an unsigned long from stream respecting endianness.
*
* @param resource $stream
- * @param bool $isBigEndian
- *
- * @return int
*/
- private function readLong($stream, $isBigEndian)
+ private function readLong($stream, bool $isBigEndian): int
{
$result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
$result = current($result);
while ($line = fgets($stream)) {
$line = trim($line);
- if ($line === '') {
+ if ('' === $line) {
// Whitespace indicated current item is done
if (!in_array('fuzzy', $flags)) {
$this->addMessage($messages, $item);
}
$item = $defaults;
$flags = array();
- } elseif (substr($line, 0, 2) === '#,') {
+ } elseif ('#,' === substr($line, 0, 2)) {
$flags = array_map('trim', explode(',', substr($line, 2)));
- } elseif (substr($line, 0, 7) === 'msgid "') {
+ } elseif ('msgid "' === substr($line, 0, 7)) {
// We start a new msg so save previous
// TODO: this fails when comments or contexts are added
$this->addMessage($messages, $item);
$item = $defaults;
$item['ids']['singular'] = substr($line, 7, -1);
- } elseif (substr($line, 0, 8) === 'msgstr "') {
+ } elseif ('msgstr "' === substr($line, 0, 8)) {
$item['translated'] = substr($line, 8, -1);
- } elseif ($line[0] === '"') {
+ } elseif ('"' === $line[0]) {
$continues = isset($item['translated']) ? 'translated' : 'ids';
if (is_array($item[$continues])) {
} else {
$item[$continues] .= substr($line, 1, -1);
}
- } elseif (substr($line, 0, 14) === 'msgid_plural "') {
+ } elseif ('msgid_plural "' === substr($line, 0, 14)) {
$item['ids']['plural'] = substr($line, 14, -1);
- } elseif (substr($line, 0, 7) === 'msgstr[') {
+ } elseif ('msgstr[' === substr($line, 0, 7)) {
$size = strpos($line, ']');
$item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1);
}
*
* A .po file could contain by error missing plural indexes. We need to
* fix these before saving them.
- *
- * @param array $messages
- * @param array $item
*/
private function addMessage(array &$messages, array $item)
{
$nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');
$catalogue = new MessageCatalogue($locale);
- if ($nodes->length == 1) {
+ if (1 == $nodes->length) {
$translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
foreach ($translations as $translation) {
$translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;
* @param MessageCatalogue $catalogue Catalogue where we'll collect messages and metadata
* @param string $domain The domain
*/
- private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, $domain)
+ private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
{
$xml = simplexml_import_dom($dom);
$encoding = strtoupper($dom->encoding);
}
}
- /**
- * @param \DOMDocument $dom
- * @param MessageCatalogue $catalogue
- * @param string $domain
- */
- private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, $domain)
+ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
{
$xml = simplexml_import_dom($dom);
$encoding = strtoupper($dom->encoding);
$xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0');
- foreach ($xml->xpath('//xliff:unit/xliff:segment') as $segment) {
- $source = $segment->source;
+ foreach ($xml->xpath('//xliff:unit') as $unit) {
+ foreach ($unit->segment as $segment) {
+ $source = $segment->source;
- // If the xlf file has another encoding specified, try to convert it because
- // simple_xml will always return utf-8 encoded values
- $target = $this->utf8ToCharset((string) (isset($segment->target) ? $segment->target : $source), $encoding);
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) (isset($segment->target) ? $segment->target : $source), $encoding);
- $catalogue->set((string) $source, $target, $domain);
+ $catalogue->set((string) $source, $target, $domain);
- $metadata = array();
- if (isset($segment->target) && $segment->target->attributes()) {
- $metadata['target-attributes'] = array();
- foreach ($segment->target->attributes() as $key => $value) {
- $metadata['target-attributes'][$key] = (string) $value;
+ $metadata = array();
+ if (isset($segment->target) && $segment->target->attributes()) {
+ $metadata['target-attributes'] = array();
+ foreach ($segment->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
}
- }
- $catalogue->setMetadata((string) $source, $metadata, $domain);
+ if (isset($unit->notes)) {
+ $metadata['notes'] = array();
+ foreach ($unit->notes->note as $noteNode) {
+ $note = array();
+ foreach ($noteNode->attributes() as $key => $value) {
+ $note[$key] = (string) $value;
+ }
+ $note['content'] = (string) $noteNode;
+ $metadata['notes'][] = $note;
+ }
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
}
}
/**
* Convert a UTF8 string to the specified encoding.
- *
- * @param string $content String to decode
- * @param string $encoding Target encoding
- *
- * @return string
*/
- private function utf8ToCharset($content, $encoding = null)
+ private function utf8ToCharset(string $content, string $encoding = null): string
{
if ('UTF-8' !== $encoding && !empty($encoding)) {
return mb_convert_encoding($content, $encoding, 'UTF-8');
/**
* Validates and parses the given file into a DOMDocument.
*
- * @param string $file
- * @param \DOMDocument $dom
- * @param string $schema source of the schema
- *
* @throws InvalidResourceException
*/
- private function validateSchema($file, \DOMDocument $dom, $schema)
+ private function validateSchema(string $file, \DOMDocument $dom, string $schema)
{
$internalErrors = libxml_use_internal_errors(true);
/**
* Internally changes the URI of a dependent xsd to be loaded locally.
- *
- * @param string $schemaSource Current content of schema file
- * @param string $xmlUri External URI of XML to convert to local
- *
- * @return string
*/
- private function fixXmlLocation($schemaSource, $xmlUri)
+ private function fixXmlLocation(string $schemaSource, string $xmlUri): string
{
$newPath = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd';
$parts = explode('/', $newPath);
+ $locationstart = 'file:///';
if (0 === stripos($newPath, 'phar://')) {
- $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
+ $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
if ($tmpfile) {
copy($newPath, $tmpfile);
$parts = explode('/', str_replace('\\', '/', $tmpfile));
+ } else {
+ array_shift($parts);
+ $locationstart = 'phar:///';
}
}
$drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
- $newPath = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));
+ $newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts));
return str_replace($xmlUri, $newPath, $schemaSource);
}
/**
* Returns the XML errors of the internal XML parser.
- *
- * @param bool $internalErrors
- *
- * @return array An array of errors
*/
- private function getXmlErrors($internalErrors)
+ private function getXmlErrors(bool $internalErrors): array
{
$errors = array();
foreach (libxml_get_errors() as $error) {
* Gets xliff file version based on the root "version" attribute.
* Defaults to 1.2 for backwards compatibility.
*
- * @param \DOMDocument $dom
- *
* @throws InvalidArgumentException
- *
- * @return string
*/
- private function getVersionNumber(\DOMDocument $dom)
+ private function getVersionNumber(\DOMDocument $dom): string
{
/** @var \DOMNode $xliff */
foreach ($dom->getElementsByTagName('xliff') as $xliff) {
$namespace = $xliff->attributes->getNamedItem('xmlns');
if ($namespace) {
- if (substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34) !== 0) {
+ if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) {
throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s"', $namespace));
}
return '1.2';
}
- /**
- * @param \SimpleXMLElement|null $noteElement
- * @param string|null $encoding
- *
- * @return array
- */
- private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, $encoding = null)
+ private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array
{
$notes = array();
use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Yaml\Exception\ParseException;
-use Symfony\Component\Yaml\Yaml;
/**
* YamlFileLoader loads translations from Yaml files.
}
try {
- $messages = $this->yamlParser->parse(file_get_contents($resource), Yaml::PARSE_KEYS_AS_STRINGS);
+ $messages = $this->yamlParser->parseFile($resource);
} catch (ParseException $e) {
throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $resource), 0, $e);
}
*/
private $translator;
- /**
- * @var LoggerInterface
- */
private $logger;
/**
use Symfony\Component\Translation\Exception\LogicException;
/**
- * MessageCatalogue.
- *
* @author Fabien Potencier <fabien@symfony.com>
*/
class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface
private $parent;
/**
- * Constructor.
- *
* @param string $locale The locale
* @param array $messages An array of messages classified by domain
*/
- public function __construct($locale, array $messages = array())
+ public function __construct(?string $locale, array $messages = array())
{
$this->locale = $locale;
$this->messages = $messages;
* Merges translations from the given Catalogue into the current one.
*
* The two catalogues must have the same locale.
- *
- * @param self $catalogue
*/
public function addCatalogue(MessageCatalogueInterface $catalogue);
* only when the translation does not exist.
*
* This is used to provide default translations when they do not exist for the current locale.
- *
- * @param self $catalogue
*/
public function addFallbackCatalogue(MessageCatalogueInterface $catalogue);
/**
* Adds a resource for this collection.
- *
- * @param ResourceInterface $resource A resource instance
*/
public function addResource(ResourceInterface $resource);
}
*/
public function choose($message, $number, $locale)
{
- preg_match_all('/(?:\|\||[^\|])++/', $message, $parts);
+ $parts = array();
+ if (preg_match('/^\|++$/', $message)) {
+ $parts = explode('|', $message);
+ } elseif (preg_match_all('/(?:\|\||[^\|])++/', $message, $matches)) {
+ $parts = $matches[0];
+ }
+
$explicitRules = array();
$standardRules = array();
- foreach ($parts[0] as $part) {
+ foreach ($parts as $part) {
$part = trim(str_replace('||', '|', $part));
if (preg_match('/^(?P<interval>'.Interval::getIntervalRegexp().')\s*(?P<message>.*?)$/xs', $part, $matches)) {
if (!isset($standardRules[$position])) {
// when there's exactly one rule given, and that rule is a standard
// rule, use this rule
- if (1 === count($parts[0]) && isset($standardRules[0])) {
+ if (1 === count($parts) && isset($standardRules[0])) {
return $standardRules[0];
}
case 'vi':
case 'zh':
return 0;
- break;
case 'af':
case 'bn':
case 'tk':
case 'ur':
case 'zu':
- return ($number == 1) ? 0 : 1;
+ return (1 == $number) ? 0 : 1;
case 'am':
case 'bh':
case 'xbr':
case 'ti':
case 'wa':
- return (($number == 0) || ($number == 1)) ? 0 : 1;
+ return ((0 == $number) || (1 == $number)) ? 0 : 1;
case 'be':
case 'bs':
case 'ru':
case 'sr':
case 'uk':
- return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+ return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
case 'cs':
case 'sk':
- return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
+ return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
case 'ga':
- return ($number == 1) ? 0 : (($number == 2) ? 1 : 2);
+ return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2);
case 'lt':
- return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+ return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
case 'sl':
- return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3));
+ return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3));
case 'mk':
- return ($number % 10 == 1) ? 0 : 1;
+ return (1 == $number % 10) ? 0 : 1;
case 'mt':
- return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
+ return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
case 'lv':
- return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2);
+ return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2);
case 'pl':
- return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
+ return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
case 'cy':
- return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3));
+ return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3));
case 'ro':
- return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
+ return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
case 'ar':
- return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5))));
+ return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5))));
default:
return 0;
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Reader;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationReader reads translation messages from translation files.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class TranslationReader implements TranslationReaderInterface
+{
+ /**
+ * Loaders used for import.
+ *
+ * @var array
+ */
+ private $loaders = array();
+
+ /**
+ * Adds a loader to the translation extractor.
+ *
+ * @param string $format The format of the loader
+ * @param LoaderInterface $loader
+ */
+ public function addLoader($format, LoaderInterface $loader)
+ {
+ $this->loaders[$format] = $loader;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read($directory, MessageCatalogue $catalogue)
+ {
+ if (!is_dir($directory)) {
+ return;
+ }
+
+ foreach ($this->loaders as $format => $loader) {
+ // load any existing translation files
+ $finder = new Finder();
+ $extension = $catalogue->getLocale().'.'.$format;
+ $files = $finder->files()->name('*.'.$extension)->in($directory);
+ foreach ($files as $file) {
+ $domain = substr($file->getFilename(), 0, -1 * strlen($extension) - 1);
+ $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain));
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Reader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationReader reads translation messages from translation files.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+interface TranslationReaderInterface
+{
+ /**
+ * Reads translation messages from a directory to the catalogue.
+ *
+ * @param string $directory
+ * @param MessageCatalogue $catalogue
+ */
+ public function read($directory, MessageCatalogue $catalogue);
+}
-<?xml version="1.0" encoding="UTF-8"?>\r
-\r
-<!--\r
-\r
-May-19-2004:\r
-- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements \r
-to <choice> itself.\r
-- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and\r
-<alt-trans>.\r
-\r
-Oct-2005\r
-- updated version info to 1.2\r
-- equiv-trans attribute to <trans-unit> element \r
-- merged-trans attribute for <group> element\r
-- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source> \r
-- Create a new value "seg" for the mtype attribute of the <mrk> element\r
-- Add mid as an optional attribute for the <alt-trans> element\r
-\r
-Nov-14-2005\r
-- Changed name attribute for <context-group> from required to optional\r
-- Added extension point at <xliff>\r
-\r
-Jan-9-2006\r
-- Added alttranstype type attribute to <alt-trans>, and values\r
-\r
-Jan-10-2006\r
-- Corrected error with overwritten purposeValueList\r
-- Corrected name="AttrType_Version", attribute should have been "name"\r
-\r
--->\r
-<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">\r
- <!-- Import for xml:lang and xml:space -->\r
- <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>\r
- <!-- Attributes Lists -->\r
- <xsd:simpleType name="XTend">\r
- <xsd:restriction base="xsd:string">\r
- <xsd:pattern value="x-[^\s]+"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="context-typeValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:string">\r
- <xsd:enumeration value="database">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a database content.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="element">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="elementtitle">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="linenumber">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="numparams">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a the number of parameters contained within the <source>.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="paramnotes">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates notes pertaining to the parameters in the <source>.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="record">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="recordtitle">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="sourcefile">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="count-typeValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="num-usages">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="repetition">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="total">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a total count.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="InlineDelimitersValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'ctype' when used other elements than <ph> or <x>.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="bold">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="italic">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="underlined">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="link">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="InlinePlaceholdersValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'ctype' when used with <ph> or <x>.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="image">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a inline image.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="pb">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a page break.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="lb">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a line break.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="mime-typeValueList">\r
- <xsd:restriction base="xsd:string">\r
- <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="datatypeValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="asp">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="c">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates C source file data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="cdf">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="cfm">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="cpp">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates C++ source file data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="csharp">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="cstring">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="csv">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="database">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates database data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="documentfooter">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="documentheader">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="filedialog">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="form">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="html">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="htmlbody">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates content within an HTML document’s <body> element.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="ini">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="interleaf">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Interleaf data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="javaclass">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="javapropertyresourcebundle">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="javalistresourcebundle">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="javascript">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="jscript">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates JScript source file data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="layout">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="lisp">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates LISP source file data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="margin">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="menufile">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a file containing menu.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="messagefile">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="mif">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="mimetype">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="mo">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="msglib">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="pagefooter">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="pageheader">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="parameters">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="pascal">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="php">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="plaintext">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="po">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="report">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="resources">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="resx">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rtf">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="sgml">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="sgmldtd">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="svg">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="vbscript">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="warning">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates warning message.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="winres">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="xhtml">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="xml">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="xmldtd">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="xsl">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="xul">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates XUL elements.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="mtypeValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="abbrev">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="abbreviated-form">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="abbreviation">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="acronym">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="appellation">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="collocation">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="common-name">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="datetime">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="equation">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="expanded-form">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="formula">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="head-term">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="initialism">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="international-scientific-term">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="internationalism">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="logical-expression">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="materials-management-unit">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="name">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="near-synonym">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="part-number">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="phrase">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="phraseological-unit">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="protected">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="romanized-form">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="seg">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="set-phrase">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="short-form">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="sku">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="standard-text">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="symbol">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="synonym">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="synonymous-phrase">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="term">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="transcribed-form">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="transliterated-form">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="truncated-term">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="variant">\r
- <xsd:annotation>\r
- <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="restypeValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="auto3state">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="autocheckbox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="autoradiobutton">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="bedit">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="bitmap">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="button">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="caption">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="cell">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the cell in a table, for example the content of the <td> element in HTML.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="checkbox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="checkboxmenuitem">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="checkedlistbox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="colorchooser">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="combobox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="comboboxexitem">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="comboboxitem">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="component">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="contextmenu">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a context menu.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="ctext">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="cursor">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="datetimepicker">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a date/time picker.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="defpushbutton">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="dialog">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a dialog box.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="dlginit">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="edit">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="file">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a filename.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="filechooser">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a file dialog.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="fn">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a footnote.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="font">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a font name.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="footer">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a footer.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="frame">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a frame object.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="grid">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="groupbox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="header">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a header item.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="heading">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="hedit">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="hscrollbar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="icon">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="iedit">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="keywords">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="label">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a label object.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="linklabel">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="list">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="listbox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="listitem">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="ltext">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="menu">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="menubar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="menuitem">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="menuseparator">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="message">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="monthcalendar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a calendar control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="numericupdown">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="panel">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="popupmenu">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="pushbox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="pushbutton">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="radio">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a radio button object.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="radiobuttonmenuitem">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rcdata">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="row">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a row in a table.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rtext">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="scrollpane">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="separator">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="shortcut">\r
- <xsd:annotation>\r
- <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="spinner">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="splitter">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a splitter bar.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="state3">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="statusbar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="string">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="tabcontrol">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="table">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="textbox">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="togglebutton">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="toolbar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="tooltip">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="trackbar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="tree">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="uri">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="userbutton">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="usercontrol">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="var">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the text of a variable.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="versioninfo">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="vscrollbar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="window">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a graphical window.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="size-unitValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="byte">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="char">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="col">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="cm">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="dlgunit">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="em">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="ex">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="glyph">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="in">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in inches.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="mm">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="percent">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in percentage.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="pixel">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in pixels.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="point">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in point.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="row">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="stateValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="final">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the terminating state.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="needs-adaptation">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="needs-l10n">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="needs-review-adaptation">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="needs-review-l10n">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="needs-review-translation">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="needs-translation">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="new">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="signed-off">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="translated">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="state-qualifierValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="exact-match">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="fuzzy-match">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="id-match">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="leveraged-glossary">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="leveraged-inherited">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="leveraged-mt">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="leveraged-repository">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="leveraged-tm">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="mt-suggestion">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rejected-grammar">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rejected-inaccurate">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rejected-length">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rejected-spelling">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="tm-suggestion">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="unitValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="word">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to words.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="page">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to pages.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="trans-unit">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to <trans-unit> elements.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="bin-unit">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to <bin-unit> elements.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="glyph">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to glyphs.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="item">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to <trans-unit> and/or <bin-unit> elements.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="instance">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="character">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to characters.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="line">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to lines.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="sentence">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to sentences.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="paragraph">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to paragraphs.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="segment">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to segments.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="placeable">\r
- <xsd:annotation>\r
- <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="priorityValueList">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:positiveInteger">\r
- <xsd:enumeration value="1">\r
- <xsd:annotation>\r
- <xsd:documentation>Highest priority.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="2">\r
- <xsd:annotation>\r
- <xsd:documentation>High priority.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="3">\r
- <xsd:annotation>\r
- <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="4">\r
- <xsd:annotation>\r
- <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="5">\r
- <xsd:annotation>\r
- <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="6">\r
- <xsd:annotation>\r
- <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="7">\r
- <xsd:annotation>\r
- <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="8">\r
- <xsd:annotation>\r
- <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="9">\r
- <xsd:annotation>\r
- <xsd:documentation>Low priority.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="10">\r
- <xsd:annotation>\r
- <xsd:documentation>Lowest priority.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="reformatValueYesNo">\r
- <xsd:restriction base="xsd:string">\r
- <xsd:enumeration value="yes">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="no">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="reformatValueList">\r
- <xsd:list>\r
- <xsd:simpleType>\r
- <xsd:union memberTypes="xlf:XTend">\r
- <xsd:simpleType>\r
- <xsd:restriction base="xsd:string">\r
- <xsd:enumeration value="coord">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="coord-x">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="coord-y">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="coord-cx">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="coord-cy">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="font">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="font-name">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="font-size">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="font-weight">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="css-style">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="style">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="ex-style">\r
- <xsd:annotation>\r
- <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- </xsd:union>\r
- </xsd:simpleType>\r
- </xsd:list>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="purposeValueList">\r
- <xsd:restriction base="xsd:string">\r
- <xsd:enumeration value="information">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="location">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="match">\r
- <xsd:annotation>\r
- <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="alttranstypeValueList">\r
- <xsd:restriction base="xsd:string">\r
- <xsd:enumeration value="proposal">\r
- <xsd:annotation>\r
- <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="previous-version">\r
- <xsd:annotation>\r
- <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="rejected">\r
- <xsd:annotation>\r
- <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="reference">\r
- <xsd:annotation>\r
- <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- <xsd:enumeration value="accepted">\r
- <xsd:annotation>\r
- <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>\r
- </xsd:annotation>\r
- </xsd:enumeration>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <!-- Other Types -->\r
- <xsd:complexType name="ElemType_ExternalReference">\r
- <xsd:choice>\r
- <xsd:element ref="xlf:internal-file"/>\r
- <xsd:element ref="xlf:external-file"/>\r
- </xsd:choice>\r
- </xsd:complexType>\r
- <xsd:simpleType name="AttrType_purpose">\r
- <xsd:list>\r
- <xsd:simpleType>\r
- <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- </xsd:list>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_datatype">\r
- <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_restype">\r
- <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_alttranstype">\r
- <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_context-type">\r
- <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_state">\r
- <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_state-qualifier">\r
- <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_count-type">\r
- <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_InlineDelimiters">\r
- <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_InlinePlaceholders">\r
- <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_size-unit">\r
- <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_mtype">\r
- <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_unit">\r
- <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_priority">\r
- <xsd:union memberTypes="xlf:priorityValueList"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_reformat">\r
- <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_YesNo">\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="yes"/>\r
- <xsd:enumeration value="no"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_Position">\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="open"/>\r
- <xsd:enumeration value="close"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_assoc">\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="preceding"/>\r
- <xsd:enumeration value="following"/>\r
- <xsd:enumeration value="both"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_annotates">\r
- <xsd:restriction base="xsd:NMTOKEN">\r
- <xsd:enumeration value="source"/>\r
- <xsd:enumeration value="target"/>\r
- <xsd:enumeration value="general"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_Coordinates">\r
- <xsd:annotation>\r
- <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:string">\r
- <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <xsd:simpleType name="AttrType_Version">\r
- <xsd:annotation>\r
- <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>\r
- </xsd:annotation>\r
- <xsd:restriction base="xsd:string">\r
- <xsd:enumeration value="1.2"/>\r
- <xsd:enumeration value="1.1"/>\r
- <xsd:enumeration value="1.0"/>\r
- </xsd:restriction>\r
- </xsd:simpleType>\r
- <!-- Groups -->\r
- <xsd:group name="ElemGroup_TextContent">\r
- <xsd:choice>\r
- <xsd:element ref="xlf:g"/>\r
- <xsd:element ref="xlf:bpt"/>\r
- <xsd:element ref="xlf:ept"/>\r
- <xsd:element ref="xlf:ph"/>\r
- <xsd:element ref="xlf:it"/>\r
- <xsd:element ref="xlf:mrk"/>\r
- <xsd:element ref="xlf:x"/>\r
- <xsd:element ref="xlf:bx"/>\r
- <xsd:element ref="xlf:ex"/>\r
- </xsd:choice>\r
- </xsd:group>\r
- <xsd:attributeGroup name="AttrGroup_TextContent">\r
- <xsd:attribute name="id" type="xsd:string" use="required"/>\r
- <xsd:attribute name="xid" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:attributeGroup>\r
- <!-- XLIFF Structure -->\r
- <xsd:element name="xliff">\r
- <xsd:complexType>\r
- <xsd:sequence maxOccurs="unbounded">\r
- <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>\r
- <xsd:element ref="xlf:file"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>\r
- <xsd:attribute ref="xml:lang" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="file">\r
- <xsd:complexType>\r
- <xsd:sequence>\r
- <xsd:element minOccurs="0" ref="xlf:header"/>\r
- <xsd:element ref="xlf:body"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="original" type="xsd:string" use="required"/>\r
- <xsd:attribute name="source-language" type="xsd:language" use="required"/>\r
- <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>\r
- <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>\r
- <xsd:attribute ref="xml:space" use="optional"/>\r
- <xsd:attribute name="category" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="target-language" type="xsd:language" use="optional"/>\r
- <xsd:attribute name="product-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="product-version" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="build-num" type="xsd:string" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- <xsd:unique name="U_group_id">\r
- <xsd:selector xpath=".//xlf:group"/>\r
- <xsd:field xpath="@id"/>\r
- </xsd:unique>\r
- <xsd:key name="K_unit_id">\r
- <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>\r
- <xsd:field xpath="@id"/>\r
- </xsd:key>\r
- <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">\r
- <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>\r
- <xsd:field xpath="@xid"/>\r
- </xsd:keyref>\r
- <xsd:key name="K_tool-id">\r
- <xsd:selector xpath="xlf:header/xlf:tool"/>\r
- <xsd:field xpath="@tool-id"/>\r
- </xsd:key>\r
- <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">\r
- <xsd:selector xpath="."/>\r
- <xsd:field xpath="@tool-id"/>\r
- </xsd:keyref>\r
- <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">\r
- <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>\r
- <xsd:field xpath="@tool-id"/>\r
- </xsd:keyref>\r
- <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">\r
- <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>\r
- <xsd:field xpath="@tool-id"/>\r
- </xsd:keyref>\r
- <xsd:key name="K_count-group_name">\r
- <xsd:selector xpath=".//xlf:count-group"/>\r
- <xsd:field xpath="@name"/>\r
- </xsd:key>\r
- <xsd:unique name="U_context-group_name">\r
- <xsd:selector xpath=".//xlf:context-group"/>\r
- <xsd:field xpath="@name"/>\r
- </xsd:unique>\r
- <xsd:key name="K_phase-name">\r
- <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>\r
- <xsd:field xpath="@phase-name"/>\r
- </xsd:key>\r
- <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">\r
- <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>\r
- <xsd:field xpath="@phase-name"/>\r
- </xsd:keyref>\r
- <xsd:unique name="U_uid">\r
- <xsd:selector xpath=".//xlf:external-file"/>\r
- <xsd:field xpath="@uid"/>\r
- </xsd:unique>\r
- </xsd:element>\r
- <xsd:element name="header">\r
- <xsd:complexType>\r
- <xsd:sequence>\r
- <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>\r
- <xsd:element minOccurs="0" ref="xlf:phase-group"/>\r
- <xsd:choice maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>\r
- <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>\r
- <xsd:element ref="xlf:count-group"/>\r
- <xsd:element ref="xlf:note"/>\r
- <xsd:element ref="xlf:tool"/>\r
- </xsd:choice>\r
- <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>\r
- </xsd:sequence>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="internal-file">\r
- <xsd:complexType>\r
- <xsd:simpleContent>\r
- <xsd:extension base="xsd:string">\r
- <xsd:attribute name="form" type="xsd:string"/>\r
- <xsd:attribute name="crc" type="xsd:NMTOKEN"/>\r
- </xsd:extension>\r
- </xsd:simpleContent>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="external-file">\r
- <xsd:complexType>\r
- <xsd:attribute name="href" type="xsd:string" use="required"/>\r
- <xsd:attribute name="crc" type="xsd:NMTOKEN"/>\r
- <xsd:attribute name="uid" type="xsd:NMTOKEN"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="note">\r
- <xsd:complexType>\r
- <xsd:simpleContent>\r
- <xsd:extension base="xsd:string">\r
- <xsd:attribute ref="xml:lang" use="optional"/>\r
- <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>\r
- <xsd:attribute name="from" type="xsd:string" use="optional"/>\r
- <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>\r
- </xsd:extension>\r
- </xsd:simpleContent>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="phase-group">\r
- <xsd:complexType>\r
- <xsd:sequence maxOccurs="unbounded">\r
- <xsd:element ref="xlf:phase"/>\r
- </xsd:sequence>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="phase">\r
- <xsd:complexType>\r
- <xsd:sequence maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:note"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="phase-name" type="xsd:string" use="required"/>\r
- <xsd:attribute name="process-name" type="xsd:string" use="required"/>\r
- <xsd:attribute name="company-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>\r
- <xsd:attribute name="job-id" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="count-group">\r
- <xsd:complexType>\r
- <xsd:sequence maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:count"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="name" type="xsd:string" use="required"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="count">\r
- <xsd:complexType>\r
- <xsd:simpleContent>\r
- <xsd:extension base="xsd:string">\r
- <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>\r
- <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>\r
- </xsd:extension>\r
- </xsd:simpleContent>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="context-group">\r
- <xsd:complexType>\r
- <xsd:sequence maxOccurs="unbounded">\r
- <xsd:element ref="xlf:context"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="context">\r
- <xsd:complexType>\r
- <xsd:simpleContent>\r
- <xsd:extension base="xsd:string">\r
- <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>\r
- <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>\r
- </xsd:extension>\r
- </xsd:simpleContent>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="tool">\r
- <xsd:complexType mixed="true">\r
- <xsd:sequence>\r
- <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="tool-id" type="xsd:string" use="required"/>\r
- <xsd:attribute name="tool-name" type="xsd:string" use="required"/>\r
- <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="body">\r
- <xsd:complexType>\r
- <xsd:choice maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>\r
- </xsd:choice>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="group">\r
- <xsd:complexType>\r
- <xsd:sequence>\r
- <xsd:sequence>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>\r
- <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>\r
- </xsd:sequence>\r
- <xsd:choice maxOccurs="unbounded">\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>\r
- </xsd:choice>\r
- </xsd:sequence>\r
- <xsd:attribute name="id" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>\r
- <xsd:attribute default="default" ref="xml:space" use="optional"/>\r
- <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>\r
- <xsd:attribute name="resname" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="extradata" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="extype" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="menu" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>\r
- <xsd:attribute name="font" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="css-style" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>\r
- <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>\r
- <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="charclass" type="xsd:string" use="optional"/>\r
- <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="trans-unit">\r
- <xsd:complexType>\r
- <xsd:sequence>\r
- <xsd:element ref="xlf:source"/>\r
- <xsd:element minOccurs="0" ref="xlf:seg-source"/>\r
- <xsd:element minOccurs="0" ref="xlf:target"/>\r
- <xsd:choice maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:context-group"/>\r
- <xsd:element ref="xlf:count-group"/>\r
- <xsd:element ref="xlf:note"/>\r
- <xsd:element ref="xlf:alt-trans"/>\r
- </xsd:choice>\r
- <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="id" type="xsd:string" use="required"/>\r
- <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>\r
- <xsd:attribute default="default" ref="xml:space" use="optional"/>\r
- <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>\r
- <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>\r
- <xsd:attribute name="resname" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="extradata" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="extype" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="menu" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>\r
- <xsd:attribute name="font" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="css-style" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>\r
- <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="charclass" type="xsd:string" use="optional"/>\r
- <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- <xsd:unique name="U_tu_segsrc_mid">\r
- <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>\r
- <xsd:field xpath="@mid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">\r
- <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>\r
- <xsd:field xpath="@mid"/>\r
- </xsd:keyref>\r
- </xsd:element>\r
- <xsd:element name="source">\r
- <xsd:complexType mixed="true">\r
- <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>\r
- <xsd:attribute ref="xml:lang" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- <xsd:unique name="U_source_bpt_rid">\r
- <xsd:selector xpath=".//xlf:bpt"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">\r
- <xsd:selector xpath=".//xlf:ept"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:keyref>\r
- <xsd:unique name="U_source_bx_rid">\r
- <xsd:selector xpath=".//xlf:bx"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">\r
- <xsd:selector xpath=".//xlf:ex"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:keyref>\r
- </xsd:element>\r
- <xsd:element name="seg-source">\r
- <xsd:complexType mixed="true">\r
- <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>\r
- <xsd:attribute ref="xml:lang" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- <xsd:unique name="U_segsrc_bpt_rid">\r
- <xsd:selector xpath=".//xlf:bpt"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">\r
- <xsd:selector xpath=".//xlf:ept"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:keyref>\r
- <xsd:unique name="U_segsrc_bx_rid">\r
- <xsd:selector xpath=".//xlf:bx"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">\r
- <xsd:selector xpath=".//xlf:ex"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:keyref>\r
- </xsd:element>\r
- <xsd:element name="target">\r
- <xsd:complexType mixed="true">\r
- <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>\r
- <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>\r
- <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>\r
- <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute ref="xml:lang" use="optional"/>\r
- <xsd:attribute name="resname" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>\r
- <xsd:attribute name="font" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="css-style" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- <xsd:unique name="U_target_bpt_rid">\r
- <xsd:selector xpath=".//xlf:bpt"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">\r
- <xsd:selector xpath=".//xlf:ept"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:keyref>\r
- <xsd:unique name="U_target_bx_rid">\r
- <xsd:selector xpath=".//xlf:bx"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">\r
- <xsd:selector xpath=".//xlf:ex"/>\r
- <xsd:field xpath="@rid"/>\r
- </xsd:keyref>\r
- </xsd:element>\r
- <xsd:element name="alt-trans">\r
- <xsd:complexType>\r
- <xsd:sequence>\r
- <xsd:element minOccurs="0" ref="xlf:source"/>\r
- <xsd:element minOccurs="0" ref="xlf:seg-source"/>\r
- <xsd:element maxOccurs="1" ref="xlf:target"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>\r
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>\r
- <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute ref="xml:lang" use="optional"/>\r
- <xsd:attribute name="origin" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>\r
- <xsd:attribute default="default" ref="xml:space" use="optional"/>\r
- <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>\r
- <xsd:attribute name="resname" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="extradata" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="extype" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="menu" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>\r
- <xsd:attribute name="font" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="css-style" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- <xsd:unique name="U_at_segsrc_mid">\r
- <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>\r
- <xsd:field xpath="@mid"/>\r
- </xsd:unique>\r
- <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">\r
- <xsd:selector xpath="./xlf:target/xlf:mrk"/>\r
- <xsd:field xpath="@mid"/>\r
- </xsd:keyref>\r
- </xsd:element>\r
- <xsd:element name="bin-unit">\r
- <xsd:complexType>\r
- <xsd:sequence>\r
- <xsd:element ref="xlf:bin-source"/>\r
- <xsd:element minOccurs="0" ref="xlf:bin-target"/>\r
- <xsd:choice maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:context-group"/>\r
- <xsd:element ref="xlf:count-group"/>\r
- <xsd:element ref="xlf:note"/>\r
- <xsd:element ref="xlf:trans-unit"/>\r
- </xsd:choice>\r
- <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="id" type="xsd:string" use="required"/>\r
- <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>\r
- <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>\r
- <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>\r
- <xsd:attribute name="resname" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="bin-source">\r
- <xsd:complexType>\r
- <xsd:choice>\r
- <xsd:element ref="xlf:internal-file"/>\r
- <xsd:element ref="xlf:external-file"/>\r
- </xsd:choice>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="bin-target">\r
- <xsd:complexType>\r
- <xsd:choice>\r
- <xsd:element ref="xlf:internal-file"/>\r
- <xsd:element ref="xlf:external-file"/>\r
- </xsd:choice>\r
- <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>\r
- <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>\r
- <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>\r
- <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>\r
- <xsd:attribute name="resname" type="xsd:string" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <!-- Element for inline codes -->\r
- <xsd:element name="g">\r
- <xsd:complexType mixed="true">\r
- <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>\r
- <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>\r
- <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="x">\r
- <xsd:complexType>\r
- <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>\r
- <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="bx">\r
- <xsd:complexType>\r
- <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>\r
- <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="ex">\r
- <xsd:complexType>\r
- <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="ph">\r
- <xsd:complexType mixed="true">\r
- <xsd:sequence maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:sub"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>\r
- <xsd:attribute name="crc" type="xsd:string" use="optional"/>\r
- <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="bpt">\r
- <xsd:complexType mixed="true">\r
- <xsd:sequence maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:sub"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>\r
- <xsd:attribute name="crc" type="xsd:string" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="ept">\r
- <xsd:complexType mixed="true">\r
- <xsd:sequence maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:sub"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="crc" type="xsd:string" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="it">\r
- <xsd:complexType mixed="true">\r
- <xsd:sequence maxOccurs="unbounded" minOccurs="0">\r
- <xsd:element ref="xlf:sub"/>\r
- </xsd:sequence>\r
- <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>\r
- <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>\r
- <xsd:attribute name="crc" type="xsd:string" use="optional"/>\r
- <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="sub">\r
- <xsd:complexType mixed="true">\r
- <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>\r
- <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>\r
- <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>\r
- <xsd:attribute name="xid" type="xsd:string" use="optional"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
- <xsd:element name="mrk">\r
- <xsd:complexType mixed="true">\r
- <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>\r
- <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>\r
- <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>\r
- <xsd:attribute name="comment" type="xsd:string" use="optional"/>\r
- <xsd:anyAttribute namespace="##other" processContents="strict"/>\r
- </xsd:complexType>\r
- </xsd:element>\r
-</xsd:schema>
\ No newline at end of file
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+
+May-19-2004:
+- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements
+to <choice> itself.
+- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and
+<alt-trans>.
+
+Oct-2005
+- updated version info to 1.2
+- equiv-trans attribute to <trans-unit> element
+- merged-trans attribute for <group> element
+- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source>
+- Create a new value "seg" for the mtype attribute of the <mrk> element
+- Add mid as an optional attribute for the <alt-trans> element
+
+Nov-14-2005
+- Changed name attribute for <context-group> from required to optional
+- Added extension point at <xliff>
+
+Jan-9-2006
+- Added alttranstype type attribute to <alt-trans>, and values
+
+Jan-10-2006
+- Corrected error with overwritten purposeValueList
+- Corrected name="AttrType_Version", attribute should have been "name"
+
+-->
+<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
+ <!-- Import for xml:lang and xml:space -->
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ <!-- Attributes Lists -->
+ <xsd:simpleType name="XTend">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="x-[^\s]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="context-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a database content.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="element">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="elementtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linenumber">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numparams">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a the number of parameters contained within the <source>.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paramnotes">
+ <xsd:annotation>
+ <xsd:documentation>Indicates notes pertaining to the parameters in the <source>.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="record">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="recordtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sourcefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="count-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="num-usages">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="repetition">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="total">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a total count.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlineDelimitersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used other elements than <ph> or <x>.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="bold">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="italic">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="underlined">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="link">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlinePlaceholdersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used with <ph> or <x>.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="image">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a inline image.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a page break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a line break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mime-typeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="datatypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="asp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="c">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cdf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cfm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cpp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C++ source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csharp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cstring">
+ <xsd:annotation>
+ <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csv">
+ <xsd:annotation>
+ <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates database data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentfooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filedialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="form">
+ <xsd:annotation>
+ <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="html">
+ <xsd:annotation>
+ <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="htmlbody">
+ <xsd:annotation>
+ <xsd:documentation>Indicates content within an HTML document’s <body> element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ini">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="interleaf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Interleaf data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javaclass">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javapropertyresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javalistresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javascript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="jscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="layout">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lisp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates LISP source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="margin">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menufile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file containing menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="messagefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mif">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mimetype">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="msglib">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pagefooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pageheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="parameters">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pascal">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="php">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="plaintext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="po">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="report">
+ <xsd:annotation>
+ <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resources">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resx">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="svg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vbscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="warning">
+ <xsd:annotation>
+ <xsd:documentation>Indicates warning message.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="winres">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xhtml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xsl">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xul">
+ <xsd:annotation>
+ <xsd:documentation>Indicates XUL elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mtypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="abbrev">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="acronym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="appellation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="collocation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="common-name">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetime">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="equation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="expanded-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="formula">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="head-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="initialism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="international-scientific-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="internationalism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="logical-expression">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="materials-management-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="name">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="near-synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="part-number">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phrase">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phraseological-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="protected">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="romanized-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="seg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="set-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="short-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sku">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="standard-text">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="symbol">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonymous-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="term">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transcribed-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transliterated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="truncated-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="variant">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="restypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="auto3state">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autocheckbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autoradiobutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bitmap">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="button">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="caption">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cell">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the cell in a table, for example the content of the <td> element in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkboxmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkedlistbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="colorchooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="combobox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxexitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="component">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="contextmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a context menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ctext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cursor">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetimepicker">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a date/time picker.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="defpushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlginit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="edit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="file">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a filename.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filechooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fn">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footnote.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a font name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="footer">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footer.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="frame">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a frame object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="grid">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="groupbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="header">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a header item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="heading">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="icon">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="iedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="keywords">
+ <xsd:annotation>
+ <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="label">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linklabel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="list">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ltext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menubar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuseparator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="message">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="monthcalendar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a calendar control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numericupdown">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="panel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="popupmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radio">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a radio button object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radiobuttonmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rcdata">
+ <xsd:annotation>
+ <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a row in a table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="scrollpane">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="separator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="shortcut">
+ <xsd:annotation>
+ <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="spinner">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="splitter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a splitter bar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="state3">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="statusbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="string">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tabcontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="table">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="textbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="togglebutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="toolbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tooltip">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trackbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tree">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="uri">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="userbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="usercontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="var">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the text of a variable.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="versioninfo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="window">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a graphical window.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="size-unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="byte">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="char">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="col">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlgunit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="em">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="in">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in inches.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="percent">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in percentage.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pixel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in pixels.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="point">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in point.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="stateValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="final">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the terminating state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="new">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="signed-off">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="translated">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="state-qualifierValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="exact-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fuzzy-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="id-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-glossary">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-inherited">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-mt">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-repository">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-tm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mt-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-grammar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-inaccurate">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-length">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-spelling">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tm-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="word">
+ <xsd:annotation>
+ <xsd:documentation>Refers to words.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="page">
+ <xsd:annotation>
+ <xsd:documentation>Refers to pages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trans-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <trans-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bin-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <bin-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to glyphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="item">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <trans-unit> and/or <bin-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="instance">
+ <xsd:annotation>
+ <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="character">
+ <xsd:annotation>
+ <xsd:documentation>Refers to characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="line">
+ <xsd:annotation>
+ <xsd:documentation>Refers to lines.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sentence">
+ <xsd:annotation>
+ <xsd:documentation>Refers to sentences.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paragraph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to paragraphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="segment">
+ <xsd:annotation>
+ <xsd:documentation>Refers to segments.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="placeable">
+ <xsd:annotation>
+ <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="priorityValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:positiveInteger">
+ <xsd:enumeration value="1">
+ <xsd:annotation>
+ <xsd:documentation>Highest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="2">
+ <xsd:annotation>
+ <xsd:documentation>High priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="3">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="4">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="5">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="6">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="7">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="8">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="9">
+ <xsd:annotation>
+ <xsd:documentation>Low priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="10">
+ <xsd:annotation>
+ <xsd:documentation>Lowest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueYesNo">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="yes">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="no">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueList">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:XTend">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="coord">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-x">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-y">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cx">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cy">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-name">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-size">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-weight">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="css-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="purposeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="information">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="location">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="alttranstypeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="proposal">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="previous-version">
+ <xsd:annotation>
+ <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected">
+ <xsd:annotation>
+ <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="reference">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="accepted">
+ <xsd:annotation>
+ <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Other Types -->
+ <xsd:complexType name="ElemType_ExternalReference">
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ </xsd:complexType>
+ <xsd:simpleType name="AttrType_purpose">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_datatype">
+ <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_restype">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_alttranstype">
+ <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_context-type">
+ <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state">
+ <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state-qualifier">
+ <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_count-type">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlineDelimiters">
+ <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlinePlaceholders">
+ <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_size-unit">
+ <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_mtype">
+ <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_unit">
+ <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_priority">
+ <xsd:union memberTypes="xlf:priorityValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_reformat">
+ <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_YesNo">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="yes"/>
+ <xsd:enumeration value="no"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Position">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="open"/>
+ <xsd:enumeration value="close"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_assoc">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="preceding"/>
+ <xsd:enumeration value="following"/>
+ <xsd:enumeration value="both"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_annotates">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="source"/>
+ <xsd:enumeration value="target"/>
+ <xsd:enumeration value="general"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Coordinates">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Version">
+ <xsd:annotation>
+ <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="1.2"/>
+ <xsd:enumeration value="1.1"/>
+ <xsd:enumeration value="1.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Groups -->
+ <xsd:group name="ElemGroup_TextContent">
+ <xsd:choice>
+ <xsd:element ref="xlf:g"/>
+ <xsd:element ref="xlf:bpt"/>
+ <xsd:element ref="xlf:ept"/>
+ <xsd:element ref="xlf:ph"/>
+ <xsd:element ref="xlf:it"/>
+ <xsd:element ref="xlf:mrk"/>
+ <xsd:element ref="xlf:x"/>
+ <xsd:element ref="xlf:bx"/>
+ <xsd:element ref="xlf:ex"/>
+ </xsd:choice>
+ </xsd:group>
+ <xsd:attributeGroup name="AttrGroup_TextContent">
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:attributeGroup>
+ <!-- XLIFF Structure -->
+ <xsd:element name="xliff">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ <xsd:element ref="xlf:file"/>
+ </xsd:sequence>
+ <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="file">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:header"/>
+ <xsd:element ref="xlf:body"/>
+ </xsd:sequence>
+ <xsd:attribute name="original" type="xsd:string" use="required"/>
+ <xsd:attribute name="source-language" type="xsd:language" use="required"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute ref="xml:space" use="optional"/>
+ <xsd:attribute name="category" type="xsd:string" use="optional"/>
+ <xsd:attribute name="target-language" type="xsd:language" use="optional"/>
+ <xsd:attribute name="product-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="product-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="build-num" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_group_id">
+ <xsd:selector xpath=".//xlf:group"/>
+ <xsd:field xpath="@id"/>
+ </xsd:unique>
+ <xsd:key name="K_unit_id">
+ <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>
+ <xsd:field xpath="@id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">
+ <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>
+ <xsd:field xpath="@xid"/>
+ </xsd:keyref>
+ <xsd:key name="K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:tool"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="."/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:key name="K_count-group_name">
+ <xsd:selector xpath=".//xlf:count-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:key>
+ <xsd:unique name="U_context-group_name">
+ <xsd:selector xpath=".//xlf:context-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:unique>
+ <xsd:key name="K_phase-name">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:key>
+ <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">
+ <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:keyref>
+ <xsd:unique name="U_uid">
+ <xsd:selector xpath=".//xlf:external-file"/>
+ <xsd:field xpath="@uid"/>
+ </xsd:unique>
+ </xsd:element>
+ <xsd:element name="header">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element minOccurs="0" ref="xlf:phase-group"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:tool"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="internal-file">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="form" type="xsd:string"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="external-file">
+ <xsd:complexType>
+ <xsd:attribute name="href" type="xsd:string" use="required"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ <xsd:attribute name="uid" type="xsd:NMTOKEN"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="note">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>
+ <xsd:attribute name="from" type="xsd:string" use="optional"/>
+ <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:phase"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:note"/>
+ </xsd:sequence>
+ <xsd:attribute name="phase-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="process-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="company-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute name="job-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:count"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:context"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>
+ <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="tool">
+ <xsd:complexType mixed="true">
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="tool-id" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="body">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="group">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="trans-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element minOccurs="0" ref="xlf:target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:alt-trans"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="seg-source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="target">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="alt-trans">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element maxOccurs="1" ref="xlf:target"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="origin" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="bin-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:bin-source"/>
+ <xsd:element minOccurs="0" ref="xlf:bin-target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:trans-unit"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-source">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-target">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- Element for inline codes -->
+ <xsd:element name="g">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="x">
+ <xsd:complexType>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bx">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ex">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ph">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bpt">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ept">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="it">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="sub">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mrk">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="comment" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+</xsd:schema>
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
+
+class TranslationDumperPassTest extends TestCase
+{
+ public function testProcess()
+ {
+ $container = new ContainerBuilder();
+ $writerDefinition = $container->register('translation.writer');
+ $container->register('foo.id')
+ ->addTag('translation.dumper', array('alias' => 'bar.alias'));
+
+ $translationDumperPass = new TranslationDumperPass();
+ $translationDumperPass->process($container);
+
+ $this->assertEquals(array(array('addDumper', array('bar.alias', new Reference('foo.id')))), $writerDefinition->getMethodCalls());
+ }
+
+ public function testProcessNoDefinitionFound()
+ {
+ $container = new ContainerBuilder();
+
+ $definitionsBefore = count($container->getDefinitions());
+ $aliasesBefore = count($container->getAliases());
+
+ $translationDumperPass = new TranslationDumperPass();
+ $translationDumperPass->process($container);
+
+ // the container is untouched (i.e. no new definitions or aliases)
+ $this->assertCount($definitionsBefore, $container->getDefinitions());
+ $this->assertCount($aliasesBefore, $container->getAliases());
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
+
+class TranslationExtractorPassTest extends TestCase
+{
+ public function testProcess()
+ {
+ $container = new ContainerBuilder();
+ $extractorDefinition = $container->register('translation.extractor');
+ $container->register('foo.id')
+ ->addTag('translation.extractor', array('alias' => 'bar.alias'));
+
+ $translationDumperPass = new TranslationExtractorPass();
+ $translationDumperPass->process($container);
+
+ $this->assertEquals(array(array('addExtractor', array('bar.alias', new Reference('foo.id')))), $extractorDefinition->getMethodCalls());
+ }
+
+ public function testProcessNoDefinitionFound()
+ {
+ $container = new ContainerBuilder();
+
+ $definitionsBefore = count($container->getDefinitions());
+ $aliasesBefore = count($container->getAliases());
+
+ $translationDumperPass = new TranslationExtractorPass();
+ $translationDumperPass->process($container);
+
+ // the container is untouched (i.e. no new definitions or aliases)
+ $this->assertCount($definitionsBefore, $container->getDefinitions());
+ $this->assertCount($aliasesBefore, $container->getAliases());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
+ * @expectedExceptionMessage The alias for the tag "translation.extractor" of service "foo.id" must be set.
+ */
+ public function testProcessMissingAlias()
+ {
+ $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->disableOriginalConstructor()->getMock();
+ $container = new ContainerBuilder();
+ $container->register('translation.extractor');
+ $container->register('foo.id')
+ ->addTag('translation.extractor', array());
+
+ $definition->expects($this->never())->method('addMethodCall');
+
+ $translationDumperPass = new TranslationExtractorPass();
+ $translationDumperPass->process($container);
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
+
+class TranslationPassTest extends TestCase
+{
+ public function testValidCollector()
+ {
+ $loader = (new Definition())
+ ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'));
+
+ $reader = new Definition();
+
+ $translator = (new Definition())
+ ->setArguments(array(null, null, null, null));
+
+ $container = new ContainerBuilder();
+ $container->setDefinition('translator.default', $translator);
+ $container->setDefinition('translation.reader', $reader);
+ $container->setDefinition('translation.xliff_loader', $loader);
+
+ $pass = new TranslatorPass('translator.default', 'translation.reader');
+ $pass->process($container);
+
+ $expectedReader = (new Definition())
+ ->addMethodCall('addLoader', array('xliff', new Reference('translation.xliff_loader')))
+ ->addMethodCall('addLoader', array('xlf', new Reference('translation.xliff_loader')))
+ ;
+ $this->assertEquals($expectedReader, $reader);
+
+ $expectedLoader = (new Definition())
+ ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'))
+ ;
+ $this->assertEquals($expectedLoader, $loader);
+
+ $this->assertSame(array('translation.xliff_loader' => array('xliff', 'xlf')), $translator->getArgument(3));
+
+ $expected = array('translation.xliff_loader' => new ServiceClosureArgument(new Reference('translation.xliff_loader')));
+ $this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0));
+ }
+}
$dumper->dump($catalogue, array('path' => $tempDir));
$this->assertFileExists($tempDir.'/messages.en.concrete');
- }
-
- /**
- * @group legacy
- */
- public function testDumpBackupsFileIfExisting()
- {
- $tempDir = sys_get_temp_dir();
- $file = $tempDir.'/messages.en.concrete';
- $backupFile = $file.'~';
- @touch($file);
-
- $catalogue = new MessageCatalogue('en');
- $catalogue->add(array('foo' => 'bar'));
-
- $dumper = new ConcreteFileDumper();
- $dumper->dump($catalogue, array('path' => $tempDir));
-
- $this->assertFileExists($backupFile);
-
- @unlink($file);
- @unlink($backupFile);
+ @unlink($tempDir.'/messages.en.concrete');
}
public function testDumpCreatesNestedDirectoriesAndFile()
$dumper->formatCatalogue($catalogue, 'messages', array('default_locale' => 'fr_FR'))
);
}
+
+ public function testFormatCatalogueWithNotesMetadata()
+ {
+ $catalogue = new MessageCatalogue('en_US');
+ $catalogue->add(array(
+ 'foo' => 'bar',
+ 'baz' => 'biz',
+ ));
+ $catalogue->setMetadata('foo', array('notes' => array(
+ array('category' => 'state', 'content' => 'new'),
+ array('category' => 'approved', 'content' => 'true'),
+ array('category' => 'section', 'content' => 'user login', 'priority' => '1'),
+ )));
+ $catalogue->setMetadata('baz', array('notes' => array(
+ array('id' => 'x', 'content' => 'x_content'),
+ array('appliesTo' => 'target', 'category' => 'quality', 'content' => 'Fuzzy'),
+ )));
+
+ $dumper = new XliffFileDumper();
+
+ $this->assertStringEqualsFile(
+ __DIR__.'/../fixtures/resources-notes-meta.xlf',
+ $dumper->formatCatalogue($catalogue, 'messages', array('default_locale' => 'fr_FR', 'xliff_version' => '2.0'))
+ );
+ }
}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Extractor;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Translation\Extractor\PhpExtractor;
+use Symfony\Component\Translation\MessageCatalogue;
+
+class PhpExtractorTest extends TestCase
+{
+ /**
+ * @dataProvider resourcesProvider
+ *
+ * @param array|string $resource
+ */
+ public function testExtraction($resource)
+ {
+ // Arrange
+ $extractor = new PhpExtractor();
+ $extractor->setPrefix('prefix');
+ $catalogue = new MessageCatalogue('en');
+
+ // Act
+ $extractor->extract($resource, $catalogue);
+
+ $expectedHeredoc = <<<EOF
+heredoc key with whitespace and escaped \$\n sequences
+EOF;
+ $expectedNowdoc = <<<'EOF'
+nowdoc key with whitespace and nonescaped \$\n sequences
+EOF;
+ // Assert
+ $expectedCatalogue = array(
+ 'messages' => array(
+ 'single-quoted key' => 'prefixsingle-quoted key',
+ 'double-quoted key' => 'prefixdouble-quoted key',
+ 'heredoc key' => 'prefixheredoc key',
+ 'nowdoc key' => 'prefixnowdoc key',
+ "double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixdouble-quoted key with whitespace and escaped \$\n\" sequences",
+ 'single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixsingle-quoted key with whitespace and nonescaped \$\n\' sequences',
+ 'single-quoted key with "quote mark at the end"' => 'prefixsingle-quoted key with "quote mark at the end"',
+ $expectedHeredoc => 'prefix'.$expectedHeredoc,
+ $expectedNowdoc => 'prefix'.$expectedNowdoc,
+ '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples' => 'prefix{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples',
+ ),
+ 'not_messages' => array(
+ 'other-domain-test-no-params-short-array' => 'prefixother-domain-test-no-params-short-array',
+ 'other-domain-test-no-params-long-array' => 'prefixother-domain-test-no-params-long-array',
+ 'other-domain-test-params-short-array' => 'prefixother-domain-test-params-short-array',
+ 'other-domain-test-params-long-array' => 'prefixother-domain-test-params-long-array',
+ 'other-domain-test-trans-choice-short-array-%count%' => 'prefixother-domain-test-trans-choice-short-array-%count%',
+ 'other-domain-test-trans-choice-long-array-%count%' => 'prefixother-domain-test-trans-choice-long-array-%count%',
+ 'typecast' => 'prefixtypecast',
+ 'msg1' => 'prefixmsg1',
+ 'msg2' => 'prefixmsg2',
+ ),
+ );
+ $actualCatalogue = $catalogue->all();
+
+ $this->assertEquals($expectedCatalogue, $actualCatalogue);
+ }
+
+ public function resourcesProvider()
+ {
+ $directory = __DIR__.'/../fixtures/extractor/';
+ $splFiles = array();
+ foreach (new \DirectoryIterator($directory) as $fileInfo) {
+ if ($fileInfo->isDot()) {
+ continue;
+ }
+ if ('translation.html.php' === $fileInfo->getBasename()) {
+ $phpFile = $fileInfo->getPathname();
+ }
+ $splFiles[] = $fileInfo->getFileInfo();
+ }
+
+ return array(
+ array($directory),
+ array($phpFile),
+ array(glob($directory.'*')),
+ array($splFiles),
+ array(new \ArrayObject(glob($directory.'*'))),
+ array(new \ArrayObject($splFiles)),
+ );
+ }
+}
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Formatter;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
+
+class MessageFormatterTest extends TestCase
+{
+ /**
+ * @dataProvider getTransMessages
+ */
+ public function testFormat($expected, $message, $parameters = array())
+ {
+ $this->assertEquals($expected, $this->getMessageFormatter()->format($message, 'en', $parameters));
+ }
+
+ /**
+ * @dataProvider getTransChoiceMessages
+ */
+ public function testFormatPlural($expected, $message, $number, $parameters)
+ {
+ $this->assertEquals($expected, $this->getMessageFormatter()->choiceFormat($message, $number, 'fr', $parameters));
+ }
+
+ public function getTransMessages()
+ {
+ return array(
+ array(
+ 'There is one apple',
+ 'There is one apple',
+ ),
+ array(
+ 'There are 5 apples',
+ 'There are %count% apples',
+ array('%count%' => 5),
+ ),
+ array(
+ 'There are 5 apples',
+ 'There are {{count}} apples',
+ array('{{count}}' => 5),
+ ),
+ );
+ }
+
+ public function getTransChoiceMessages()
+ {
+ return array(
+ array('Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il y a 0 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', 'Il y a %count% pomme|Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il y a 0 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il n\'y a aucune pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0)),
+ );
+ }
+
+ private function getMessageFormatter()
+ {
+ return new MessageFormatter();
+ }
+}
// target attributes
$this->assertEquals(array('target-attributes' => array('order' => 1)), $catalogue->getMetadata('bar', 'domain1'));
}
+
+ public function testLoadVersion2WithNoteMeta()
+ {
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/resources-notes-meta.xlf';
+ $catalogue = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertEquals('en', $catalogue->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
+ $this->assertSame(array(), libxml_get_errors());
+
+ // test for "foo" metadata
+ $this->assertTrue($catalogue->defines('foo', 'domain1'));
+ $metadata = $catalogue->getMetadata('foo', 'domain1');
+ $this->assertNotEmpty($metadata);
+ $this->assertCount(3, $metadata['notes']);
+
+ $this->assertEquals('state', $metadata['notes'][0]['category']);
+ $this->assertEquals('new', $metadata['notes'][0]['content']);
+
+ $this->assertEquals('approved', $metadata['notes'][1]['category']);
+ $this->assertEquals('true', $metadata['notes'][1]['content']);
+
+ $this->assertEquals('section', $metadata['notes'][2]['category']);
+ $this->assertEquals('1', $metadata['notes'][2]['priority']);
+ $this->assertEquals('user login', $metadata['notes'][2]['content']);
+
+ // test for "baz" metadata
+ $this->assertTrue($catalogue->defines('baz', 'domain1'));
+ $metadata = $catalogue->getMetadata('baz', 'domain1');
+ $this->assertNotEmpty($metadata);
+ $this->assertCount(2, $metadata['notes']);
+
+ $this->assertEquals('x', $metadata['notes'][0]['id']);
+ $this->assertEquals('x_content', $metadata['notes'][0]['content']);
+
+ $this->assertEquals('target', $metadata['notes'][1]['appliesTo']);
+ $this->assertEquals('quality', $metadata['notes'][1]['category']);
+ $this->assertEquals('Fuzzy', $metadata['notes'][1]['content']);
+ }
+
+ public function testLoadVersion2WithMultiSegmentUnit()
+ {
+ $loader = new XliffFileLoader();
+ $resource = __DIR__.'/../fixtures/resources-2.0-multi-segment-unit.xlf';
+ $catalog = $loader->load($resource, 'en', 'domain1');
+
+ $this->assertSame('en', $catalog->getLocale());
+ $this->assertEquals(array(new FileResource($resource)), $catalog->getResources());
+ $this->assertFalse(libxml_get_last_error());
+
+ // test for "foo" metadata
+ $this->assertTrue($catalog->defines('foo', 'domain1'));
+ $metadata = $catalog->getMetadata('foo', 'domain1');
+ $this->assertNotEmpty($metadata);
+ $this->assertCount(1, $metadata['notes']);
+
+ $this->assertSame('processed', $metadata['notes'][0]['category']);
+ $this->assertSame('true', $metadata['notes'][0]['content']);
+
+ // test for "bar" metadata
+ $this->assertTrue($catalog->defines('bar', 'domain1'));
+ $metadata = $catalog->getMetadata('bar', 'domain1');
+ $this->assertNotEmpty($metadata);
+ $this->assertCount(1, $metadata['notes']);
+
+ $this->assertSame('processed', $metadata['notes'][0]['category']);
+ $this->assertSame('true', $metadata['notes'][0]['content']);
+ }
}
array("This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1),
// esacape pipe
array('This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0),
+ // Empty plural set (2 plural forms) from a .PO file
+ array('', '|', 1),
+ // Empty plural set (3 plural forms) from a .PO file
+ array('', '||', 1),
);
}
}
/**
* We validate only on the plural coverage. Thus the real rules is not tested.
*
- * @param string $nplural plural expected
- * @param array $matrix containing langcodes and their plural index values
+ * @param string $nplural Plural expected
+ * @param array $matrix Containing langcodes and their plural index values
* @param bool $expectSuccess
*/
protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\Translator;
-use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\MessageCatalogue;
*/
public function testConstructorInvalidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ new Translator($locale);
}
/**
*/
public function testConstructorValidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$this->assertEquals($locale, $translator->getLocale());
}
public function testConstructorWithoutLocale()
{
- $translator = new Translator(null, new MessageSelector());
+ $translator = new Translator(null);
$this->assertNull($translator->getLocale());
}
*/
public function testSetInvalidLocale($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->setLocale($locale);
}
*/
public function testSetValidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$translator->setLocale($locale);
$this->assertEquals($locale, $translator->getLocale());
*/
public function testSetFallbackInvalidLocales($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->setFallbackLocales(array('fr', $locale));
}
*/
public function testSetFallbackValidLocales($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$translator->setFallbackLocales(array('fr', $locale));
// no assertion. this method just asserts that no exception is thrown
$this->addToAssertionCount(1);
*/
public function testAddResourceInvalidLocales($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
}
*/
public function testAddResourceValidLocales($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
// no assertion. this method just asserts that no exception is thrown
$this->addToAssertionCount(1);
public function testFallbackCatalogueResources()
{
- $translator = new Translator('en_GB', new MessageSelector());
+ $translator = new Translator('en_GB');
$translator->addLoader('yml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
$translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB');
$translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en');
*/
public function testTransInvalidLocale($locale)
{
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
*/
public function testTransValidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('test' => 'OK'), $locale);
*/
public function testTransChoiceInvalidLocale($locale)
{
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
*/
public function testTransChoiceValidLocale($locale)
{
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
class TranslationWriterTest extends TestCase
{
- public function testWriteTranslations()
+ public function testWrite()
{
$dumper = $this->getMockBuilder('Symfony\Component\Translation\Dumper\DumperInterface')->getMock();
$dumper
$writer = new TranslationWriter();
$writer->addDumper('test', $dumper);
- $writer->writeTranslations(new MessageCatalogue(array()), 'test');
+ $writer->write(new MessageCatalogue('en'), 'test');
}
public function testDisableBackup()
--- /dev/null
+This template is used for translation message extraction tests
+<?php echo $view['translator']->trans('single-quoted key'); ?>
+<?php echo $view['translator']->trans('double-quoted key'); ?>
+<?php echo $view['translator']->trans(<<<'EOF'
+heredoc key
+EOF
+); ?>
+<?php echo $view['translator']->trans(<<<'EOF'
+nowdoc key
+EOF
+); ?>
+<?php echo $view['translator']->trans(
+ "double-quoted key with whitespace and escaped \$\n\" sequences"
+); ?>
+<?php echo $view['translator']->trans(
+ 'single-quoted key with whitespace and nonescaped \$\n\' sequences'
+); ?>
+<?php echo $view['translator']->trans(<<<EOF
+heredoc key with whitespace and escaped \$\n sequences
+EOF
+); ?>
+<?php echo $view['translator']->trans(<<<'EOF'
+nowdoc key with whitespace and nonescaped \$\n sequences
+EOF
+); ?>
+
+<?php echo $view['translator']->trans('single-quoted key with "quote mark at the end"'); ?>
+
+<?php echo $view['translator']->transChoice(
+ '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples',
+ 10,
+ array('%count%' => 10)
+); ?>
+
+<?php echo $view['translator']->trans('other-domain-test-no-params-short-array', array(), 'not_messages'); ?>
+
+<?php echo $view['translator']->trans('other-domain-test-no-params-long-array', array(), 'not_messages'); ?>
+
+<?php echo $view['translator']->trans('other-domain-test-params-short-array', array('foo' => 'bar'), 'not_messages'); ?>
+
+<?php echo $view['translator']->trans('other-domain-test-params-long-array', array('foo' => 'bar'), 'not_messages'); ?>
+
+<?php echo $view['translator']->transChoice('other-domain-test-trans-choice-short-array-%count%', 10, array('%count%' => 10), 'not_messages'); ?>
+
+<?php echo $view['translator']->transChoice('other-domain-test-trans-choice-long-array-%count%', 10, array('%count%' => 10), 'not_messages'); ?>
+
+<?php echo $view['translator']->trans('typecast', array('a' => (int) '123'), 'not_messages'); ?>
+<?php echo $view['translator']->transChoice('msg1', 10 + 1, array(), 'not_messages'); ?>
+<?php echo $view['translator']->transChoice('msg2', ceil(4.5), array(), 'not_messages'); ?>
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="fr-FR" trgLang="en-US">
<file id="messages.en_US">
- <unit id="acbd18db4cc2f85cedef654fccc4a4d8">
+ <unit id="LCa0a2j">
<segment>
<source>foo</source>
<target>bar</target>
</segment>
</unit>
- <unit id="3c6e0b8a9c15224a8228b9a98ca1531d">
+ <unit id="LHDhK3o">
<segment>
<source>key</source>
<target order="1"></target>
</segment>
</unit>
- <unit id="18e6a493872558d949b4c16ea1fa6ab6">
+ <unit id="2DA_bnh">
<segment>
<source>key.with.cdata</source>
<target><![CDATA[<source> & <target>]]></target>
--- /dev/null
+<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en-US" trgLang="en-US">
+ <file id="f1">
+ <unit id="1">
+ <notes>
+ <note category="processed">true</note>
+ </notes>
+ <segment id="id-foo">
+ <source>foo</source>
+ <target>foo (translated)</target>
+ </segment>
+ <segment id="id-bar">
+ <source>bar</source>
+ <target>bar (translated)</target>
+ </segment>
+ </unit>
+ </file>
+</xliff>
<tool tool-id="symfony" tool-name="Symfony"/>
</header>
<body>
- <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
+ <trans-unit id="LCa0a2j" resname="foo">
<source>foo</source>
<target>bar</target>
<note priority="1" from="bar">baz</note>
</trans-unit>
- <trans-unit id="3c6e0b8a9c15224a8228b9a98ca1531d" resname="key">
+ <trans-unit id="LHDhK3o" resname="key">
<source>key</source>
<target></target>
<note>baz</note>
<note>qux</note>
</trans-unit>
- <trans-unit id="18e6a493872558d949b4c16ea1fa6ab6" resname="key.with.cdata">
+ <trans-unit id="2DA_bnh" resname="key.with.cdata">
<source>key.with.cdata</source>
<target><![CDATA[<source> & <target>]]></target>
</trans-unit>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="fr-FR" trgLang="en-US">
+ <file id="messages.en_US">
+ <unit id="LCa0a2j">
+ <notes>
+ <note category="state">new</note>
+ <note category="approved">true</note>
+ <note category="section" priority="1">user login</note>
+ </notes>
+ <segment>
+ <source>foo</source>
+ <target>bar</target>
+ </segment>
+ </unit>
+ <unit id="uqWglk0">
+ <notes>
+ <note id="x">x_content</note>
+ <note appliesTo="target" category="quality">Fuzzy</note>
+ </notes>
+ <segment>
+ <source>baz</source>
+ <target>biz</target>
+ </segment>
+ </unit>
+ </file>
+</xliff>
<tool tool-id="symfony" tool-name="Symfony"/>
</header>
<body>
- <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
+ <trans-unit id="LCa0a2j" resname="foo">
<source>foo</source>
<target state="needs-translation">bar</target>
</trans-unit>
<tool tool-id="foo" tool-name="foo" tool-version="0.0" tool-company="Foo"/>
</header>
<body>
- <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
+ <trans-unit id="LCa0a2j" resname="foo">
<source>foo</source>
<target>bar</target>
</trans-unit>
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Config\ConfigCacheInterface;
use Symfony\Component\Config\ConfigCacheFactoryInterface;
use Symfony\Component\Config\ConfigCacheFactory;
+use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
+use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
/**
- * Translator.
- *
* @author Fabien Potencier <fabien@symfony.com>
*/
class Translator implements TranslatorInterface, TranslatorBagInterface
private $resources = array();
/**
- * @var MessageSelector
+ * @var MessageFormatterInterface
*/
- private $selector;
+ private $formatter;
/**
* @var string
private $configCacheFactory;
/**
- * Constructor.
- *
- * @param string $locale The locale
- * @param MessageSelector|null $selector The message selector for pluralization
- * @param string|null $cacheDir The directory to use for the cache
- * @param bool $debug Use cache in debug mode ?
- *
* @throws InvalidArgumentException If a locale contains invalid characters
*/
- public function __construct($locale, MessageSelector $selector = null, $cacheDir = null, $debug = false)
+ public function __construct(?string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false)
{
$this->setLocale($locale);
- $this->selector = $selector ?: new MessageSelector();
+
+ if (null === $formatter) {
+ $formatter = new MessageFormatter();
+ }
+
+ $this->formatter = $formatter;
$this->cacheDir = $cacheDir;
$this->debug = $debug;
}
- /**
- * Sets the ConfigCache factory to use.
- *
- * @param ConfigCacheFactoryInterface $configCacheFactory
- */
public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
{
$this->configCacheFactory = $configCacheFactory;
$domain = 'messages';
}
- return strtr($this->getCatalogue($locale)->get((string) $id, $domain), $parameters);
+ return $this->formatter->format($this->getCatalogue($locale)->get((string) $id, $domain), $locale, $parameters);
}
/**
*/
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
{
- $parameters = array_merge(array(
- '%count%' => $number,
- ), $parameters);
+ if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
+ throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', get_class($this->formatter)));
+ }
if (null === $domain) {
$domain = 'messages';
}
}
- return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters);
+ return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters);
}
/**
$this->loadFallbackCatalogues($locale);
}
- /**
- * @param string $locale
- */
- private function initializeCacheCatalogue($locale)
+ private function initializeCacheCatalogue(string $locale): void
{
if (isset($this->catalogues[$locale])) {
/* Catalogue already initialized. */
$this->catalogues[$locale] = include $cache->getPath();
}
- private function dumpCatalogue($locale, ConfigCacheInterface $cache)
+ private function dumpCatalogue($locale, ConfigCacheInterface $cache): void
{
$this->initializeCatalogue($locale);
$fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
$cache->write($content, $this->catalogues[$locale]->getResources());
}
- private function getFallbackContent(MessageCatalogue $catalogue)
+ private function getFallbackContent(MessageCatalogue $catalogue): string
{
$fallbackContent = '';
$current = '';
private function getCatalogueCachePath($locale)
{
- return $this->cacheDir.'/catalogue.'.$locale.'.'.sha1(serialize($this->fallbackLocales)).'.php';
+ return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->fallbackLocales), true)), 0, 7), '/', '_').'.php';
}
- private function doLoadCatalogue($locale)
+ private function doLoadCatalogue($locale): void
{
$this->catalogues[$locale] = new MessageCatalogue($locale);
}
}
- private function loadFallbackCatalogues($locale)
+ private function loadFallbackCatalogues($locale): void
{
$current = $this->catalogues[$locale];
$locales[] = $fallback;
}
- if (strrchr($locale, '_') !== false) {
+ if (false !== strrchr($locale, '_')) {
array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_'))));
}
/**
* Provides the ConfigCache factory implementation, falling back to a
* default implementation if necessary.
- *
- * @return ConfigCacheFactoryInterface $configCacheFactory
*/
- private function getConfigCacheFactory()
+ private function getConfigCacheFactory(): ConfigCacheFactoryInterface
{
if (!$this->configCacheFactory) {
$this->configCacheFactory = new ConfigCacheFactory($this->debug);
*
* @author Michel Salib <michelsalib@hotmail.com>
*/
-class TranslationWriter
+class TranslationWriter implements TranslationWriterInterface
{
- /**
- * Dumpers used for export.
- *
- * @var array
- */
private $dumpers = array();
/**
*/
public function disableBackup()
{
+ // to be deprecated in 4.1
foreach ($this->dumpers as $dumper) {
if (method_exists($dumper, 'setBackup')) {
$dumper->setBackup(false);
/**
* Writes translation from the catalogue according to the selected format.
*
- * @param MessageCatalogue $catalogue The message catalogue to dump
+ * @param MessageCatalogue $catalogue The message catalogue to write
* @param string $format The format to use to dump the messages
* @param array $options Options that are passed to the dumper
*
* @throws InvalidArgumentException
*/
- public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array())
+ public function write(MessageCatalogue $catalogue, $format, $options = array())
{
if (!isset($this->dumpers[$format])) {
throw new InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format));
--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Writer;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationWriter writes translation messages.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface TranslationWriterInterface
+{
+ /**
+ * Writes translation from the catalogue according to the selected format.
+ *
+ * @param MessageCatalogue $catalogue The message catalogue to write
+ * @param string $format The format to use to dump the messages
+ * @param array $options Options that are passed to the dumper
+ *
+ * @throws InvalidArgumentException
+ */
+ public function write(MessageCatalogue $catalogue, $format, $options = array());
+}
}
],
"require": {
- "php": ">=5.5.9",
+ "php": "^7.1.3",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
- "symfony/config": "~2.8|~3.0",
- "symfony/intl": "^2.8.18|^3.2.5",
- "symfony/yaml": "~3.3",
+ "symfony/config": "~3.4|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/intl": "~3.4|~4.0",
+ "symfony/yaml": "~3.4|~4.0",
+ "symfony/finder": "~2.8|~3.0|~4.0",
"psr/log": "~1.0"
},
"conflict": {
- "symfony/config": "<2.8",
- "symfony/yaml": "<3.3"
+ "symfony/config": "<3.4",
+ "symfony/dependency-injection": "<3.4",
+ "symfony/yaml": "<3.4"
},
"suggest": {
"symfony/config": "",
"symfony/yaml": "",
- "psr/log": "To use logging capability in translator"
+ "psr/log-implementation": "To use logging capability in translator"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Translation\\": "" },
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "4.0-dev"
}
}
}
CHANGELOG
=========
+3.4.0
+-----
+
+ * added support for parsing YAML files using the `Yaml::parseFile()` or `Parser::parseFile()` method
+
+ * the `Dumper`, `Parser`, and `Yaml` classes are marked as final
+
+ * Deprecated the `!php/object:` tag which will be replaced by the
+ `!php/object` tag (without the colon) in 4.0.
+
+ * Deprecated the `!php/const:` tag which will be replaced by the
+ `!php/const` tag (without the colon) in 4.0.
+
+ * Support for the `!str` tag is deprecated, use the `!!str` tag instead.
+
+ * Deprecated using the non-specific tag `!` as its behavior will change in 4.0.
+ It will force non-evaluating your values in 4.0. Use plain integers or `!!float` instead.
+
3.3.0
-----
*/
class LintCommand extends Command
{
+ protected static $defaultName = 'lint:yaml';
+
private $parser;
private $format;
private $displayCorrectFiles;
protected function configure()
{
$this
- ->setName('lint:yaml')
->setDescription('Lints a file and outputs encountered errors')
->addArgument('filename', null, 'A file or a directory or STDIN')
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
+ ->addOption('parse-tags', null, InputOption::VALUE_NONE, 'Parse custom tags')
->setHelp(<<<EOF
The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
the first encountered syntax error.
$filename = $input->getArgument('filename');
$this->format = $input->getOption('format');
$this->displayCorrectFiles = $output->isVerbose();
+ $flags = $input->getOption('parse-tags') ? Yaml::PARSE_CUSTOM_TAGS : 0;
if (!$filename) {
if (!$stdin = $this->getStdin()) {
throw new \RuntimeException('Please provide a filename or pipe file content to STDIN.');
}
- return $this->display($io, array($this->validate($stdin)));
+ return $this->display($io, array($this->validate($stdin, $flags)));
}
if (!$this->isReadable($filename)) {
$filesInfo = array();
foreach ($this->getFiles($filename) as $file) {
- $filesInfo[] = $this->validate(file_get_contents($file), $file);
+ $filesInfo[] = $this->validate(file_get_contents($file), $flags, $file);
}
return $this->display($io, $filesInfo);
}
- private function validate($content, $file = null)
+ private function validate($content, $flags, $file = null)
{
$prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) {
if (E_USER_DEPRECATED === $level) {
- throw new ParseException($message);
+ throw new ParseException($message, $this->getParser()->getRealCurrentLineNb() + 1);
}
return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false;
});
try {
- $this->getParser()->parse($content, Yaml::PARSE_CONSTANT);
+ $this->getParser()->parse($content, Yaml::PARSE_CONSTANT | $flags);
} catch (ParseException $e) {
- return array('file' => $file, 'valid' => false, 'message' => $e->getMessage());
+ return array('file' => $file, 'line' => $e->getParsedLine(), 'valid' => false, 'message' => $e->getMessage());
} finally {
restore_error_handler();
}
}
}
- if ($erroredFiles === 0) {
+ if (0 === $erroredFiles) {
$io->success(sprintf('All %d YAML files contain valid syntax.', $countFiles));
} else {
$io->warning(sprintf('%d YAML files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
* Dumper dumps PHP variables to YAML strings.
*
* @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @final since version 3.4
*/
class Dumper
{
*/
public function setIndentation($num)
{
- @trigger_error('The '.__METHOD__.' method is deprecated since version 3.1 and will be removed in 4.0. Pass the indentation to the constructor instead.', E_USER_DEPRECATED);
+ @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 3.1 and will be removed in 4.0. Pass the indentation to the constructor instead.', E_USER_DEPRECATED);
$this->indentation = (int) $num;
}
public function dump($input, $inline = 0, $indent = 0, $flags = 0)
{
if (is_bool($flags)) {
- @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
if ($flags) {
$flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE;
}
if (func_num_args() >= 5) {
- @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
if (func_get_arg(4)) {
$flags |= Yaml::DUMP_OBJECT;
$dumpAsMap = Inline::isHash($input);
foreach ($input as $key => $value) {
- if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && is_string($value) && false !== strpos($value, "\n")) {
- $output .= sprintf("%s%s%s |\n", $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '');
+ if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r\n")) {
+ // If the first line starts with a space character, the spec requires a blockIndicationIndicator
+ // http://www.yaml.org/spec/1.2/spec.html#id2793979
+ $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : '';
+ $output .= sprintf("%s%s%s |%s\n", $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator);
foreach (preg_split('/\n|\r\n/', $value) as $row) {
$output .= sprintf("%s%s%s\n", $prefix, str_repeat(' ', $this->indentation), $row);
private $rawMessage;
/**
- * Constructor.
- *
* @param string $message The error message
* @param int $parsedLine The line where the error occurred
* @param string|null $snippet The snippet of code near the problem
{
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+)"|\'([^\']*+(?:\'\'[^\']*+)*+)\')';
- public static $parsedLineNumber;
+ public static $parsedLineNumber = -1;
+ public static $parsedFilename;
private static $exceptionOnInvalidType = false;
private static $objectSupport = false;
private static $objectForMap = false;
private static $constantSupport = false;
+ /**
+ * @param int $flags
+ * @param int|null $parsedLineNumber
+ * @param string|null $parsedFilename
+ */
+ public static function initialize($flags, $parsedLineNumber = null, $parsedFilename = null)
+ {
+ self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags);
+ self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags);
+ self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
+ self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags);
+ self::$parsedFilename = $parsedFilename;
+
+ if (null !== $parsedLineNumber) {
+ self::$parsedLineNumber = $parsedLineNumber;
+ }
+ }
+
/**
* Converts a YAML string to a PHP value.
*
public static function parse($value, $flags = 0, $references = array())
{
if (is_bool($flags)) {
- @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
if ($flags) {
$flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE;
}
if (func_num_args() >= 3 && !is_array($references)) {
- @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
if ($references) {
$flags |= Yaml::PARSE_OBJECT;
}
if (func_num_args() >= 4) {
- @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
if (func_get_arg(3)) {
$flags |= Yaml::PARSE_OBJECT_FOR_MAP;
}
}
- self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags);
- self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags);
- self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
- self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags);
+ self::initialize($flags);
$value = trim($value);
// some comments are allowed at the end
if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) {
- throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)));
+ throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
}
if (isset($mbEncoding)) {
public static function dump($value, $flags = 0)
{
if (is_bool($flags)) {
- @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
if ($flags) {
$flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE;
}
if (func_num_args() >= 3) {
- @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
if (func_get_arg(2)) {
$flags |= Yaml::DUMP_OBJECT;
}
if (Yaml::DUMP_OBJECT & $flags) {
- return '!php/object:'.serialize($value);
+ return '!php/object '.self::dump(serialize($value));
}
if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) {
if (null !== $delimiters) {
$tmp = ltrim(substr($scalar, $i), ' ');
+ if ('' === $tmp) {
+ throw new ParseException(sprintf('Unexpected end of line, expected one of "%s".', implode($delimiters)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
+ }
if (!in_array($tmp[0], $delimiters)) {
- throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)));
+ throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
}
} else {
$output = $match[1];
$i += strlen($output);
} else {
- throw new ParseException(sprintf('Malformed inline YAML string: %s.', $scalar));
+ throw new ParseException(sprintf('Malformed inline YAML string: %s.', $scalar), self::$parsedLineNumber + 1, null, self::$parsedFilename);
}
// a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >)
if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0])) {
- throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0]));
+ throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0]), self::$parsedLineNumber + 1, $output, self::$parsedFilename);
}
if ($output && '%' === $output[0]) {
- @trigger_error(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output), E_USER_DEPRECATED);
+ @trigger_error(self::getDeprecationMessage(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output)), E_USER_DEPRECATED);
}
if ($evaluate) {
private static function parseQuotedScalar($scalar, &$i)
{
if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) {
- throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i)));
+ throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
$output = substr($match[0], 1, strlen($match[0]) - 2);
++$i;
}
- throw new ParseException(sprintf('Malformed inline YAML string: %s.', $sequence));
+ throw new ParseException(sprintf('Malformed inline YAML string: %s.', $sequence), self::$parsedLineNumber + 1, null, self::$parsedFilename);
}
/**
$output = array();
$len = strlen($mapping);
++$i;
+ $allowOverwrite = false;
// {foo: bar, bar:foo, ...}
while ($i < $len) {
}
if (':' === $key) {
- @trigger_error('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.', E_USER_DEPRECATED);
+ @trigger_error(self::getDeprecationMessage('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.'), E_USER_DEPRECATED);
}
- if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags)) {
+ if (!$isKeyQuoted) {
$evaluatedKey = self::evaluateScalar($key, $flags, $references);
if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) {
- @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', E_USER_DEPRECATED);
+ @trigger_error(self::getDeprecationMessage('Implicit casting of incompatible mapping keys to strings is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.'), E_USER_DEPRECATED);
}
}
if (':' !== $key && !$isKeyQuoted && (!isset($mapping[$i + 1]) || !in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true))) {
- @trigger_error('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0.', E_USER_DEPRECATED);
+ @trigger_error(self::getDeprecationMessage('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since Symfony 3.2 and will throw a ParseException in 4.0.'), E_USER_DEPRECATED);
+ }
+
+ if ('<<' === $key) {
+ $allowOverwrite = true;
}
while ($i < $len) {
}
$tag = self::parseTag($mapping, $i, $flags);
- $duplicate = false;
switch ($mapping[$i]) {
case '[':
// nested sequence
// Spec: Keys MUST be unique; first one wins.
// Parser cannot abort this mapping earlier, since lines
// are processed sequentially.
- if (isset($output[$key])) {
- @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
- $duplicate = true;
+ // But overwriting is allowed when a merge node is used in current block.
+ if ('<<' === $key) {
+ foreach ($value as $parsedValue) {
+ $output += $parsedValue;
+ }
+ } elseif ($allowOverwrite || !isset($output[$key])) {
+ if (null !== $tag) {
+ $output[$key] = new TaggedValue($tag, $value);
+ } else {
+ $output[$key] = $value;
+ }
+ } elseif (isset($output[$key])) {
+ @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED);
}
break;
case '{':
// Spec: Keys MUST be unique; first one wins.
// Parser cannot abort this mapping earlier, since lines
// are processed sequentially.
- if (isset($output[$key])) {
- @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
- $duplicate = true;
+ // But overwriting is allowed when a merge node is used in current block.
+ if ('<<' === $key) {
+ $output += $value;
+ } elseif ($allowOverwrite || !isset($output[$key])) {
+ if (null !== $tag) {
+ $output[$key] = new TaggedValue($tag, $value);
+ } else {
+ $output[$key] = $value;
+ }
+ } elseif (isset($output[$key])) {
+ @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED);
}
break;
default:
// Spec: Keys MUST be unique; first one wins.
// Parser cannot abort this mapping earlier, since lines
// are processed sequentially.
- if (isset($output[$key])) {
- @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
- $duplicate = true;
+ // But overwriting is allowed when a merge node is used in current block.
+ if ('<<' === $key) {
+ $output += $value;
+ } elseif ($allowOverwrite || !isset($output[$key])) {
+ if (null !== $tag) {
+ $output[$key] = new TaggedValue($tag, $value);
+ } else {
+ $output[$key] = $value;
+ }
+ } elseif (isset($output[$key])) {
+ @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED);
}
--$i;
}
-
- if (!$duplicate) {
- if (null !== $tag) {
- $output[$key] = new TaggedValue($tag, $value);
- } else {
- $output[$key] = $value;
- }
- }
++$i;
continue 2;
}
}
- throw new ParseException(sprintf('Malformed inline YAML string: %s.', $mapping));
+ throw new ParseException(sprintf('Malformed inline YAML string: %s.', $mapping), self::$parsedLineNumber + 1, null, self::$parsedFilename);
}
/**
// an unquoted *
if (false === $value || '' === $value) {
- throw new ParseException('A reference must contain at least one character.');
+ throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber + 1, $value, self::$parsedFilename);
}
if (!array_key_exists($value, $references)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $value));
+ throw new ParseException(sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
}
return $references[$value];
return true;
case 'false' === $scalarLower:
return false;
- case $scalar[0] === '!':
+ case '!' === $scalar[0]:
switch (true) {
case 0 === strpos($scalar, '!str'):
+ @trigger_error(self::getDeprecationMessage('Support for the !str tag is deprecated since Symfony 3.4. Use the !!str tag instead.'), E_USER_DEPRECATED);
+
return (string) substr($scalar, 5);
+ case 0 === strpos($scalar, '!!str '):
+ return (string) substr($scalar, 6);
case 0 === strpos($scalar, '! '):
+ @trigger_error(self::getDeprecationMessage('Using the non-specific tag "!" is deprecated since Symfony 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.'), E_USER_DEPRECATED);
+
return (int) self::parseScalar(substr($scalar, 2), $flags);
case 0 === strpos($scalar, '!php/object:'):
if (self::$objectSupport) {
+ @trigger_error(self::getDeprecationMessage('The !php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED);
+
return unserialize(substr($scalar, 12));
}
if (self::$exceptionOnInvalidType) {
- throw new ParseException('Object support when parsing a YAML file has been disabled.');
+ throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
return;
case 0 === strpos($scalar, '!!php/object:'):
if (self::$objectSupport) {
- @trigger_error('The !!php/object tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object tag instead.', E_USER_DEPRECATED);
+ @trigger_error(self::getDeprecationMessage('The !!php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED);
return unserialize(substr($scalar, 13));
}
if (self::$exceptionOnInvalidType) {
- throw new ParseException('Object support when parsing a YAML file has been disabled.');
+ throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
+ }
+
+ return;
+ case 0 === strpos($scalar, '!php/object'):
+ if (self::$objectSupport) {
+ return unserialize(self::parseScalar(substr($scalar, 12)));
+ }
+
+ if (self::$exceptionOnInvalidType) {
+ throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
return;
case 0 === strpos($scalar, '!php/const:'):
if (self::$constantSupport) {
+ @trigger_error(self::getDeprecationMessage('The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.'), E_USER_DEPRECATED);
+
if (defined($const = substr($scalar, 11))) {
return constant($const);
}
- throw new ParseException(sprintf('The constant "%s" is not defined.', $const));
+ throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
+ }
+ if (self::$exceptionOnInvalidType) {
+ throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
+ }
+
+ return;
+ case 0 === strpos($scalar, '!php/const'):
+ if (self::$constantSupport) {
+ $i = 0;
+ if (defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, false))) {
+ return constant($const);
+ }
+
+ throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
if (self::$exceptionOnInvalidType) {
- throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar));
+ throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
return;
case 0 === strpos($scalar, '!!binary '):
return self::evaluateBinaryScalar(substr($scalar, 9));
default:
- @trigger_error(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar), E_USER_DEPRECATED);
+ @trigger_error(self::getDeprecationMessage(sprintf('Using the unquoted scalar value "%s" is deprecated since Symfony 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar)), E_USER_DEPRECATED);
}
// Optimize for returning strings.
- case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || is_numeric($scalar[0]):
+ // no break
+ case '+' === $scalar[0] || '-' === $scalar[0] || '.' === $scalar[0] || is_numeric($scalar[0]):
switch (true) {
case Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar):
$scalar = str_replace('_', '', (string) $scalar);
// omitting the break / return as integers are handled in the next case
+ // no break
case ctype_digit($scalar):
$raw = $scalar;
$cast = (int) $scalar;
case Parser::preg_match('/^(-|\+)?[0-9][0-9,]*(\.[0-9_]+)?$/', $scalar):
case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar):
if (false !== strpos($scalar, ',')) {
- @trigger_error('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED);
+ @trigger_error(self::getDeprecationMessage('Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0.'), E_USER_DEPRECATED);
}
return (float) str_replace(array(',', '_'), '', $scalar);
$nextOffset += strspn($value, ' ', $nextOffset);
// Is followed by a scalar
- if (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) {
- // Manage scalars in {@link self::evaluateScalar()}
+ if ((!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && 'tagged' !== $tag) {
+ // Manage non-whitelisted scalars in {@link self::evaluateScalar()}
return;
}
// Built-in tags
if ($tag && '!' === $tag[0]) {
- throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag));
+ throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
}
if (Yaml::PARSE_CUSTOM_TAGS & $flags) {
return $tag;
}
- throw new ParseException(sprintf('Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!%s".', $tag));
+ throw new ParseException(sprintf('Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!%s".', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
}
/**
$parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar));
if (0 !== (strlen($parsedBinaryData) % 4)) {
- throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', strlen($parsedBinaryData)));
+ throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', strlen($parsedBinaryData)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
if (!Parser::preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) {
- throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData));
+ throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
}
return base64_decode($parsedBinaryData, true);
{
return '~^0x[0-9a-f_]++$~i';
}
+
+ private static function getDeprecationMessage($message)
+ {
+ $message = rtrim($message, '.');
+
+ if (null !== self::$parsedFilename) {
+ $message .= ' in '.self::$parsedFilename;
+ }
+
+ if (-1 !== self::$parsedLineNumber) {
+ $message .= ' on line '.(self::$parsedLineNumber + 1);
+ }
+
+ return $message.'.';
+ }
}
-Copyright (c) 2004-2017 Fabien Potencier
+Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
* Parser parses YAML strings to convert them to PHP arrays.
*
* @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @final since version 3.4
*/
class Parser
{
const TAG_PATTERN = '(?P<tag>![\w!.\/:-]+)';
const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
+ private $filename;
private $offset = 0;
private $totalNumberOfLines;
private $lines = array();
}
}
+ /**
+ * Parses a YAML file into a PHP value.
+ *
+ * @param string $filename The path to the YAML file to be parsed
+ * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior
+ *
+ * @return mixed The YAML converted to a PHP value
+ *
+ * @throws ParseException If the file could not be read or the YAML is not valid
+ */
+ public function parseFile($filename, $flags = 0)
+ {
+ if (!is_file($filename)) {
+ throw new ParseException(sprintf('File "%s" does not exist.', $filename));
+ }
+
+ if (!is_readable($filename)) {
+ throw new ParseException(sprintf('File "%s" cannot be read.', $filename));
+ }
+
+ $this->filename = $filename;
+
+ try {
+ return $this->parse(file_get_contents($filename), $flags);
+ } finally {
+ $this->filename = null;
+ }
+ }
+
/**
* Parses a YAML string to a PHP value.
*
public function parse($value, $flags = 0)
{
if (is_bool($flags)) {
- @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
if ($flags) {
$flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE;
}
if (func_num_args() >= 3) {
- @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
if (func_get_arg(2)) {
$flags |= Yaml::PARSE_OBJECT;
}
if (func_num_args() >= 4) {
- @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
if (func_get_arg(3)) {
$flags |= Yaml::PARSE_OBJECT_FOR_MAP;
}
}
+ if (Yaml::PARSE_KEYS_AS_STRINGS & $flags) {
+ @trigger_error('Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.', E_USER_DEPRECATED);
+ }
+
if (false === preg_match('//u', $value)) {
- throw new ParseException('The YAML value does not appear to be valid UTF-8.');
+ throw new ParseException('The YAML value does not appear to be valid UTF-8.', -1, null, $this->filename);
}
$this->refs = array();
// tab?
if ("\t" === $this->currentLine[0]) {
- throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
+ Inline::initialize($flags, $this->getRealCurrentLineNb(), $this->filename);
+
$isRef = $mergeNode = false;
if (self::preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+))?$#u', rtrim($this->currentLine), $values)) {
if ($context && 'mapping' == $context) {
- throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
$context = 'sequence';
}
if (isset($values['value'][1]) && '?' === $values['value'][0] && ' ' === $values['value'][1]) {
- @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED);
+ @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), E_USER_DEPRECATED);
}
// array
$this->refs[$isRef] = end($data);
}
} elseif (
- self::preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|(?:!?!php/const:)?(?:![^\s]++\s++)?[^ \'"\[\{!].*?) *\:(\s++(?P<value>.+))?$#u', rtrim($this->currentLine), $values)
+ self::preg_match('#^(?P<key>(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|(?:!?!php/const:)?[^ \'"\[\{!].*?)) *\:(\s++(?P<value>.+))?$#u', rtrim($this->currentLine), $values)
&& (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))
) {
if ($context && 'sequence' == $context) {
- throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine);
+ throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine, $this->filename);
}
$context = 'mapping';
- // force correct settings
- Inline::parse(null, $flags, $this->refs);
try {
- Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
$i = 0;
$evaluateKey = !(Yaml::PARSE_KEYS_AS_STRINGS & $flags);
throw $e;
}
- if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) {
+ if (!is_string($key) && !is_int($key)) {
$keyType = is_numeric($key) ? 'numeric key' : 'non-string key';
- @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType), E_USER_DEPRECATED);
+ @trigger_error($this->getDeprecationMessage(sprintf('Implicit casting of %s to string is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType)), E_USER_DEPRECATED);
}
// Convert float keys to strings, to avoid being converted to integers by PHP
$key = (string) $key;
}
- if ('<<' === $key) {
+ if ('<<' === $key && (!isset($values['value']) || !self::preg_match('#^&(?P<ref>[^ ]+)#u', $values['value'], $refMatches))) {
$mergeNode = true;
$allowOverwrite = true;
- if (isset($values['value']) && 0 === strpos($values['value'], '*')) {
+ if (isset($values['value'][0]) && '*' === $values['value'][0]) {
$refName = substr(rtrim($values['value']), 1);
if (!array_key_exists($refName, $this->refs)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
$refValue = $this->refs[$refName];
+ if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $refValue instanceof \stdClass) {
+ $refValue = (array) $refValue;
+ }
+
if (!is_array($refValue)) {
- throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
$data += $refValue; // array union
} else {
- if (isset($values['value']) && $values['value'] !== '') {
+ if (isset($values['value']) && '' !== $values['value']) {
$value = $values['value'];
} else {
$value = $this->getNextEmbedBlock();
}
$parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags);
+ if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsed instanceof \stdClass) {
+ $parsed = (array) $parsed;
+ }
+
if (!is_array($parsed)) {
- throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
if (isset($parsed[0])) {
// and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier
// in the sequence override keys specified in later mapping nodes.
foreach ($parsed as $parsedItem) {
+ if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsedItem instanceof \stdClass) {
+ $parsedItem = (array) $parsedItem;
+ }
+
if (!is_array($parsedItem)) {
- throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem);
+ throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem, $this->filename);
}
$data += $parsedItem; // array union
$data += $parsed; // array union
}
}
- } elseif (isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]++) *+(?P<value>.*)#u', $values['value'], $matches)) {
+ } elseif ('<<' !== $key && isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]++) *+(?P<value>.*)#u', $values['value'], $matches)) {
$isRef = $matches['ref'];
$values['value'] = $matches['value'];
}
$subTag = null;
if ($mergeNode) {
// Merge keys
- } elseif (!isset($values['value']) || '' === $values['value'] || 0 === strpos($values['value'], '#') || (null !== $subTag = $this->getLineTag($values['value'], $flags))) {
+ } elseif (!isset($values['value']) || '' === $values['value'] || 0 === strpos($values['value'], '#') || (null !== $subTag = $this->getLineTag($values['value'], $flags)) || '<<' === $key) {
// hash
// if next line is less indented or equal, then it means that the current value is null
if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
$data[$key] = null;
}
} else {
- @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
+ @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED);
}
} else {
- // remember the parsed line number here in case we need it to provide some contexts in error messages below
- $realCurrentLineNbKey = $this->getRealCurrentLineNb();
$value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags);
- // Spec: Keys MUST be unique; first one wins.
- // But overwriting is allowed when a merge node is used in current block.
- if ($allowOverwrite || !isset($data[$key])) {
+ if ('<<' === $key) {
+ $this->refs[$refMatches['ref']] = $value;
+
+ if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $value instanceof \stdClass) {
+ $value = (array) $value;
+ }
+
+ $data += $value;
+ } elseif ($allowOverwrite || !isset($data[$key])) {
+ // Spec: Keys MUST be unique; first one wins.
+ // But overwriting is allowed when a merge node is used in current block.
if (null !== $subTag) {
$data[$key] = new TaggedValue($subTag, $value);
} else {
$data[$key] = $value;
}
} else {
- @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
+ @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED);
}
}
} else {
if ($allowOverwrite || !isset($data[$key])) {
$data[$key] = $value;
} else {
- @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
+ @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED);
}
}
if ($isRef) {
} else {
// multiple documents are not supported
if ('---' === $this->currentLine) {
- throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine);
+ throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine, $this->filename);
}
- if (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1]) {
- @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED);
+ if ($deprecatedUsage = (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1])) {
+ @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), E_USER_DEPRECATED);
}
// 1-liner optionally followed by newline(s)
if (is_string($value) && $this->lines[0] === trim($value)) {
try {
- Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
$value = Inline::parse($this->lines[0], $flags, $this->refs);
} catch (ParseException $e) {
$e->setParsedLine($this->getRealCurrentLineNb() + 1);
// try to parse the value as a multi-line string as a last resort
if (0 === $this->currentLineNb) {
- $parseError = false;
$previousLineWasNewline = false;
+ $previousLineWasTerminatedWithBackslash = false;
$value = '';
foreach ($this->lines as $line) {
- try {
- if (isset($line[0]) && ('"' === $line[0] || "'" === $line[0])) {
- $parsedLine = $line;
- } else {
- $parsedLine = Inline::parse($line, $flags, $this->refs);
- }
+ // If the indentation is not consistent at offset 0, it is to be considered as a ParseError
+ if (0 === $this->offset && !$deprecatedUsage && isset($line[0]) && ' ' === $line[0]) {
+ throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
+ }
+ if ('' === trim($line)) {
+ $value .= "\n";
+ } elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) {
+ $value .= ' ';
+ }
- if (!is_string($parsedLine)) {
- $parseError = true;
- break;
- }
+ if ('' !== trim($line) && '\\' === substr($line, -1)) {
+ $value .= ltrim(substr($line, 0, -1));
+ } elseif ('' !== trim($line)) {
+ $value .= trim($line);
+ }
- if ('' === trim($parsedLine)) {
- $value .= "\n";
- $previousLineWasNewline = true;
- } elseif ($previousLineWasNewline) {
- $value .= trim($parsedLine);
- $previousLineWasNewline = false;
- } else {
- $value .= ' '.trim($parsedLine);
- $previousLineWasNewline = false;
- }
- } catch (ParseException $e) {
- $parseError = true;
- break;
+ if ('' === trim($line)) {
+ $previousLineWasNewline = true;
+ $previousLineWasTerminatedWithBackslash = false;
+ } elseif ('\\' === substr($line, -1)) {
+ $previousLineWasNewline = false;
+ $previousLineWasTerminatedWithBackslash = true;
+ } else {
+ $previousLineWasNewline = false;
+ $previousLineWasTerminatedWithBackslash = false;
}
}
- if (!$parseError) {
- return trim($value);
+ try {
+ return Inline::parse(trim($value));
+ } catch (ParseException $e) {
+ // fall-through to the ParseException thrown below
}
}
- throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
} while ($this->moveToNextLine());
/**
* Returns the current line number (takes the offset into account).
*
+ * @internal
+ *
* @return int The current line number
*/
- private function getRealCurrentLineNb()
+ public function getRealCurrentLineNb()
{
$realCurrentLineNumber = $this->currentLineNb + $this->offset;
}
if (null === $indentation) {
- $newIndent = $this->getCurrentLineIndentation();
+ $newIndent = null;
+ $movements = 0;
+
+ do {
+ $EOF = false;
+
+ // empty and comment-like lines do not influence the indentation depth
+ if ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()) {
+ $EOF = !$this->moveToNextLine();
+
+ if (!$EOF) {
+ ++$movements;
+ }
+ } else {
+ $newIndent = $this->getCurrentLineIndentation();
+ }
+ } while (!$EOF && null === $newIndent);
+
+ for ($i = 0; $i < $movements; ++$i) {
+ $this->moveToPreviousLine();
+ }
$unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem();
if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) {
- throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
} else {
$newIndent = $indentation;
$data = array();
if ($this->getCurrentLineIndentation() >= $newIndent) {
$data[] = substr($this->currentLine, $newIndent);
+ } elseif ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()) {
+ $data[] = $this->currentLine;
} else {
$this->moveToPreviousLine();
$indent = $this->getCurrentLineIndentation();
// terminate all block scalars that are more indented than the current line
- if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && trim($this->currentLine) !== '') {
+ if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && '' !== trim($this->currentLine)) {
foreach ($blockScalarIndentations as $key => $blockScalarIndentation) {
if ($blockScalarIndentation >= $indent) {
unset($blockScalarIndentations[$key]);
continue;
}
- // we ignore "comment" lines only when we are not inside a scalar block
- if (empty($blockScalarIndentations) && $this->isCurrentLineComment()) {
- // remember ignored comment lines (they are used later in nested
- // parser calls to determine real line numbers)
- //
- // CAUTION: beware to not populate the global property here as it
- // will otherwise influence the getRealCurrentLineNb() call here
- // for consecutive comment lines and subsequent embedded blocks
- $this->locallySkippedLineNumbers[] = $this->getRealCurrentLineNb();
-
- continue;
- }
-
if ($indent >= $newIndent) {
$data[] = substr($this->currentLine, $newIndent);
+ } elseif ($this->isCurrentLineComment()) {
+ $data[] = $this->currentLine;
} elseif (0 == $indent) {
$this->moveToPreviousLine();
break;
} else {
- throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
+ throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
}
}
}
if (!array_key_exists($value, $this->refs)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine);
+ throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine, $this->filename);
}
return $this->refs[$value];
if ('' !== $matches['tag']) {
if ('!!binary' === $matches['tag']) {
return Inline::evaluateBinaryScalar($data);
+ } elseif ('tagged' === $matches['tag']) {
+ return new TaggedValue(substr($matches['tag'], 1), $data);
} elseif ('!' !== $matches['tag']) {
- @trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED);
+ @trigger_error($this->getDeprecationMessage(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since Symfony 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class)), E_USER_DEPRECATED);
}
}
return Inline::parse($value, $flags, $this->refs);
}
+ $lines = array();
+
while ($this->moveToNextLine()) {
// unquoted strings end before the first unindented line
- if (null === $quotation && $this->getCurrentLineIndentation() === 0) {
+ if (null === $quotation && 0 === $this->getCurrentLineIndentation()) {
$this->moveToPreviousLine();
break;
}
- $value .= ' '.trim($this->currentLine);
+ $lines[] = trim($this->currentLine);
// quoted string values end with a line that is terminated with the quotation character
if ('' !== $this->currentLine && substr($this->currentLine, -1) === $quotation) {
}
}
+ for ($i = 0, $linesCount = count($lines), $previousLineBlank = false; $i < $linesCount; ++$i) {
+ if ('' === $lines[$i]) {
+ $value .= "\n";
+ $previousLineBlank = true;
+ } elseif ($previousLineBlank) {
+ $value .= $lines[$i];
+ $previousLineBlank = false;
+ } else {
+ $value .= ' '.$lines[$i];
+ $previousLineBlank = false;
+ }
+ }
+
Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
+
$parsedValue = Inline::parse($value, $flags, $this->refs);
if ('mapping' === $context && is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) {
- throw new ParseException('A colon cannot be used in an unquoted mapping value.');
+ throw new ParseException('A colon cannot be used in an unquoted mapping value.', $this->getRealCurrentLineNb() + 1, $value, $this->filename);
}
return $parsedValue;
private function isNextLineIndented()
{
$currentIndentation = $this->getCurrentLineIndentation();
- $EOF = !$this->moveToNextLine();
+ $movements = 0;
- while (!$EOF && $this->isCurrentLineEmpty()) {
+ do {
$EOF = !$this->moveToNextLine();
- }
+
+ if (!$EOF) {
+ ++$movements;
+ }
+ } while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()));
if ($EOF) {
return false;
$ret = $this->getCurrentLineIndentation() > $currentIndentation;
- $this->moveToPreviousLine();
+ for ($i = 0; $i < $movements; ++$i) {
+ $this->moveToPreviousLine();
+ }
return $ret;
}
//checking explicitly the first char of the trim is faster than loops or strpos
$ltrimmedLine = ltrim($this->currentLine, ' ');
- return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#';
+ return '' !== $ltrimmedLine && '#' === $ltrimmedLine[0];
}
private function isCurrentLineLastLineInDocument()
// remove leading comments
$trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count);
- if ($count == 1) {
+ if (1 === $count) {
// items have been removed, update the offset
$this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
$value = $trimmedValue;
// remove start of the document marker (---)
$trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count);
- if ($count == 1) {
+ if (1 === $count) {
// items have been removed, update the offset
$this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
$value = $trimmedValue;
private function isNextLineUnIndentedCollection()
{
$currentIndentation = $this->getCurrentLineIndentation();
- $notEOF = $this->moveToNextLine();
+ $movements = 0;
- while ($notEOF && $this->isCurrentLineEmpty()) {
- $notEOF = $this->moveToNextLine();
- }
+ do {
+ $EOF = !$this->moveToNextLine();
+
+ if (!$EOF) {
+ ++$movements;
+ }
+ } while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()));
- if (false === $notEOF) {
+ if ($EOF) {
return false;
}
$ret = $this->getCurrentLineIndentation() === $currentIndentation && $this->isStringUnIndentedCollectionItem();
- $this->moveToPreviousLine();
+ for ($i = 0; $i < $movements; ++$i) {
+ $this->moveToPreviousLine();
+ }
return $ret;
}
// Built-in tags
if ($tag && '!' === $tag[0]) {
- throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag));
+ throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), $this->getRealCurrentLineNb() + 1, $value, $this->filename);
}
if (Yaml::PARSE_CUSTOM_TAGS & $flags) {
return $tag;
}
- throw new ParseException(sprintf('Tags support is not enabled. You must use the flag `Yaml::PARSE_CUSTOM_TAGS` to use "%s".', $matches['tag']));
+ throw new ParseException(sprintf('Tags support is not enabled. You must use the flag `Yaml::PARSE_CUSTOM_TAGS` to use "%s".', $matches['tag']), $this->getRealCurrentLineNb() + 1, $value, $this->filename);
+ }
+
+ private function getDeprecationMessage($message)
+ {
+ $message = rtrim($message, '.');
+
+ if (null !== $this->filename) {
+ $message .= ' in '.$this->filename;
+ }
+
+ $message .= ' on line '.($this->getRealCurrentLineNb() + 1);
+
+ return $message.'.';
}
}
public function testConstantAsKey()
{
$yaml = <<<YAML
-!php/const:Symfony\Component\Yaml\Tests\Command\Foo::TEST: bar
+!php/const 'Symfony\Component\Yaml\Tests\Command\Foo::TEST': bar
YAML;
$ret = $this->createCommandTester()->execute(array('filename' => $this->createFile($yaml)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false));
$this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success');
}
+ public function testCustomTags()
+ {
+ $yaml = <<<YAML
+foo: !my_tag {foo: bar}
+YAML;
+ $ret = $this->createCommandTester()->execute(array('filename' => $this->createFile($yaml), '--parse-tags' => true), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false));
+ $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success');
+ }
+
+ public function testCustomTagsError()
+ {
+ $yaml = <<<YAML
+foo: !my_tag {foo: bar}
+YAML;
+ $ret = $this->createCommandTester()->execute(array('filename' => $this->createFile($yaml)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false));
+ $this->assertSame(1, $ret, 'lint:yaml exits with code 1 in case of error');
+ }
+
/**
* @expectedException \RuntimeException
*/
// TODO
} else {
eval('$expected = '.trim($test['php']).';');
- $this->assertSame($expected, $this->parser->parse($this->dumper->dump($expected, 10), Yaml::PARSE_KEYS_AS_STRINGS), $test['test']);
+ $this->assertSame($expected, $this->parser->parse($this->dumper->dump($expected, 10)), $test['test']);
}
}
}
{
$dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_OBJECT);
- $this->assertEquals('{ foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects');
+ $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects');
}
/**
{
$dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true);
- $this->assertEquals('{ foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects');
+ $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects');
}
public function testObjectSupportDisabledButNoExceptions()
$data = array(
'data' => array(
'single_line' => 'foo bar baz',
- 'multi_line' => "foo\nline with trailing spaces:\n \nbar\r\ninteger like line:\n123456789\nempty line:\n\nbaz",
+ 'multi_line' => "foo\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz",
+ 'multi_line_with_carriage_return' => "foo\nbar\r\nbaz",
'nested_inlined_multi_line_string' => array(
'inlined_multi_line' => "foo\nbar\r\nempty line:\n\nbaz",
),
$this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK));
}
+ public function testDumpMultiLineStringAsScalarBlockWhenFirstLineHasLeadingSpace()
+ {
+ $data = array(
+ 'data' => array(
+ 'multi_line' => " the first line has leading spaces\nThe second line does not.",
+ ),
+ );
+
+ $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK));
+ }
+
+ public function testCarriageReturnIsMaintainedWhenDumpingAsMultiLineLiteralBlock()
+ {
+ $this->assertSame("- \"a\\r\\nb\\nc\"\n", $this->dumper->dump(array("a\r\nb\nc"), 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK));
+ }
+
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage The indentation must be greater than zero
todo: true
spec: 2.23
yaml: |
- not-date: !str 2002-04-28
+ not-date: !!str 2002-04-28
picture: !binary |
R0lGODlhDAAMAIQAAP//9/X
17unp5WZmZgAAAOfn515eXv
---
test: Explicit typing
+deprecated: Using the non-specific tag "!" is deprecated since Symfony 3.4 as its behavior will change in 4.0.
yaml: |
integer: 12
also int: ! "12"
- string: !str 12
+ string: !!str 12
php: |
array( 'integer' => 12, 'also int' => 12, 'string' => '12' )
---
test: Type family under yaml.org
yaml: |
# The URI is 'tag:yaml.org,2002:str'
- - !str a Unicode string
+ - !!str a Unicode string
php: |
array( 'a Unicode string' )
---
second: 12 ## This is an integer.
- third: !str 12 ## This is a string.
+ third: !!str 12 ## This is a string.
span: this contains
six spaces
# The following scalars
# are loaded to the
# string value '1' '2'.
- - !str 12
+ - !!str 12
- '12'
- "12"
- "\
test: Forcing Strings
brief: >
Any YAML type can be forced into a string using the
- explicit !str method.
+ explicit !!str method.
yaml: |
- date string: !str 2001-08-01
- number string: !str 192
+ date string: !!str 2001-08-01
+ number string: !!str 192
php: |
array(
'date string' => '2001-08-01',
empty line:
baz
+ multi_line_with_carriage_return: "foo\nbar\r\nbaz"
nested_inlined_multi_line_string: { inlined_multi_line: "foo\nbar\r\nempty line:\n\nbaz" }
--- /dev/null
+data:
+ multi_line: |4
+ the first line has leading spaces
+ The second line does not.
--- /dev/null
+- escapedCharacters
+- sfComments
+- sfCompact
+- sfTests
+- sfObjects
+- sfMergeKey
+- sfQuotes
+- YtsAnchorAlias
+- YtsBasicTests
+- YtsBlockMapping
+- YtsDocumentSeparator
+- YtsErrorTests
+- YtsFlowCollections
+- YtsFoldedScalars
+- YtsNullsAndEmpties
+- YtsSpecificationExamples
+- YtsTypeTransfers
+- unindentedCollections
c:
foo: bar
bar: foo
+ bar_inline: {a: before, d: other, <<: *foo, b: new, x: Oren, c: { foo: bar, bar: foo}}
foo2: &foo2
a: Ballmer
ding: &dong [ fi, fei, fo, fam]
p: 12345
z:
<<: *nestedref
+ head_inline: &head_inline { <<: [ *foo , *dong , *foo2 ] }
+ recursive_inline: { <<: *head_inline, c: { <<: *foo2 } }
php: |
array(
'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull'),
'bar' => array('a' => 'before', 'd' => 'other', 'e' => null, 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'),
+ 'bar_inline' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'e' => 'notnull', 'x' => 'Oren'),
'foo2' => array('a' => 'Ballmer'),
'ding' => array('fi', 'fei', 'fo', 'fam'),
'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'),
'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'),
'taz' => array('a' => 'Steve', 'w' => array('p' => 1234)),
- 'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345))
+ 'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)),
+ 'head_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'),
+ 'recursive_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => array('a' => 'Ballmer'), 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'),
)
class InlineTest extends TestCase
{
+ protected function setUp()
+ {
+ Inline::initialize(0, 0);
+ }
+
/**
* @dataProvider getTestsForParse
*/
public function getTestsForParsePhpConstants()
{
return array(
- array('!php/const:Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT),
- array('!php/const:PHP_INT_MAX', PHP_INT_MAX),
- array('[!php/const:PHP_INT_MAX]', array(PHP_INT_MAX)),
- array('{ foo: !php/const:PHP_INT_MAX }', array('foo' => PHP_INT_MAX)),
+ array('!php/const Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT),
+ array('!php/const PHP_INT_MAX', PHP_INT_MAX),
+ array('[!php/const PHP_INT_MAX]', array(PHP_INT_MAX)),
+ array('{ foo: !php/const PHP_INT_MAX }', array('foo' => PHP_INT_MAX)),
+ array('!php/const NULL', null),
);
}
*/
public function testParsePhpConstantThrowsExceptionWhenUndefined()
{
- Inline::parse('!php/const:WRONG_CONSTANT', Yaml::PARSE_CONSTANT);
+ Inline::parse('!php/const WRONG_CONSTANT', Yaml::PARSE_CONSTANT);
}
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessageRegExp #The string "!php/const:PHP_INT_MAX" could not be parsed as a constant.*#
+ * @expectedExceptionMessageRegExp #The string "!php/const PHP_INT_MAX" could not be parsed as a constant.*#
*/
public function testParsePhpConstantThrowsExceptionOnInvalidType()
{
- Inline::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
+ Inline::parse('!php/const PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 1.
+ * @dataProvider getTestsForParseLegacyPhpConstants
+ */
+ public function testDeprecatedConstantTag($yaml, $expectedValue)
+ {
+ $this->assertSame($expectedValue, Inline::parse($yaml, Yaml::PARSE_CONSTANT));
+ }
+
+ public function getTestsForParseLegacyPhpConstants()
+ {
+ return array(
+ array('!php/const:Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT),
+ array('!php/const:PHP_INT_MAX', PHP_INT_MAX),
+ array('[!php/const:PHP_INT_MAX]', array(PHP_INT_MAX)),
+ array('{ foo: !php/const:PHP_INT_MAX }', array('foo' => PHP_INT_MAX)),
+ array('!php/const:NULL', null),
+ );
}
/**
/**
* @group legacy
- * @expectedDeprecation Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0.
+ * @expectedDeprecation Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since Symfony 3.2 and will throw a ParseException in 4.0 on line 1.
* throws \Symfony\Component\Yaml\Exception\ParseException in 4.0
*/
public function testParseMappingKeyWithColonNotFollowedBySpace()
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage A reference must contain at least one character.
+ * @expectedExceptionMessage A reference must contain at least one character at line 1.
*/
public function testParseUnquotedAsterisk()
{
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage A reference must contain at least one character.
+ * @expectedExceptionMessage A reference must contain at least one character at line 1.
*/
public function testParseUnquotedAsteriskFollowedByAComment()
{
/**
* @dataProvider getReservedIndicators
- * @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage cannot start a plain scalar; you need to quote the scalar.
*/
public function testParseUnquotedScalarStartingWithReservedIndicator($indicator)
{
+ if (method_exists($this, 'expectExceptionMessage')) {
+ $this->expectException(ParseException::class);
+ $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator));
+ } else {
+ $this->setExpectedException(ParseException::class, sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator));
+ }
+
Inline::parse(sprintf('{ foo: %sfoo }', $indicator));
}
/**
* @dataProvider getScalarIndicators
- * @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage cannot start a plain scalar; you need to quote the scalar.
*/
public function testParseUnquotedScalarStartingWithScalarIndicator($indicator)
{
+ if (method_exists($this, 'expectExceptionMessage')) {
+ $this->expectException(ParseException::class);
+ $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator));
+ } else {
+ $this->setExpectedException(ParseException::class, sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator));
+ }
+
Inline::parse(sprintf('{ foo: %sfoo }', $indicator));
}
/**
* @group legacy
- * @expectedDeprecation Not quoting the scalar "%bar " starting with the "%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.
+ * @expectedDeprecation Not quoting the scalar "%bar " starting with the "%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0 on line 1.
* throws \Symfony\Component\Yaml\Exception\ParseException in 4.0
*/
public function testParseUnquotedScalarStartingWithPercentCharacter()
array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
// mappings
- array('{foo: bar,bar: foo,false: false,null: null,integer: 12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS),
- array('{ foo : bar, bar : foo, false : false, null : null, integer : 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS),
+ array('{foo: bar,bar: foo,"false": false, "null": null,integer: 12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
+ array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
array('{foo: \'bar\', bar: \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', array('foo\'' => 'bar', 'bar"' => 'foo: bar')),
array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
// mappings
- array('{foo: bar,bar: foo,false: false,null: null,integer: 12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP | Yaml::PARSE_KEYS_AS_STRINGS),
- array('{ foo : bar, bar : foo, false : false, null : null, integer : 12 }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP | Yaml::PARSE_KEYS_AS_STRINGS),
+ array('{foo: bar,bar: foo,"false": false,"null": null,integer: 12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP),
+ array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP),
array('{foo: \'bar\', bar: \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', (object) array('foo\'' => 'bar', 'bar"' => 'foo: bar')),
array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
// mappings
- array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS),
+ array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
array('{ foo: bar, bar: \'foo: bar\' }', array('foo' => 'bar', 'bar' => 'foo: bar')),
// nested sequences and mappings
array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')),
- array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3))), Yaml::PARSE_KEYS_AS_STRINGS),
+ array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3)))),
);
}
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage Malformed inline YAML string: {this, is not, supported}.
+ * @expectedExceptionMessage Malformed inline YAML string: {this, is not, supported} at line 1.
*/
public function testNotSupportedMissingValue()
{
/**
* @group legacy
- * @expectedDeprecation Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.
+ * @expectedDeprecation Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0 on line 1.
*/
public function testOmittedMappingKeyIsParsedAsColon()
{
/**
* @group legacy
- * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.
+ * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 1.
* @dataProvider getNotPhpCompatibleMappingKeyData
*/
public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected)
}
/**
+ * @group legacy
+ * @expectedDeprecation Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.
+ * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 1.
* @dataProvider getNotPhpCompatibleMappingKeyData
*/
public function testExplicitStringCastingOfMappingKeys($yaml, $expected)
{
- $this->assertSame($expected, Inline::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
+ $this->assertSame($expected, Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
}
public function getNotPhpCompatibleMappingKeyData()
'float' => array('{0.25: "foo"}', array('0.25' => 'foo')),
);
}
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Support for the !str tag is deprecated since Symfony 3.4. Use the !!str tag instead on line 1.
+ */
+ public function testDeprecatedStrTag()
+ {
+ $this->assertSame(array('foo' => 'bar'), Inline::parse('{ foo: !str bar }'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessage Unexpected end of line, expected one of ",}" at line 1 (near "{abc: 'def'").
+ */
+ public function testUnfinishedInlineMap()
+ {
+ Inline::parse("{abc: 'def'");
+ }
}
protected function tearDown()
{
$this->parser = null;
+
+ chmod(__DIR__.'/Fixtures/not_readable.yml', 0644);
}
/**
restore_error_handler();
$this->assertCount(1, $deprecations);
- $this->assertContains('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', $deprecations[0]);
+ $this->assertContains(true !== $deprecated ? $deprecated : 'Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0 on line 1.', $deprecations[0]);
}
}
}
/**
+ * @group legacy
+ * @expectedDeprecationMessage Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable
* @dataProvider getNonStringMappingKeysData
*/
public function testNonStringMappingKeys($expected, $yaml, $comment)
public function testObjectSupportEnabled()
{
$input = <<<'EOF'
-foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
+foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
bar: 1
EOF;
$this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
/**
* @group legacy
+ * @dataProvider deprecatedObjectValueProvider
*/
- public function testObjectSupportEnabledWithDeprecatedTag()
+ public function testObjectSupportEnabledWithDeprecatedTag($yaml)
{
- $input = <<<'EOF'
+ $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
+ }
+
+ public function deprecatedObjectValueProvider()
+ {
+ return array(
+ array(
+ <<<YAML
foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
bar: 1
-EOF;
- $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
+YAML
+ ),
+ array(
+ <<<YAML
+foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
+bar: 1
+YAML
+ ),
+ );
}
/**
/**
* @dataProvider getObjectForMapTests
*/
- public function testObjectForMap($yaml, $expected, $explicitlyParseKeysAsStrings = false)
+ public function testObjectForMap($yaml, $expected)
{
$flags = Yaml::PARSE_OBJECT_FOR_MAP;
- if ($explicitlyParseKeysAsStrings) {
- $flags |= Yaml::PARSE_KEYS_AS_STRINGS;
- }
-
$this->assertEquals($expected, $this->parser->parse($yaml, $flags));
}
$expected->map = new \stdClass();
$expected->map->{1} = 'one';
$expected->map->{2} = 'two';
- $tests['numeric-keys'] = array($yaml, $expected, true);
+ $tests['numeric-keys'] = array($yaml, $expected);
$yaml = <<<'YAML'
map:
- 0: one
- 1: two
+ '0': one
+ '1': two
YAML;
$expected = new \stdClass();
$expected->map = new \stdClass();
$expected->map->{0} = 'one';
$expected->map->{1} = 'two';
- $tests['zero-indexed-numeric-keys'] = array($yaml, $expected, true);
+ $tests['zero-indexed-numeric-keys'] = array($yaml, $expected);
return $tests;
}
$this->assertSame($expected, $this->parser->parse($yaml));
}
+ public function testNonStringFollowedByCommentEmbeddedInMapping()
+ {
+ $yaml = <<<'EOT'
+a:
+ b:
+ {}
+# comment
+ d:
+ 1.1
+# another comment
+EOT;
+ $expected = array(
+ 'a' => array(
+ 'b' => array(),
+ 'd' => 1.1,
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function getParseExceptionNotAffectedMultiLineStringLastResortParsing()
+ {
+ $tests = array();
+
+ $yaml = <<<'EOT'
+a
+ b:
+EOT;
+ $tests['parse error on first line'] = array($yaml);
+
+ $yaml = <<<'EOT'
+a
+
+b
+ c:
+EOT;
+ $tests['parse error due to inconsistent indentation'] = array($yaml);
+
+ $yaml = <<<'EOT'
+ & * ! | > ' " % @ ` #, { asd a;sdasd }-@^qw3
+EOT;
+ $tests['symfony/symfony/issues/22967#issuecomment-322067742'] = array($yaml);
+
+ return $tests;
+ }
+
+ /**
+ * @dataProvider getParseExceptionNotAffectedMultiLineStringLastResortParsing
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ */
+ public function testParseExceptionNotAffectedByMultiLineStringLastResortParsing($yaml)
+ {
+ $this->parser->parse($yaml);
+ }
+
+ public function testMultiLineStringLastResortParsing()
+ {
+ $yaml = <<<'EOT'
+test:
+ You can have things that don't look like strings here
+ true
+ yes you can
+EOT;
+ $expected = array(
+ 'test' => 'You can have things that don\'t look like strings here true yes you can',
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+
+ $yaml = <<<'EOT'
+a:
+ b
+ c
+EOT;
+ $expected = array(
+ 'a' => 'b c',
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/
/**
* @group legacy
* @dataProvider getParseExceptionOnDuplicateData
- * @expectedDeprecation Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s.
+ * @expectedDeprecation Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.
* throws \Symfony\Component\Yaml\Exception\ParseException in 4.0
*/
public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber)
/**
* @group legacy
- * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.
+ * @expectedDeprecation Implicit casting of numeric key to string is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 2.
*/
public function testFloatKeys()
{
/**
* @group legacy
- * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.
+ * @expectedDeprecation Implicit casting of non-string key to string is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 1.
*/
public function testBooleanKeys()
{
$this->assertEquals($expected, $this->parser->parse($yaml));
}
- public function testExplicitStringCastingOfFloatKeys()
+ public function testExplicitStringCasting()
{
$yaml = <<<'EOF'
-foo:
- 1.2: "bar"
- 1.3: "baz"
-EOF;
+'1.2': "bar"
+!!str 1.3: "baz"
- $expected = array(
- 'foo' => array(
- '1.2' => 'bar',
- '1.3' => 'baz',
- ),
- );
+'true': foo
+!!str false: bar
- $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
- }
-
- public function testExplicitStringCastingOfBooleanKeys()
- {
- $yaml = <<<'EOF'
-true: foo
-false: bar
+!!str null: 'null'
+'~': 'null'
EOF;
$expected = array(
+ '1.2' => 'bar',
+ '1.3' => 'baz',
'true' => 'foo',
'false' => 'bar',
+ 'null' => 'null',
+ '~' => 'null',
);
- $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS));
+ $this->assertEquals($expected, $this->parser->parse($yaml));
}
/**
$this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml));
}
+ public function testMultiLineQuotedStringWithTrailingBackslash()
+ {
+ $yaml = <<<YAML
+foobar:
+ "foo\
+ bar"
+YAML;
+
+ $this->assertSame(array('foobar' => 'foobar'), $this->parser->parse($yaml));
+ }
+
+ public function testCommentCharactersInMultiLineQuotedStrings()
+ {
+ $yaml = <<<YAML
+foo:
+ foobar: 'foo
+ #bar'
+ bar: baz
+YAML;
+ $expected = array(
+ 'foo' => array(
+ 'foobar' => 'foo #bar',
+ 'bar' => 'baz',
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function testBlankLinesInQuotedMultiLineString()
+ {
+ $yaml = <<<YAML
+foobar: 'foo
+
+ bar'
+YAML;
+ $expected = array(
+ 'foobar' => "foo\nbar",
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
public function testParseMultiLineUnquotedString()
{
$yaml = <<<EOT
/**
* @group legacy
- * @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.
+ * @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since Symfony 3.3 and will be considered as a tagged value in 4.0. You must quote it on line 1.
*/
public function testUnsupportedTagWithScalar()
{
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage The built-in tag "!!foo" is not implemented.
+ * @expectedExceptionMessage The built-in tag "!!foo" is not implemented at line 1 (near "!!foo").
*/
public function testExceptionWhenUsingUnsuportedBuiltInTags()
{
/**
* @group legacy
- * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.
+ * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1.
*/
public function testComplexMappingThrowsParseException()
{
/**
* @group legacy
- * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.
+ * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 2.
*/
public function testComplexMappingNestedInMappingThrowsParseException()
{
/**
* @group legacy
- * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.
+ * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1.
*/
public function testComplexMappingNestedInSequenceThrowsParseException()
{
$parser = new Parser();
$tests = array();
- $files = $parser->parse(file_get_contents(__DIR__.'/Fixtures/'.$testsFile));
+ $files = $parser->parseFile(__DIR__.'/Fixtures/'.$testsFile);
foreach ($files as $file) {
$yamls = file_get_contents(__DIR__.'/Fixtures/'.$file.'.yml');
public function testPhpConstantTagMappingKey()
{
$yaml = <<<YAML
+transitions:
+ !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
+ from:
+ - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
+ to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
+YAML;
+ $expected = array(
+ 'transitions' => array(
+ 'foo' => array(
+ 'from' => array(
+ 'bar',
+ ),
+ 'to' => 'baz',
+ ),
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 2.
+ * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 4.
+ * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 5.
+ */
+ public function testDeprecatedPhpConstantTagMappingKey()
+ {
+ $yaml = <<<YAML
transitions:
!php/const:Symfony\Component\Yaml\Tests\B::FOO:
from:
$this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
}
+ /**
+ * @group legacy
+ * @expectedDeprecation Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.
+ */
public function testPhpConstantTagMappingKeyWithKeysCastToStrings()
{
$yaml = <<<YAML
transitions:
- !php/const:Symfony\Component\Yaml\Tests\B::FOO:
+ !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
from:
- - !php/const:Symfony\Component\Yaml\Tests\B::BAR
- to: !php/const:Symfony\Component\Yaml\Tests\B::BAZ
+ - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
+ to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
YAML;
$expected = array(
'transitions' => array(
$this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS));
}
+
+ public function testMergeKeysWhenMappingsAreParsedAsObjects()
+ {
+ $yaml = <<<YAML
+foo: &FOO
+ bar: 1
+bar: &BAR
+ baz: 2
+ <<: *FOO
+baz:
+ baz_foo: 3
+ <<:
+ baz_bar: 4
+foobar:
+ bar: ~
+ <<: [*FOO, *BAR]
+YAML;
+ $expected = (object) array(
+ 'foo' => (object) array(
+ 'bar' => 1,
+ ),
+ 'bar' => (object) array(
+ 'baz' => 2,
+ 'bar' => 1,
+ ),
+ 'baz' => (object) array(
+ 'baz_foo' => 3,
+ 'baz_bar' => 4,
+ ),
+ 'foobar' => (object) array(
+ 'bar' => null,
+ 'baz' => 2,
+ ),
+ );
+
+ $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
+ }
+
+ public function testFilenamesAreParsedAsStringsWithoutFlag()
+ {
+ $file = __DIR__.'/Fixtures/index.yml';
+
+ $this->assertSame($file, $this->parser->parse($file));
+ }
+
+ public function testParseFile()
+ {
+ $this->assertInternalType('array', $this->parser->parseFile(__DIR__.'/Fixtures/index.yml'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessageRegExp #^File ".+/Fixtures/nonexistent.yml" does not exist\.$#
+ */
+ public function testParsingNonExistentFilesThrowsException()
+ {
+ $this->parser->parseFile(__DIR__.'/Fixtures/nonexistent.yml');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessageRegExp #^File ".+/Fixtures/not_readable.yml" cannot be read\.$#
+ */
+ public function testParsingNotReadableFilesThrowsException()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('chmod is not supported on Windows');
+ }
+
+ $file = __DIR__.'/Fixtures/not_readable.yml';
+ chmod($file, 0200);
+
+ $this->parser->parseFile($file);
+ }
+
+ public function testParseReferencesOnMergeKeys()
+ {
+ $yaml = <<<YAML
+mergekeyrefdef:
+ a: foo
+ <<: &quux
+ b: bar
+ c: baz
+mergekeyderef:
+ d: quux
+ <<: *quux
+YAML;
+ $expected = array(
+ 'mergekeyrefdef' => array(
+ 'a' => 'foo',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ 'mergekeyderef' => array(
+ 'd' => 'quux',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects()
+ {
+ $yaml = <<<YAML
+mergekeyrefdef:
+ a: foo
+ <<: &quux
+ b: bar
+ c: baz
+mergekeyderef:
+ d: quux
+ <<: *quux
+YAML;
+ $expected = (object) array(
+ 'mergekeyrefdef' => (object) array(
+ 'a' => 'foo',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ 'mergekeyderef' => (object) array(
+ 'd' => 'quux',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ );
+
+ $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessage Reference "foo" does not exist
+ */
+ public function testEvalRefException()
+ {
+ $yaml = <<<EOE
+foo: { &foo { a: Steve, <<: *foo} }
+EOE;
+ $this->parser->parse($yaml);
+ }
+
+ /**
+ * @dataProvider indentedMappingData
+ */
+ public function testParseIndentedMappings($yaml, $expected)
+ {
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function indentedMappingData()
+ {
+ $tests = array();
+
+ $yaml = <<<YAML
+foo:
+ - bar: "foobar"
+ # A comment
+ baz: "foobaz"
+YAML;
+ $expected = array(
+ 'foo' => array(
+ array(
+ 'bar' => 'foobar',
+ 'baz' => 'foobaz',
+ ),
+ ),
+ );
+ $tests['comment line is first line in indented block'] = array($yaml, $expected);
+
+ $yaml = <<<YAML
+foo:
+ - bar:
+ # comment
+ baz: [1, 2, 3]
+YAML;
+ $expected = array(
+ 'foo' => array(
+ array(
+ 'bar' => array(
+ 'baz' => array(1, 2, 3),
+ ),
+ ),
+ ),
+ );
+ $tests['mapping value on new line starting with a comment line'] = array($yaml, $expected);
+
+ $yaml = <<<YAML
+foo:
+ -
+ bar: foobar
+YAML;
+ $expected = array(
+ 'foo' => array(
+ array(
+ 'bar' => 'foobar',
+ ),
+ ),
+ );
+ $tests['mapping in sequence starting on a new line'] = array($yaml, $expected);
+
+ $yaml = <<<YAML
+foo:
+
+ bar: baz
+YAML;
+ $expected = array(
+ 'foo' => array(
+ 'bar' => 'baz',
+ ),
+ );
+ $tests['blank line at the beginning of an indented mapping value'] = array($yaml, $expected);
+
+ return $tests;
+ }
}
class B
* Yaml offers convenience methods to load and dump YAML.
*
* @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @final since version 3.4
*/
class Yaml
{
const PARSE_CONSTANT = 256;
const PARSE_CUSTOM_TAGS = 512;
const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
+
+ /**
+ * @deprecated since version 3.4, to be removed in 4.0. Quote your evaluable keys instead.
+ */
const PARSE_KEYS_AS_STRINGS = 2048;
+ /**
+ * Parses a YAML file into a PHP value.
+ *
+ * Usage:
+ * <code>
+ * $array = Yaml::parseFile('config.yml');
+ * print_r($array);
+ * </code>
+ *
+ * @param string $filename The path to the YAML file to be parsed
+ * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior
+ *
+ * @return mixed The YAML converted to a PHP value
+ *
+ * @throws ParseException If the file could not be read or the YAML is not valid
+ */
+ public static function parseFile($filename, $flags = 0)
+ {
+ $yaml = new Parser();
+
+ return $yaml->parseFile($filename, $flags);
+ }
+
/**
* Parses YAML into a PHP value.
*
public static function parse($input, $flags = 0)
{
if (is_bool($flags)) {
- @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
if ($flags) {
$flags = self::PARSE_EXCEPTION_ON_INVALID_TYPE;
}
if (func_num_args() >= 3) {
- @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the PARSE_OBJECT flag instead.', E_USER_DEPRECATED);
if (func_get_arg(2)) {
$flags |= self::PARSE_OBJECT;
}
if (func_num_args() >= 4) {
- @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED);
if (func_get_arg(3)) {
$flags |= self::PARSE_OBJECT_FOR_MAP;
public static function dump($input, $inline = 2, $indent = 4, $flags = 0)
{
if (is_bool($flags)) {
- @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
if ($flags) {
$flags = self::DUMP_EXCEPTION_ON_INVALID_TYPE;
}
if (func_num_args() >= 5) {
- @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
+ @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
if (func_get_arg(4)) {
$flags |= self::DUMP_OBJECT;
}
],
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"require-dev": {
- "symfony/console": "~2.8|~3.0"
+ "symfony/console": "~3.4|~4.0"
+ },
+ "conflict": {
+ "symfony/console": "<3.4"
},
"suggest": {
"symfony/console": "For validating YAML files using the lint command"
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.3-dev"
+ "dev-master": "3.4-dev"
}
}
}