diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..6244004 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,51 @@ +name: PHP tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + strategy: + matrix: + php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2'] + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + # https://github.com/marketplace/actions/setup-php-action + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, intl + ini-values: post_max_size=256M, max_execution_time=180 + + - uses: actions/checkout@v2 + + - name: Check PHP version + run: php -v + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v2 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + - name: Install dependencies + if: steps.composer-cache.outputs.cache-hit != 'true' + run: composer install --prefer-dist --no-progress --no-suggest + + - name: PHPStan + run: ./vendor/bin/phpstan analyse + + - name: PHPUnit + run: ./vendor/bin/phpunit \ No newline at end of file diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 78b1391..7513392 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -20,7 +20,7 @@ jobs: if: ${{ steps.release.outputs.release_created }} - name: Create release files run: | - zip -r wordpress-multi-env-config.zip wp-config.* + zip -r wordpress-multi-env-config.zip .wp-config.php wp-config.* if: ${{ steps.release.outputs.release_created }} - name: Upload release files uses: svenstaro/upload-release-action@v2 diff --git a/.gitignore b/.gitignore index 325c5cc..fb32d52 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,3 @@ -# OS generated files # -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db -/nbproject -/.project -/.settings -/.buildpath -.idea +vendor +.phpunit.result.cache +composer.lock \ No newline at end of file diff --git a/wp-config.local.php b/.wp-config.php similarity index 100% rename from wp-config.local.php rename to .wp-config.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 792dc7c..e8c9234 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ ## [2.0.1](https://github.com/studio24/wordpress-multi-env-config/compare/v2.0.0...v2.0.1) (2022-08-23) - ### Bug Fixes * 29 - escape * wildcard match ([923c69c](https://github.com/studio24/wordpress-multi-env-config/commit/923c69ceb2044a0338e0b049eecc5db379522e35)) * 32: Can't use array for multisite across multiple environments ([7675bc2](https://github.com/studio24/wordpress-multi-env-config/commit/7675bc275b790e4c7fa1efe6807223d53f758596)) * Create release ZIP file and add docs on contributing and security reports ([057d949](https://github.com/studio24/wordpress-multi-env-config/commit/057d949629c9e24dd2d4da928d12bcf520bb0187)) + +## [1.0.2](https://github.com/studio24/wordpress-multi-env-config/releases/tag/v1.0.2) (2020-07-15) + +* Previous v1 release \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbfbb5e..7575ca7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,11 +17,38 @@ All contributions must be made on a branch and must be merged into the main bran All Pull Requests need at least one approval from the Studio 24 development team. +## Tests + +Simple PHPUnit tests can be added to the `tests/` folder. Please try to add tests for any future changes. + +## Continuous integration + +[GitHub actions](https://github.com/studio24/wordpress-multi-env-config/actions) runs PHPUnit tests and PHPStan for code +quality (checks `tests/*` and the `wp-config.load.php` file). You can set this up locally via: + +``` +composer install +``` + +Run PHPUnit via: + +``` +vendor/bin/phpunit +``` + +Run PHPStan via: + +``` +vendor/bin/phpstan analyse +``` + ## Creating new releases This repo uses [Release Please](https://github.com/marketplace/actions/release-please-action) to automatically create releases, based on [semantic versioning](https://semver.org/). -To create a new release use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) in your commit message. This will automatically create a Release PR, which is kept up to date with further commits and you can merge it to create the new release when you are ready. +To create a new release use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) in your commit message. +On merging new code to the `main` branch this will automatically create a release PR, which you can merge to create the +new release when you are ready. Use the following keywords in your commits: diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..dc34d6e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Studio 24 Ltd + +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. diff --git a/README.md b/README.md index 058119d..2182c45 100644 --- a/README.md +++ b/README.md @@ -1,217 +1,38 @@ # Studio 24 WordPress Multi-Environment Config -This repository contains Studio 24's standard config setup for WordPress, which -loads different config based on current environment. This allows you to have different -site configuration (e.g. debug mode) for different environments (e.g. production and staging). +It is common practise in web development to create multiple environments for a website when testing it, for example +development, staging and production. It is also a common requirement to need different configuration depending on the +environment type, for example different database credentials. + +This repository supports different configuration for different environments. It is Studio 24's standard config setup for +WordPress sites. Credit is due to FocusLabs [EE Master Config](https://github.com/focuslabllc/ee-master-config) who gave me the inspiration for the organisation of the config files. -Please note the current version is v2, if you need to use the older v1 version [please see the v1 release](https://github.com/studio24/wordpress-multi-env-config/releases/tag/v1.0.2). - -## Contributing - -Strata is an Open Source project. Find out more about how to [contribute](CONTRIBUTING.md). - -## Security Issues - -If you discover a security vulnerability within WordPress Multi-Environment Config, please follow our [disclosure procedure](SECURITY.md). - -## How it works - -The system detects what environment the current website is in and loads the relevant config file for that environment. - -By default the environment is defined by the hostname, though you can also set this as an environment variable. - -Config files are then loaded according to the current environment. There is support for loading a local config file -for sensitive data, which is intended to not be committed to version control. - -### Config files - -Up to three different config files are loaded: - -1. **Default configuration** (in `wp-config.default.php`, e.g. shared settings such as `$table_prefix`) -2. **Environment configuration** (in `wp-config.{ENVIRONMENT}.php`, e.g. any setting specific to the environment such as database name or debug mode) -3. **Optional local settings** (in `wp-config.local.php`, e.g. any sensitive settings you do not want to commit to version control, e.g. database password) - -### Environment values - -By default, environment values are: - -* `production` (live website) -* `staging` (test website for client review) -* `development` (local development copy of the website) - -You can add other environment values by adding these to the `wp-config.env.php` file. - -## Setting the environment - -The current environment is detected in one of three ways: - -### Environment variable - -You can set an environment variable called `WP_ENV` to set which environment the website uses in your webserver configuration. - -This is commonly done via Apache in your virtual host declaration: - - SetEnv WP_ENV production - -If you don't use Apache consult your webserver documentation. +## Requirements -### Server hostname +* PHP 7.3+ -The current environment can also be detected from matching the hostname with the domain setup in `wp-config.env.php`. +## Current version -### WP-CLI -If you're using [WP-CLI](http://wp-cli.org/) you can specify your environment using an '.env' file. +The current version is v3, see [upgrading from v2](docs/upgrading.md) for details on how to use the new version. -You need to create a file called `.env` and simply write the current environment in this file as a string. +## Installation -Example: +See [installation](docs/install.md) docs. -``` -development -``` -This file needs to be placed among the wp-config.*.php files (this applies if you keep these files in a sub-folder and the wp-config.php file in the web root). +## Documentation -It is recommended you do not add this file to version control. +* [Docs](docs/README.md) + * [How it works](docs/how-it-works.md) + * [Setting the environment](docs/setting-the-environment.md) + * [Accessing the environment](docs/accessing-the-environment.md) -## The wp-config.env.php file - -You need to edit the `wp-config.env.php` file to define some settings related to the current environment URL. This needs to -be set regardless of which method is used to set the environment, since all methods set the WordPress URL via settings -contained in this file. - -This file contains a simple array, made up of: - -``` -environment names => - domain => The domain name. - This can also be an array of multiple domains. - You can also use a wildcard * to indicate all sub-domains at a domain, which is useful when using - WordPress Multisite. If you use wildcards, set the domain should to a single string, not an array. - path => If WordPress is installed to a sub-folder set it here. - ssl => Whether SSL should be used on this domain. If set, this also sets FORCE_SSL_ADMIN to true. -``` - -Example usage: - -``` -$env = [ - 'production' => [ - 'domain' => 'domain.com', - 'path' => '', - 'ssl' => false, - ], - 'staging' => [ - 'domain' => 'staging.domain.com', - 'path' => '', - 'ssl' => false, - ], - 'development' => [ - 'domain' => 'domain.local', - 'path' => '', - 'ssl' => false, - ], -]; -``` - -If you use localhost for your local test website, just set the development hostname case to `localhost` rather than `domain.local`. - -Example usage when setting a sub-folder, and also serving the live site via SSL: - -``` - 'production' => [ - 'domain' => 'domain.com', - 'path' => 'blog', - 'ssl' => true, - ], -``` - -Example usage for using more than one domain for an environment. - -``` - 'production' => [ - 'domain' => ['domain.com', 'domain2.com'], - 'path' => '', - 'ssl' => false, - ], -``` - -Example usage when using a wildcard for WordPress multi-site. - -``` - 'production' => [ - 'domain' => '*.domain.com', - 'path' => '', - 'ssl' => false, - ], -``` - -## Installing - -Please note this requires PHP5.4 or above. You should really be on PHP5.6 at a minimum! - -1. Download the required files via [wordpress-multi-env-config.zip](https://github.com/studio24/wordpress-multi-env-config/releases/latest/download/wordpress-multi-env-config.zip) -2. First make a backup of your existing `wp-config.php` file. -3. Copy the following files from this repository to your WordPress installation: - -``` -wp-config.default.php -wp-config.env.php -wp-config.php -wp-config.load.php -``` - -3. Set the correct environments you wish to support via the file `wp-config.env.php`, see the documentation above. -4. Create one `wp-config.{environment}.php` file for each environment. You can use the sample files provided in this repository: - -``` -wp-config.development.php -wp-config.production.php -wp-config.staging.php -wp-config.local.php -``` - -5. Review your backup `wp-config.php` file and copy config settings to either the default config file or the environment config files as appropriate. It is suggested to: - * If the setting is the same across all environments, add to `wp-config.default.php` - * If the setting is unique to one environment, add to `wp-config.{environment}.php` - * If the setting is sensitive (e.g. database password) add to `wp-config.local.php` -6. Remember to update the authentication unique keys and salts in `wp-config.default.php` -7. If you use version control exclude `wp-config.local.php`, an example below for Git: - -``` -# .gitignore -wp-config.local.php -``` - -You should now be able to load up the website in each different environment and everything should work just fine! It should now be safe to delete your backup *wp-config.php* file. - -## Moving your config files outside of the document root - -If you want to store your config files outside of the document root for additional security, this is very easy. - -Simply move all the config files except for `wp-config.php` itself into another folder (which can be outside the doc root). -Next amend the require path for `wp-config.load.php` in `wp-config.php` to point to the new location and everything will work just fine! +## Contributing -Example directory structure: +WordPress Multi-Environment Config is an Open Source project. Find out more about how to [contribute](CONTRIBUTING.md). -``` -config/ - wp-config.default.php (Config folder outside of doc root) - wp-config.development.php - wp-config.env.php - wp-config.load.php - wp-config.local.php - wp-config.production.php - wp-config.staging.php -web/ - wp-config.php (Your website doc root, where WordPress is installed) -``` - -Example `wp-config.php` +## Security Issues -``` -/** Load the Studio 24 WordPress Multi-Environment Config. */ -require_once(ABSPATH . '../config/wp-config.load.php'); -``` \ No newline at end of file +If you discover a security vulnerability within WordPress Multi-Environment Config, please follow our [disclosure procedure](SECURITY.md). diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c4c6f84 --- /dev/null +++ b/composer.json @@ -0,0 +1,6 @@ +{ + "require-dev": { + "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^1.9" + } +} diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..82ae669 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,11 @@ +# Studio 24 WordPress Multi-Environment Config documentation + +* [How it works](how-it-works.md) +* [Installation](install.md) + * [The wp-config.env.php file](wp-config-env.md) + * [Setting the environment](setting-the-environment.md) +* [Upgrading](upgrading.md) +* [Accessing the environment](accessing-the-environment.md) +* [Changelog](../CHANGELOG.md) +* [Contributing](../CONTRIBUTING.md) +* [Security issues](../SECURITY.md) \ No newline at end of file diff --git a/docs/accessing-the-environment.md b/docs/accessing-the-environment.md new file mode 100644 index 0000000..0423737 --- /dev/null +++ b/docs/accessing-the-environment.md @@ -0,0 +1,9 @@ +# Accessing the environment + +## Returning the current environment type + +You can use the WordPress function `wp_get_environment_type()` to return the current environment. This defaults to `production` +if the current environment cannot be determined. + +You can see example usage on the [wp_get_environment_type() reference](https://developer.wordpress.org/reference/functions/wp_get_environment_type/) +documentation page. diff --git a/docs/how-it-works.md b/docs/how-it-works.md new file mode 100644 index 0000000..d7444b1 --- /dev/null +++ b/docs/how-it-works.md @@ -0,0 +1,55 @@ +# How it works + +## The problem + +It is common practise in web development to create multiple environments for a website when testing it, for example +development, staging and production. It is also a common requirement to need different configuration depending on the +environment type, for example different database credentials. WordPress has no out-of-the box support for this. + +## Environment types in WordPress + +Since [version 5.5](https://make.wordpress.org/core/2020/07/24/new-wp_get_environment_type-function-in-wordpress-5-5/) +WordPress has supported environment types which allow you to set which environment type your website is running as, to +help toggle functionality in your website and plugins. + +Supported environment types are: + +* `production` +* `staging` +* `development` +* `local` + +Production represents the live website, and is the default if an environment cannot be detected. + +Typically, staging is a test version of a site for client review. + +Development is normally the local test version of a site. However, some people use development to indicate a test version +of a site for internal review (not for review by the client). In this instance, local is used to indicate the local test +version of a site. + +Please note, the intention is for the environment type to represent the type of environment you are running +rather than a specific instance, which is why the WordPress Core team decided to settle on a limited list of environment +types. These should be enough to toggle different functionality. + +## How this package works + +The `wp-config.load.php` file detects what environment the current website is in and loads the relevant config for +that environment. + +### Detecting the environment + +The environment is detected is done in one of the following ways (the first match wins): + +1. Environment variable `WP_ENVIRONMENT_TYPE` is set +2. Environment is detected in an `.env` file +3. Hostname matches an expected list of environment hostnames + +See [installation](install.md) and [wp-config.env.php file](wp-config-env.md) docs for how to set this up. + +### Config files + +Config files are loaded in the following order: + +1. `wp-config.default.php` the default configuration (e.g. shared settings such as `$table_prefix`) +2. `wp-config.{ENVIRONMENT}.php` environment configuration (e.g. any setting specific to the environment such as database name or debug mode) +3. `.wp-config.php`, local settings (e.g. any sensitive settings you do not want to commit to version control such as database password) diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000..068bd82 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,77 @@ +# Installation + +Please note this requires PHP 7.3 or above. + +1. Download the required files via [wordpress-multi-env-config.zip](https://github.com/studio24/wordpress-multi-env-config/releases/latest/download/wordpress-multi-env-config.zip) +2. First make a backup of your existing `wp-config.php` file. + +1. Copy the following files from this repository to your WordPress installation: + +``` +wp-config.default.php +wp-config.env.php +wp-config.php +wp-config.load.php +``` + +3. Set the correct environments you wish to support via the file `wp-config.env.php`, see the [wp-config.env.php file](wp-config-env.md) docs. +4. Decide how to set the environment for your website, see [setting the environment](setting-the-environment.md) for options. +5. Create one `wp-config.{environment}.php` file for each environment. You can use the sample files provided in this repository if you wish: + +``` +wp-config.development.php +wp-config.production.php +wp-config.staging.php +``` + +6. Add the local-only config file if you wish to use it for storing sensitive settings (this step is optional): + +``` +.wp-config.php +``` + +7. If you use Git version control exclude `.wp-config.php` in your `.gitignore` file: + +``` +.wp-config.php +``` + +8. Review your backup `wp-config.php` file and copy config settings to either the default config file or the environment config files as appropriate. It is suggested to: + * If the setting is the same across all environments, add to `wp-config.default.php` + * If the setting is unique to one environment, add to `wp-config.{environment}.php` + * If the setting is sensitive (e.g. database password) add to `.wp-config.php` +9. Remember to update the authentication unique keys and salts in `wp-config.default.php` + + +You should now be able to load up the website in each different environment and everything should work just fine! It should now be safe to delete your backup *wp-config.php* file. + +## Moving your config files outside of the document root + +It is recommended to store your config files outside of the document root for additional security. + +First, simply move all the config files except for `wp-config.php` itself into another folder (which must be outside the +document root). + +Example directory structure: + +``` +├── config/ (config folder outside of doc root) +│ ├── .wp-config.php +│ ├── wp-config.default.php +│ ├── wp-config.development.php +│ ├── wp-config.env.php +│ ├── wp-config.load.php +│ ├── wp-config.production.php +│ └── wp-config.staging.php +└── web/ (your website document root, where WordPress is installed) + └── wp-config.php +``` + +Next, amend the require path for the `wp-config.load.php` file in `wp-config.php` to point to the new location and everything will work just fine! + +Example `wp-config.php`: + +``` +/** Load the Studio 24 WordPress Multi-Environment Config. */ +require_once(ABSPATH . '../config/wp-config.load.php'); +``` \ No newline at end of file diff --git a/docs/setting-the-environment.md b/docs/setting-the-environment.md new file mode 100644 index 0000000..8cf2cc7 --- /dev/null +++ b/docs/setting-the-environment.md @@ -0,0 +1,54 @@ +# Setting the environment + +The current environment is detected in one of three ways: + +1. Environment variable `WP_ENVIRONMENT_TYPE` is set +2. Environment is detected in an `.env` file +3. Hostname matches an expected list of environment hostnames + +## Environment variable + +You can set an environment variable called `WP_ENVIRONMENT_TYPE` to set which environment the website uses in your +webserver configuration. + +### Apache + +This is commonly done via Apache in your virtual host declaration: + +``` +SetEnv WP_ENVIRONMENT_TYPE development +``` + +If you don't use Apache consult your webserver documentation. + +### Command line + +If you are using WP CLI then you can set an environment variable on the command line via: + +``` +export WP_ENVIRONMENT_TYPE="development" +``` + +## .env file + +You can also specify your environment using an `.env` file. Simply create a file called `.env` and set the environment using +the following format: + +``` +WP_ENVIRONMENT_TYPE=development +``` + +This file must either exist in the same folder as `wp-config.load.php` or the parent folder (this is useful if you store +config files in the `config/` sub-folder. + +It is recommended you do not add this file to version control. You can exclude the file in your `.gitignore` file via: + +``` +.env +``` + +## Server hostname + +The current environment can also be detected from matching the hostname with the domain setup in `wp-config.env.php`. + +See the [wp-config.env.php file](wp-config-env.md). \ No newline at end of file diff --git a/docs/upgrading.md b/docs/upgrading.md new file mode 100644 index 0000000..d6b4cb3 --- /dev/null +++ b/docs/upgrading.md @@ -0,0 +1,60 @@ +# Upgrading + +## Upgrade from v2 + +To upgrade please follow these steps. + +### wp-config.local.php + +WordPress now includes `local` as a valid environment type. Therefore, `wp-config.local.php` is no longer used for a +local-only sensitive config and is used instead as a valid environment config file (that can be comitted to git). + +In its place `.wp-config.php` is now used for storing sensitive config settings. + +1. If you are using `wp-config.local.php` for sensitive config settings, rename this file to `.wp-config.php` +2. Remove `wp-config.local.php` from your `.gitignore` file if it exists +3. Add the following to your `.gitignore` file: + +``` +# .gitignore +.wp-config.php +``` + +### WP_ENV + +In v2 this package used the environment variable `WP_ENV` to set the current environment. With the support of environment +types in WordPress this has now changed to `WP_ENVIRONMENT_TYPE` + +1. Update your environment variable from `WP_ENV` to `WP_ENVIRONMENT_TYPE` + +### Removed custom PHP constants + +If you have any code that relies on the PHP constant `WP_ENV` please update to use `wp_get_environment_type()` to return +the current environment type. + +The following custom PHP constants have been removed since they are no longer required: +* `WP_ENV` +* `WP_ENV_DOMAIN` +* `WP_ENV_PATH` +* `WP_ENV_SSL` + +### .env file + +If you use an .env file to set your environment type, the format of this has changed to match the standard dotenv format. + +Old version: + +``` +development +``` + +New version: + +``` +WP_ENVIRONMENT_TYPE=development +``` + +### CLI --env param + +Removed the `--env` CLI parameter since this does not work reliably. Instead, set the environment in the `.env` file. See +[setting the environment](setting-the-environment.md). \ No newline at end of file diff --git a/docs/wp-config-env.md b/docs/wp-config-env.md new file mode 100644 index 0000000..6ff6e0b --- /dev/null +++ b/docs/wp-config-env.md @@ -0,0 +1,78 @@ +# The wp-config.env.php file + +You need to edit the `wp-config.env.php` file to define some settings related to the current environment URL. This needs to +be set regardless of which method is used to set the environment, since all methods set the WordPress URL via settings +contained in this file. + +This file contains a simple array, made up of: + +``` +environment names => + domain => The domain name. + This can also be an array of multiple domains. + You can also use a wildcard * to indicate all sub-domains at a domain, which is useful when using + WordPress Multisite. If you use wildcards, set the domain should to a single string, not an array. + path => If WordPress is installed to a sub-folder set it here. + ssl => Whether SSL should be used on this domain. If set, this also sets FORCE_SSL_ADMIN to true. +``` + +Supported environment types are: + +* `production` +* `staging` +* `development` +* `local` + +Example usage: + +``` +$env = [ + 'production' => [ + 'domain' => 'domain.com', + 'path' => '', + 'ssl' => true, + ], + 'staging' => [ + 'domain' => 'staging.domain.com', + 'path' => '', + 'ssl' => true, + ], + 'development' => [ + 'domain' => 'domain.local', + 'path' => '', + 'ssl' => false, + ], +]; +``` + +If you use localhost for your local test website, just set the development hostname case to `localhost` rather than `domain.local`. + +Example usage when setting a sub-folder, and also serving the live site via SSL: + +``` + 'production' => [ + 'domain' => 'domain.com', + 'path' => 'blog', + 'ssl' => true, + ], +``` + +Example usage for using more than one domain for an environment. + +``` + 'production' => [ + 'domain' => ['domain.com', 'domain2.com'], + 'path' => '', + 'ssl' => false, + ], +``` + +Example usage when using a wildcard for WordPress multi-site. Please note the wildcard `*` must appear at the start of the domain string. + +``` + 'production' => [ + 'domain' => '*.domain.com', + 'path' => '', + 'ssl' => false, + ], +``` diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..7daa289 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,5 @@ +parameters: + level: 5 + paths: + - wp-config.load.php + - tests \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..5c85144 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,21 @@ + + + + + + + + + + + + tests + + + + diff --git a/tests/EnvironmentTypeTest.php b/tests/EnvironmentTypeTest.php new file mode 100644 index 0000000..110bbaf --- /dev/null +++ b/tests/EnvironmentTypeTest.php @@ -0,0 +1,45 @@ +assertTrue($bootstrap->validEnvironment('development')); + $this->assertTrue($bootstrap->validEnvironment('staging')); + $this->assertTrue($bootstrap->validEnvironment('production')); + $this->assertFalse($bootstrap->validEnvironment('stage')); + $this->assertFalse($bootstrap->validEnvironment('PRODUCTION')); + } + + public function testSetEnvType(): void + { + $bootstrap = new MultiEnvConfig_Bootstrap(); + $bootstrap->setEnvironmentType('stage'); + $this->assertFalse($bootstrap->hasEnvironment()); + + $bootstrap->setEnvironmentType('FISH'); + $this->assertFalse($bootstrap->hasEnvironment()); + $this->assertEmpty($bootstrap->getEnvironmentType()); + + $bootstrap->setEnvironmentType('production'); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('production', $bootstrap->getEnvironmentType()); + } + + public function testCustomSettings(): void + { + $settings = [ + 'production' => [ + 'domain' => 'test.com', + 'path' => '', + 'ssl' => true, + ], + ]; + $bootstrap = new MultiEnvConfig_Bootstrap($settings); + $this->assertEquals($settings, $bootstrap->getEnvironmentSettings()); + } + +} + diff --git a/tests/LoadFromEnvFileTest.php b/tests/LoadFromEnvFileTest.php new file mode 100644 index 0000000..6afad42 --- /dev/null +++ b/tests/LoadFromEnvFileTest.php @@ -0,0 +1,31 @@ +loadFromEnvFile(__DIR__ . '/env-files/.env'); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('staging', $bootstrap->getEnvironmentType()); + } + + public function testInvalid1(): void + { + $bootstrap = new MultiEnvConfig_Bootstrap(); + $bootstrap->loadFromEnvFile(__DIR__ . '/env-files/.env.invalid1'); + $this->assertFalse($bootstrap->hasEnvironment()); + $this->assertEmpty($bootstrap->getEnvironmentType()); + } + + public function testInvalid2(): void + { + $bootstrap = new MultiEnvConfig_Bootstrap(); + $bootstrap->loadFromEnvFile(__DIR__ . '/env-files/.env.invalid2'); + $this->assertFalse($bootstrap->hasEnvironment()); + $this->assertEmpty($bootstrap->getEnvironmentType()); + } + +} + diff --git a/tests/LoadFromEnvironmentVariableTest.php b/tests/LoadFromEnvironmentVariableTest.php new file mode 100644 index 0000000..749a410 --- /dev/null +++ b/tests/LoadFromEnvironmentVariableTest.php @@ -0,0 +1,27 @@ +loadFromEnvironmentVariable(); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('staging', $bootstrap->getEnvironmentType()); + } + + public function testSetInvalid(): void + { + $bootstrap = new MultiEnvConfig_Bootstrap(); + + putenv('WP_ENVIRONMENT_TYPE=stage'); + $bootstrap->loadFromEnvironmentVariable(); + $this->assertFalse($bootstrap->hasEnvironment()); + $this->assertEmpty($bootstrap->getEnvironmentType()); + } + +} + diff --git a/tests/LoadFromHostnameTest.php b/tests/LoadFromHostnameTest.php new file mode 100644 index 0000000..c5d121e --- /dev/null +++ b/tests/LoadFromHostnameTest.php @@ -0,0 +1,111 @@ +assertTrue($bootstrap->isWildcard('*.test.com')); + $this->assertTrue($bootstrap->isWildcard('*.subdomain.test.com')); + $this->assertTrue($bootstrap->isWildcard('*.subdomain.www.test.com')); + $this->assertFalse($bootstrap->isWildcard('www.*.test.com')); + $this->assertFalse($bootstrap->isWildcard('www.test.com')); + $this->assertFalse($bootstrap->isWildcard('test.*')); + } + + public function testMatchWildcard(): void + { + $bootstrap = new MultiEnvConfig_Bootstrap(); + $this->assertTrue($bootstrap->matchWildcardDomain('*.test.com', 'www.test.com')); + $this->assertTrue($bootstrap->matchWildcardDomain('*.test.com', 'www2.test.com')); + $this->assertTrue($bootstrap->matchWildcardDomain('*.test.com', 'fishcake.test.com')); + $this->assertFalse($bootstrap->matchWildcardDomain('*.test.com', 'www.test2.com')); + } + + public function testValid(): void + { + $settings = [ + 'production' => [ + 'domain' => 'www.test.com', + 'path' => '', + 'ssl' => true, + ], + 'staging' => [ + 'domain' => 'staging.test.com', + 'path' => '', + 'ssl' => true, + ], + ]; + $bootstrap = new MultiEnvConfig_Bootstrap($settings); + $bootstrap->loadFromHostname('staging.test.com'); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('staging', $bootstrap->getEnvironmentType()); + } + + public function testInvalid(): void + { + $settings = [ + 'production' => [ + 'domain' => 'www.test.com', + 'path' => '', + 'ssl' => true, + ], + 'staging' => [ + 'domain' => 'staging.test.com', + 'path' => '', + 'ssl' => true, + ], + ]; + $bootstrap = new MultiEnvConfig_Bootstrap($settings); + $bootstrap->loadFromHostname('fishcake.test.com'); + $this->assertFalse($bootstrap->hasEnvironment()); + $this->assertEmpty($bootstrap->getEnvironmentType()); + } + + public function testWildcard(): void + { + $settings = [ + 'production' => [ + 'domain' => 'www.test.com', + 'path' => '', + 'ssl' => true, + ], + 'staging' => [ + 'domain' => '*.staging-sites.com', + 'path' => '', + 'ssl' => true, + ], + ]; + $bootstrap = new MultiEnvConfig_Bootstrap($settings); + $bootstrap->loadFromHostname('mysite.staging-sites.com'); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('staging', $bootstrap->getEnvironmentType()); + $this->assertNotEquals('*.staging-sites.com', $bootstrap->getEnvironmentHostname()); + $this->assertEquals('mysite.staging-sites.com', $bootstrap->getEnvironmentHostname()); + } + + public function testArray(): void + { + $settings = [ + 'production' => [ + 'domain' => ['www.test.com', 'www2.test.com', 'www3.test.com'], + 'path' => '', + 'ssl' => true, + ], + 'staging' => [ + 'domain' => '*.staging-sites.com', + 'path' => '', + 'ssl' => true, + ], + ]; + $bootstrap = new MultiEnvConfig_Bootstrap($settings); + $bootstrap->loadFromHostname('www2.test.com'); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('production', $bootstrap->getEnvironmentType()); + $this->assertNotEquals('www.test.com', $bootstrap->getEnvironmentHostname()); + $this->assertEquals('www2.test.com', $bootstrap->getEnvironmentHostname()); + } + +} + diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..2ad5277 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,4 @@ +loadFromEnvFile(null, __DIR__); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('staging', $bootstrap->getEnvironmentType()); + } + +} + diff --git a/tests/env-files/sub-folder/LoadDefaultEnvFileOneFolderAboveTest.php b/tests/env-files/sub-folder/LoadDefaultEnvFileOneFolderAboveTest.php new file mode 100644 index 0000000..4088e5c --- /dev/null +++ b/tests/env-files/sub-folder/LoadDefaultEnvFileOneFolderAboveTest.php @@ -0,0 +1,14 @@ +loadFromEnvFile(null, __DIR__); + $this->assertTrue($bootstrap->hasEnvironment()); + $this->assertEquals('staging', $bootstrap->getEnvironmentType()); + } +} + diff --git a/tests/env-files/sub-folder/sub-folder2/LoadDefaultEnvFileTwoFoldersAboveTest.php b/tests/env-files/sub-folder/sub-folder2/LoadDefaultEnvFileTwoFoldersAboveTest.php new file mode 100644 index 0000000..a2c9386 --- /dev/null +++ b/tests/env-files/sub-folder/sub-folder2/LoadDefaultEnvFileTwoFoldersAboveTest.php @@ -0,0 +1,14 @@ +loadFromEnvFile(null, __DIR__); + $this->assertFalse($bootstrap->hasEnvironment()); + $this->assertEmpty($bootstrap->getEnvironmentType()); + } +} + diff --git a/wp-config.development.php b/wp-config.development.php index 82286fc..b9cc652 100644 --- a/wp-config.development.php +++ b/wp-config.development.php @@ -19,7 +19,7 @@ /** MySQL database username */ define('DB_USER', ''); -/** MySQL database password - set in wp-config.local.php */ +/** MySQL database password - set in .wp-config.php */ /** * For developers: WordPress debugging mode. diff --git a/wp-config.env.php b/wp-config.env.php index 4fa0c48..8c636ab 100644 --- a/wp-config.env.php +++ b/wp-config.env.php @@ -7,7 +7,7 @@ /** - * Define array of environment URLs + * Define array of environment settings * * Array of: * environment names => @@ -24,12 +24,12 @@ 'production' => [ 'domain' => 'domain.com', 'path' => '', - 'ssl' => false, + 'ssl' => true, ], 'staging' => [ 'domain' => 'staging.domain.com', 'path' => '', - 'ssl' => false, + 'ssl' => true, ], 'development' => [ 'domain' => 'domain.local', diff --git a/wp-config.load.php b/wp-config.load.php index 4a88c42..f5f83f7 100644 --- a/wp-config.load.php +++ b/wp-config.load.php @@ -1,4 +1,6 @@ */ -function s24_load_environment_config() { +/** + * Custom exceptions for any fatal errors + */ +class MultiEnvConfig_Exception extends Exception { } - /** - * Setup environment - */ - // Set env if set via environment variable - if (getenv('WP_ENV') !== false) { - define('WP_ENV', preg_replace('/[^a-z]/', '', getenv('WP_ENV'))); - } +/** + * Class to bootstrap the environment and load the appropriate config + */ +final class MultiEnvConfig_Bootstrap { - // Set env via --env= argument if running via WP-CLI - if (!defined('WP_ENV') && PHP_SAPI == "cli" && defined('WP_CLI_ROOT')) { + private $environmentType = null; + private $environmentHostname = null; + private $environmentSettings = []; - // We need to set $argv as global to be able to access it - global $argv; + /** + * Load environments + * @param array|null $environmentSettings + * @throws MultiEnvConfig_Exception + */ + public function __construct(?array $environmentSettings = null) + { + if (null === $environmentSettings) { + require __DIR__ . '/wp-config.env.php'; - if (isset($argv)) { - foreach ($argv as $arg) { - if (preg_match('/--env=(.+)/', $arg, $m)) { - define('WP_ENV', preg_replace('/[^a-z]/', '', $m[1])); - break; - } + /* @phpstan-ignore-next-line */ + if (!isset($env) || !is_array($env)) { + throw new MultiEnvConfig_Exception('$env array not detected, you must set this in wp-config.env.php'); } + /* @phpstan-ignore-next-line */ + $environmentSettings = $env; } - // Also support via .env file in config directory - if (!defined('WP_ENV')) { - if (file_exists(__DIR__ . '/.env')) { - $environment = trim(file_get_contents(__DIR__ . '/.env')); - define('WP_ENV', preg_replace('/[^a-z]/', '', $environment)); - } + $this->environmentSettings = $environmentSettings; + } + + /** + * Is this environment type allowed? + * @see https://developer.wordpress.org/reference/functions/wp_get_environment_type/ + * @param string $name Environment type + * @return bool + */ + function validEnvironment(string $name): bool + { + $environments = [ + 'local', + 'development', + 'staging', + 'production', + ]; + return in_array($name, $environments); + } + + /** + * Whether the current environment type is set + * @return bool + */ + public function hasEnvironment(): bool + { + if (null === $this->environmentType) { + return false; } + if (!$this->validEnvironment((string) $this->environmentType)) { + $this->environmentType = null; + return false; + } + return true; } - // Define ENV from hostname - if (!defined('WP_ENV')) { - if (isset($_SERVER['HTTP_X_FORWARDED_HOST']) && !empty($_SERVER['HTTP_X_FORWARDED_HOST'])) { - $hostname = strtolower(filter_var($_SERVER['HTTP_X_FORWARDED_HOST'], FILTER_SANITIZE_STRING)); - } else { - $hostname = strtolower(filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_STRING)); + /** + * Set environment type + * @param string $type + * @return void + */ + public function setEnvironmentType(string $type): void + { + if ($this->validEnvironment($type)) { + $this->environmentType = $type; } } - // Load environments - require __DIR__ . '/wp-config.env.php'; + /** + * Return current environment type + * @return string|null + */ + public function getEnvironmentType(): ?string + { + return $this->environmentType; + } - if (!isset($env) || !is_array($env)) { - throw new Exception('$env array not detected, you must set this in wp-config.env.php'); + /** + * Return the environment settings + * @return array + */ + public function getEnvironmentSettings(): array + { + return $this->environmentSettings; } - // Set environment constants - if (defined('WP_ENV')) { - if (isset($env[WP_ENV])) { - define('WP_ENV_DOMAIN', $env[WP_ENV]['domain']); - define('WP_ENV_PATH', trim($env[WP_ENV]['path'], '/')); - define('WP_ENV_SSL', (bool) $env[WP_ENV]['ssl']); + /** + * Return environment hostname, or null if not set + * @return string|null + */ + public function getEnvironmentHostname(): ?string + { + return $this->environmentHostname; + } + + /** + * Detect environment from environment variable + * @return void + */ + public function loadFromEnvironmentVariable(): void + { + $environmentType = getenv('WP_ENVIRONMENT_TYPE'); + if (false !== $environmentType) { + $this->setEnvironmentType($environmentType); } + } - } else { + /** + * Detect environment from .env file + * @param string|null $filepath + * @param string|null $dir + * @return void + */ + public function loadFromEnvFile(?string $filepath = null, ?string $dir = null): void + { + if (null === $filepath) { + if (null == $dir) { + $dir = __DIR__; + } + if (file_exists($dir . '/.env')) { + $filepath = $dir . '/.env'; + } elseif (file_exists($dir . '/../.env')) { + $filepath = $dir . '/../.env'; + } else { + return; + } + } + $envFile = file_get_contents($filepath); + if ($envFile !== false && preg_match('/WP_ENVIRONMENT_TYPE=(.+)/', $envFile, $m)) { + $this->setEnvironmentType($m[1]); + } + } - // Detect environment from hostname - foreach ($env as $environment => $env_vars) { - if (!isset($env_vars['domain'])) { - throw new Exception('You must set the domain value in your environment array, see wp-config.env.php'); + /** + * Detect environment from hostname + * @param string|null $hostname + * @return void + */ + public function loadFromHostname(?string $hostname = null): void + { + if (null === $hostname) { + if (isset($_SERVER['HTTP_X_FORWARDED_HOST']) && !empty($_SERVER['HTTP_X_FORWARDED_HOST'])) { + $hostname = strtolower(filter_var($_SERVER['HTTP_X_FORWARDED_HOST'], FILTER_SANITIZE_STRING)); + } else { + $hostname = strtolower(filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_STRING)); } - $domain = $env_vars['domain']; - - $wildcard = (is_string($domain) && strpos($domain, '*') !== false) ? true : false; - if ($wildcard) { - $match = '/' . str_replace('\*', '([^.]+)', preg_quote($domain, '/')) . '/'; - if (preg_match($match, $hostname, $m)) { - if (!defined('WP_ENV')) { - define('WP_ENV', preg_replace('/[^a-z]/', '', $environment)); - } - define('WP_ENV_DOMAIN', str_replace('*', $m[1], $domain)); - if (isset($env_vars['ssl'])) { - define('WP_ENV_SSL', (bool)$env_vars['ssl']); - } else { - define('WP_ENV_SSL', false); - } - if (isset($env_vars['path'])) { - define('WP_ENV_PATH', trim($env_vars['path'], '/')); - } - - /** - * Define WordPress Site URLs - */ - $protocol = (WP_ENV_SSL) ? 'https://' : 'http://'; - $path = (defined('WP_ENV_PATH')) ? '/' . trim(WP_ENV_PATH, '/') : ''; - - if (!defined('WP_SITEURL')) { - define('WP_SITEURL', $protocol . trim(WP_ENV_DOMAIN, '/') . $path); - } - if (!defined('WP_HOME')) { - define('WP_HOME', $protocol . trim(WP_ENV_DOMAIN, '/') . $path); - } - break; - } + } + if (empty($hostname)) { + return; + } + + // Try to match hostname against environment domain + foreach ($this->getEnvironmentSettings() as $environment => $envVars) { + if (!isset($envVars['domain'])) { + throw new MultiEnvConfig_Exception('You must set the domain value in your environment array, see wp-config.env.php'); } - if (!is_array($domain)) { - $domain = [$domain]; + + $domains = $envVars['domain']; + if (!is_array($domains)) { + $domains = [$domains]; } - foreach ($domain as $domain_name) { - if ($hostname === $domain_name) { - if (!defined('WP_ENV')) { - define('WP_ENV', preg_replace('/[^a-z]/', '', $environment)); - } - define('WP_ENV_DOMAIN', $domain_name); - if (isset($env_vars['ssl'])) { - define('WP_ENV_SSL', (bool)$env_vars['ssl']); - } else { - define('WP_ENV_SSL', false); - } - if (isset($env_vars['path'])) { - define('WP_ENV_PATH', trim($env_vars['path'], '/')); - } - - /** - * Define WordPress Site URLs - */ - $protocol = (WP_ENV_SSL) ? 'https://' : 'http://'; - $path = (defined('WP_ENV_PATH')) ? '/' . trim(WP_ENV_PATH, '/') : ''; - - if (!defined('WP_SITEURL')) { - define('WP_SITEURL', $protocol . trim(WP_ENV_DOMAIN, '/') . $path); - } - if (!defined('WP_HOME')) { - define('WP_HOME', $protocol . trim(WP_ENV_DOMAIN, '/') . $path); - } + + foreach ($domains as $domain) { + if ($this->isWildcard($domain) && $this->matchWildcardDomain($domain, $hostname)) { + $this->setEnvironmentType($environment); + break; + } elseif ($hostname === $domain) { + $this->setEnvironmentType($environment); break; } + $this->environmentHostname = $hostname; } } } - if (!defined('WP_ENV')) { - throw new Exception("Cannot determine current environment"); - } - if (!defined('WP_ENV_DOMAIN')) { - throw new Exception("Cannot determine current environment domain, make sure this is set in wp-config.env.php"); + /** + * Whether a URL contains a wildcard pattern + * @param string $domain + * @return bool + */ + public function isWildcard(string $domain): bool + { + return (preg_match('/^\*/', $domain) === 1); } - if (!defined('WP_ENV_SSL')) { - define('WP_ENV_SSL', false); + + /** + * Whether the hostname matches a wildcard domain + * @param string $domain + * @param string $hostname + * @return bool + */ + public function matchWildcardDomain(string $domain, string $hostname): bool + { + $match = '/' . str_replace('\*', '([^.]+)', preg_quote($domain, '/')) . '/'; + return (preg_match($match, $hostname, $m) === 1); } - if (WP_ENV_SSL && (!defined('FORCE_SSL_ADMIN'))) { - define('FORCE_SSL_ADMIN', true); + + /** + * Return envUrls array for the current environment + * @return array|null + */ + public function getCurrentEnvUrls(): ?array + { + $settings = $this->getEnvironmentSettings(); + if (isset($settings[$this->getEnvironmentType()])) { + return $settings[$this->getEnvironmentType()]; + } + return null; } - // Define W3 Total Cache hostname - if (defined('WP_CACHE')) { - define('COOKIE_DOMAIN', $hostname); + /** + * Set WordPress constants from current environment + * @return void + * @throws MultiEnvConfig_Exception + */ + public function setWordPressConstants(): void + { + if (!$this->hasEnvironment()) { + throw new MultiEnvConfig_Exception('Current environment is not set, please ensure you have set the environment type correctly'); + } + + // Load URLs config for the environment + $envUrls = $this->getCurrentEnvUrls(); + if (null === $envUrls) { + throw new MultiEnvConfig_Exception(sprintf('Cannot detect current environment %s in wp-config.env.php', $this->getEnvironmentType())); + } + if (null !== $this->getEnvironmentHostname()) { + $hostname = $this->getEnvironmentHostname(); + } else { + $hostname = $envUrls['domain']; + } + $ssl = (bool) $envUrls['ssl']; + $protocol = ($ssl) ? 'https://' : 'http://'; + $path = !empty($envUrls['path']) ? '/' . trim($envUrls['path'], '/') : ''; + + // @see https://developer.wordpress.org/apis/wp-config-php/#wp-environment-type + define('WP_ENVIRONMENT_TYPE', $this->getEnvironmentType()); + + // @see https://developer.wordpress.org/apis/wp-config-php/#wp-siteurl + if (!defined('WP_SITEURL')) { + define('WP_SITEURL', $protocol . rtrim($hostname, '/') . $path); + } + + // @see https://developer.wordpress.org/apis/wp-config-php/#blog-address-url + if (!defined('WP_HOME')) { + define('WP_HOME', $protocol . rtrim($hostname, '/') . $path); + } + + // @see https://developer.wordpress.org/apis/wp-config-php/#require-ssl-for-admin-and-logins + if (!defined('FORCE_SSL_ADMIN') && $ssl) { + define('FORCE_SSL_ADMIN', true); + } + + // @see https://developer.wordpress.org/apis/wp-config-php/#set-cookie-domain + if (!defined('COOKIE_DOMAIN')) { + define('COOKIE_DOMAIN', $hostname); + } } + } -s24_load_environment_config(); /** * Load config */ +$bootstrap = new MultiEnvConfig_Bootstrap(); +$bootstrap->loadFromEnvironmentVariable(); +if (!$bootstrap->hasEnvironment()) { + $bootstrap->loadFromEnvFile(); +} +if (!$bootstrap->hasEnvironment()) { + $bootstrap->loadFromHostname(); +} +$bootstrap->setWordPressConstants(); + // 1st - Load default config require __DIR__ . '/wp-config.default.php'; // 2nd - Load config file for current environment -require __DIR__ . '/wp-config.' . WP_ENV . '.php'; +require __DIR__ . '/wp-config.' . $bootstrap->getEnvironmentType() . '.php'; -// 3rd - Load local config file with any sensitive settings -if (file_exists( __DIR__ . '/wp-config.local.php')) { - require __DIR__ . '/wp-config.local.php'; +// 3rd - Optionally load local-only config file with any sensitive settings +if (file_exists(__DIR__ . '/.wp-config.php')) { + require __DIR__ . '/.wp-config.php'; } diff --git a/wp-config.production.php b/wp-config.production.php index d50c04a..db77a7c 100644 --- a/wp-config.production.php +++ b/wp-config.production.php @@ -19,7 +19,7 @@ /** MySQL database username */ define('DB_USER', ''); -/** MySQL database password - set in wp-config.local.php */ +/** MySQL database password - set in .wp-config.php */ /** * For developers: WordPress debugging mode. diff --git a/wp-config.staging.php b/wp-config.staging.php index cacbcd1..8538d9d 100644 --- a/wp-config.staging.php +++ b/wp-config.staging.php @@ -19,7 +19,7 @@ /** MySQL database username */ define('DB_USER', ''); -/** MySQL database password - set in wp-config.local.php */ +/** MySQL database password - set in .wp-config.php */ /** * For developers: WordPress debugging mode.