diff --git a/composer.lock b/composer.lock index ad95e0f21..82dc857ff 100644 --- a/composer.lock +++ b/composer.lock @@ -4341,16 +4341,16 @@ }, { "name": "symfony/property-info", - "version": "v6.4.13", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "ea388133aadf407dfa54092873d1b7e52f439515" + "reference": "9d7b576bb643c72bf3b60eb8e89c98725d00afd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/ea388133aadf407dfa54092873d1b7e52f439515", - "reference": "ea388133aadf407dfa54092873d1b7e52f439515", + "url": "https://api.github.com/repos/symfony/property-info/zipball/9d7b576bb643c72bf3b60eb8e89c98725d00afd0", + "reference": "9d7b576bb643c72bf3b60eb8e89c98725d00afd0", "shasum": "" }, "require": { @@ -4365,7 +4365,7 @@ }, "require-dev": { "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/serializer": "^6.4|^7.0" @@ -4404,7 +4404,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.4.13" + "source": "https://github.com/symfony/property-info/tree/v6.4.15" }, "funding": [ { @@ -4420,20 +4420,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2024-11-07T16:39:46+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.13", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "8be421505938b11a0ca4f656e4322232236386f0" + "reference": "9d862d66198f3c2e30404228629ef4c18d5d608e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/8be421505938b11a0ca4f656e4322232236386f0", - "reference": "8be421505938b11a0ca4f656e4322232236386f0", + "url": "https://api.github.com/repos/symfony/serializer/zipball/9d862d66198f3c2e30404228629ef4c18d5d608e", + "reference": "9d862d66198f3c2e30404228629ef4c18d5d608e", "shasum": "" }, "require": { @@ -4502,7 +4502,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.13" + "source": "https://github.com/symfony/serializer/tree/v6.4.15" }, "funding": [ { @@ -4518,7 +4518,7 @@ "type": "tidelift" } ], - "time": "2024-10-03T09:58:04+00:00" + "time": "2024-10-23T13:25:59+00:00" }, { "name": "symfony/service-contracts", @@ -4973,16 +4973,16 @@ }, { "name": "symfony/validator", - "version": "v6.4.14", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "dc259b85e59a6569e205966d447dec0a7d95facf" + "reference": "7541055cdaf54ff95f0735bf703d313374e8b20b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/dc259b85e59a6569e205966d447dec0a7d95facf", - "reference": "dc259b85e59a6569e205966d447dec0a7d95facf", + "url": "https://api.github.com/repos/symfony/validator/zipball/7541055cdaf54ff95f0735bf703d313374e8b20b", + "reference": "7541055cdaf54ff95f0735bf703d313374e8b20b", "shasum": "" }, "require": { @@ -5050,7 +5050,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.14" + "source": "https://github.com/symfony/validator/tree/v6.4.15" }, "funding": [ { @@ -5066,7 +5066,7 @@ "type": "tidelift" } ], - "time": "2024-11-04T11:33:53+00:00" + "time": "2024-11-08T15:28:48+00:00" }, { "name": "symfony/var-dumper", @@ -6084,16 +6084,16 @@ }, { "name": "ergebnis/json", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json.git", - "reference": "84051b4e243d6a8e2f8271604b11ffa52d29bc7a" + "reference": "7656ac2aa6c2ca4408f96f599e9a17a22c464f69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json/zipball/84051b4e243d6a8e2f8271604b11ffa52d29bc7a", - "reference": "84051b4e243d6a8e2f8271604b11ffa52d29bc7a", + "url": "https://api.github.com/repos/ergebnis/json/zipball/7656ac2aa6c2ca4408f96f599e9a17a22c464f69", + "reference": "7656ac2aa6c2ca4408f96f599e9a17a22c464f69", "shasum": "" }, "require": { @@ -6101,16 +6101,19 @@ "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.18", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.5", - "vimeo/psalm": "^5.26.1" + "rector/rector": "^1.2.10" }, "type": "library", "extra": { @@ -6145,20 +6148,20 @@ "security": "https://github.com/ergebnis/json/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json" }, - "time": "2024-09-27T15:01:05+00:00" + "time": "2024-11-17T11:51:22+00:00" }, { "name": "ergebnis/json-normalizer", - "version": "4.6.0", + "version": "4.7.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-normalizer.git", - "reference": "859fd3cee417f0b10a8e6ffb8dbeb03587106b8b" + "reference": "36d86389095736944a5954ec440552bbe92e425f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/859fd3cee417f0b10a8e6ffb8dbeb03587106b8b", - "reference": "859fd3cee417f0b10a8e6ffb8dbeb03587106b8b", + "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/36d86389095736944a5954ec440552bbe92e425f", + "reference": "36d86389095736944a5954ec440552bbe92e425f", "shasum": "" }, "require": { @@ -6172,21 +6175,34 @@ }, "require-dev": { "composer/semver": "^3.4.3", - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.19", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.5", - "vimeo/psalm": "^5.26.1" + "rector/rector": "^1.2.10" }, "suggest": { "composer/semver": "If you want to use ComposerJsonNormalizer or VersionConstraintNormalizer" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.7-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, "autoload": { "psr-4": { "Ergebnis\\Json\\Normalizer\\": "src/" @@ -6214,20 +6230,20 @@ "security": "https://github.com/ergebnis/json-normalizer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-normalizer" }, - "time": "2024-09-27T15:11:59+00:00" + "time": "2024-11-17T20:34:42+00:00" }, { "name": "ergebnis/json-pointer", - "version": "3.5.0", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-pointer.git", - "reference": "f6ff71e69305b8ab5e4457e374b35dcd0812609b" + "reference": "4fc85d8edb74466d282119d8d9541ec7cffc0798" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/f6ff71e69305b8ab5e4457e374b35dcd0812609b", - "reference": "f6ff71e69305b8ab5e4457e374b35dcd0812609b", + "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/4fc85d8edb74466d282119d8d9541ec7cffc0798", + "reference": "4fc85d8edb74466d282119d8d9541ec7cffc0798", "shasum": "" }, "require": { @@ -6241,15 +6257,18 @@ "ergebnis/phpunit-slow-test-detector": "^2.15.0", "fakerphp/faker": "^1.23.1", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.19", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.1", - "vimeo/psalm": "^5.25.0" + "rector/rector": "^1.2.10" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.6-dev" }, "composer-normalize": { "indent-size": 2, @@ -6284,20 +6303,20 @@ "security": "https://github.com/ergebnis/json-pointer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-pointer" }, - "time": "2024-09-27T15:47:15+00:00" + "time": "2024-11-17T12:37:06+00:00" }, { "name": "ergebnis/json-printer", - "version": "3.6.0", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-printer.git", - "reference": "d2e51379dc62d73017a779a78fcfba568de39e0a" + "reference": "ced41fce7854152f0e8f38793c2ffe59513cdd82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/d2e51379dc62d73017a779a78fcfba568de39e0a", - "reference": "d2e51379dc62d73017a779a78fcfba568de39e0a", + "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/ced41fce7854152f0e8f38793c2ffe59513cdd82", + "reference": "ced41fce7854152f0e8f38793c2ffe59513cdd82", "shasum": "" }, "require": { @@ -6306,16 +6325,19 @@ "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.19", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "~1.2.5", - "vimeo/psalm": "^5.26.1" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.1", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.21", + "rector/rector": "^1.2.10" }, "type": "library", "autoload": { @@ -6346,43 +6368,50 @@ "security": "https://github.com/ergebnis/json-printer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-printer" }, - "time": "2024-09-27T15:19:56+00:00" + "time": "2024-11-17T11:20:51+00:00" }, { "name": "ergebnis/json-schema-validator", - "version": "4.3.0", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json-schema-validator.git", - "reference": "73f938f8995c6ad1e37d2c1dfeaa8336861f9db8" + "reference": "85f90c81f718aebba1d738800af83eeb447dc7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/73f938f8995c6ad1e37d2c1dfeaa8336861f9db8", - "reference": "73f938f8995c6ad1e37d2c1dfeaa8336861f9db8", + "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/85f90c81f718aebba1d738800af83eeb447dc7ec", + "reference": "85f90c81f718aebba1d738800af83eeb447dc7ec", "shasum": "" }, "require": { "ergebnis/json": "^1.2.0", "ergebnis/json-pointer": "^3.4.0", "ext-json": "*", - "justinrainbow/json-schema": "^5.2.12", + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.20", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.5", - "vimeo/psalm": "^5.26.1" + "rector/rector": "^1.2.10" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "4.4-dev" + }, "composer-normalize": { "indent-size": 2, "indent-style": "space" @@ -6416,7 +6445,7 @@ "security": "https://github.com/ergebnis/json-schema-validator/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-schema-validator" }, - "time": "2024-09-27T15:16:33+00:00" + "time": "2024-11-18T06:32:28+00:00" }, { "name": "evenement/evenement", @@ -7015,16 +7044,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.9", + "version": "1.12.11", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "ceb937fb39a92deabc02d20709cf14b2c452502c" + "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ceb937fb39a92deabc02d20709cf14b2c452502c", - "reference": "ceb937fb39a92deabc02d20709cf14b2c452502c", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0d1fc20a962a91be578bcfe7cf939e6e1a2ff733", + "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733", "shasum": "" }, "require": { @@ -7069,7 +7098,7 @@ "type": "github" } ], - "time": "2024-11-10T17:10:04+00:00" + "time": "2024-11-17T14:08:01+00:00" }, { "name": "phpunit/php-code-coverage", @@ -9002,16 +9031,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.13", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "728ae8f4e190133ce99d6d5f0bc1e8c8bd7c7a96" + "reference": "70ab1f65a4516ef741e519ea938e6aa465e6aa36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/728ae8f4e190133ce99d6d5f0bc1e8c8bd7c7a96", - "reference": "728ae8f4e190133ce99d6d5f0bc1e8c8bd7c7a96", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/70ab1f65a4516ef741e519ea938e6aa465e6aa36", + "reference": "70ab1f65a4516ef741e519ea938e6aa465e6aa36", "shasum": "" }, "require": { @@ -9063,7 +9092,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.13" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.15" }, "funding": [ { @@ -9079,7 +9108,7 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:07:50+00:00" + "time": "2024-11-09T06:56:25+00:00" }, { "name": "symfony/event-dispatcher", @@ -9420,7 +9449,7 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -9429,7 +9458,7 @@ "ext-gd": "*", "ext-mbstring": "*" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.1.27" }, diff --git a/docs/4-Configuration.md b/docs/4-Configuration.md index ad22a761a..58b46ae2d 100644 --- a/docs/4-Configuration.md +++ b/docs/4-Configuration.md @@ -589,6 +589,50 @@ When `debug` is enabled, you can easily [dump a variable in your templates](3-Te {{ d(variable) }} # HTML dump ``` +### headers + +You can define custom HTTP headers used by the local preview server. + +It's useful to test custom Content Security or Cache Policy. + +```yaml +headers: + - source: + headers: + - key: + value: "" +``` + +_Example:_ + +```yaml +headers: + - source: /* + headers: + - key: X-Frame-Options + value: "SAMEORIGIN" + - key: X-XSS-Protection + value: "1; mode=block" + - key: X-Content-Type-Options + value: "nosniff" + - key: Content-Security-Policy + value: "default-src 'self'; object-src 'self'; img-src 'self'" + - key: Strict-Transport-Security + value: "max-age=31536000; includeSubDomains; preload" + - source: /images/* + headers: + - key: Cache-Control + value: "public, max-age=31536000" + - source: /assets/* + headers: + - key: Cache-Control + value: "public, max-age=31536000" + - source: /test.html + headers: + - key: Foo + value: "bar" +``` + ## Default configuration Your site configuration (`config.yml`) overrides the following [default configuration](https://github.com/Cecilapp/Cecil/blob/master/config/default.php). diff --git a/resources/server/router.php b/resources/server/router.php index ef59d7238..a4c043218 100644 --- a/resources/server/router.php +++ b/resources/server/router.php @@ -126,15 +126,48 @@ } } -// returns result +/** + * Returns result + */ + +// local server headers header('Etag: ' . md5_file($filename)); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('X-Powered-By: Cecil,PHP/' . phpversion()); +// file type headers foreach ($pathInfo['headers'] as $header) { header($header); } +// custom headers based on path +$headersFile = $_SERVER['DOCUMENT_ROOT'] . '/../' . SERVER_TMP_DIR . '/headers.ini'; +if (file_exists($headersFile)) { + $headersArray = parse_ini_file($headersFile, true); + // joker path tree + $pathParts = explode('/', pathinfo($path, PATHINFO_DIRNAME)); + $previous = ''; + for ($i = 0; $i < \count($pathParts); $i++) { + $headersSectionKey = $previous . \sprintf('/%s/*', trim($pathParts[$i], '\\')); + $previous .= '/' . $pathParts[$i]; + $headersSectionKey = '/' . trim($headersSectionKey, '/'); + if (\array_key_exists($headersSectionKey, $headersArray)) { + foreach ($headersArray[$headersSectionKey] as $key => $value) { + header("$key: " . $value); + } + } + if (empty($pathParts[1])) { + break; + } + } + // exact file path + if (\array_key_exists($path, $headersArray)) { + foreach ($headersArray[$path] as $key => $value) { + header("$key: " . $value); + } + } +} +// file content echo $content; return logger(true); diff --git a/src/Command/Serve.php b/src/Command/Serve.php index 5c12fef75..e25564572 100644 --- a/src/Command/Serve.php +++ b/src/Command/Serve.php @@ -147,7 +147,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln(\sprintf('Build process: %s', implode(' ', $buildProcessArguments)), OutputInterface::VERBOSITY_DEBUG); $buildProcess->run($processOutputCallback); if ($buildProcess->isSuccessful()) { - Util\File::getFS()->dumpFile(Util::joinFile($this->getPath(), self::TMP_DIR, 'changes.flag'), time()); + $this->buildSuccess($output); } if ($buildProcess->getExitCode() !== 0) { return 1; @@ -219,7 +219,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // re-builds $buildProcess->run($processOutputCallback); if ($buildProcess->isSuccessful()) { - Util\File::getFS()->dumpFile(Util::joinFile($this->getPath(), self::TMP_DIR, 'changes.flag'), time()); + $this->buildSuccess($output); } $output->writeln('Server is runnning...'); @@ -238,6 +238,25 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } + /** + * Build success. + */ + private function buildSuccess(OutputInterface $output): void + { + // writes `changes.flag` file + Util\File::getFS()->dumpFile(Util::joinFile($this->getPath(), self::TMP_DIR, 'changes.flag'), time()); + // writes `headers.ini` file + if (null !== $headers = $this->getBuilder()->getConfig()->get('headers')) { + $output->writeln('Writing headers file...'); + foreach ($headers as $header) { + Util\File::getFS()->appendToFile(Util::joinFile($this->getPath(), self::TMP_DIR, 'headers.ini'), "[{$header['source']}]\n"); + foreach ($header['headers'] as $h) { + Util\File::getFS()->appendToFile(Util::joinFile($this->getPath(), self::TMP_DIR, 'headers.ini'), "{$h['key']} = \"{$h['value']}\"\n"); + } + } + } + } + /** * Prepares server's files. *