├── .editorconfig ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── composer.lock └── wp-stage-switcher.php /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 2.2.0: May 31st, 2022 2 | * Multisite refactor 3 | 4 | ### 2.1.1: October 21st, 2021 5 | * Add `composer/installers` 2.x support 6 | 7 | ### 2.1.0: March 29th, 2019 8 | * Add CSS class for current environment to top menu item 9 | * Fix Admin Bar menu visibility logic from 'and' to 'or' condition 10 | * Remove jwage/purl dependency 11 | 12 | ### 2.0.0: February 10th, 2016 13 | * Rewrite plugin, require Composer 14 | 15 | ### 1.0.3: August 19th, 2014 16 | * Only show menu item for administrators, add filter for visibility control 17 | 18 | ### 1.0.2: July 22nd, 2014 19 | * Add support for sub-domain subsites in multisite 20 | 21 | ### 1.0.1: April 7th, 2014 22 | * Directory indepenent, enable GitHub Updater 23 | 24 | ### 1.0.0: January 13th, 2014 25 | * Initial release 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) Ben Word 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WordPress Stage Switcher 2 | [![Packagist](https://img.shields.io/packagist/v/roots/wp-stage-switcher.svg?style=flat-square)](https://packagist.org/packages/roots/wp-stage-switcher) 3 | [![Packagist Downloads](https://img.shields.io/packagist/dt/roots/wp-stage-switcher.svg?style=flat-square)](https://packagist.org/packages/roots/wp-stage-switcher) 4 | 5 | A WordPress plugin that allows you to switch between different environments from the admin bar. 6 | 7 | ![WordPress Stage Switcher](https://cdn.roots.io/app/uploads/plugin-stage-switcher.png) 8 | 9 | ## Requirements 10 | 11 | You'll need to have `ENVIRONMENTS` and `WP_ENV` defined in your WordPress config. 12 | 13 | The `ENVIRONMENTS` constant must be a serialized array of `'environment' => 'url'` elements: 14 | 15 | ```php 16 | $envs = [ 17 | 'development' => 'http://example.dev', 18 | 'staging' => 'http://staging.example.com', 19 | 'production' => 'http://example.com' 20 | ]; 21 | define('ENVIRONMENTS', serialize($envs)); 22 | ``` 23 | 24 | Note: the `serialize()` call is not needed on PHP 7.0 or newer. 25 | 26 | `WP_ENV` must be defined as the current environment: 27 | 28 | ```php 29 | define('WP_ENV', 'development'); 30 | ``` 31 | 32 | If you use [Bedrock](https://github.com/roots/bedrock), `WP_ENV` is already defined in the config. 33 | 34 | ## Installation 35 | 36 | This plugin must be installed via Composer. Add wp-stage-switcher to your project's dependencies: 37 | 38 | ```sh 39 | composer require roots/wp-stage-switcher 40 | ``` 41 | 42 | Or manually add it to your `composer.json`: 43 | 44 | ```json 45 | "require": { 46 | "php": ">=7.1", 47 | "roots/wordpress": "5.1.1", 48 | "roots/wp-stage-switcher": "~2.1" 49 | } 50 | ``` 51 | 52 | ## Support 53 | 54 | Use the [Roots Discourse](http://discourse.roots.io/) to ask questions and get support. 55 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roots/wp-stage-switcher", 3 | "type": "wordpress-plugin", 4 | "license": "MIT", 5 | "description": "WordPress plugin that allows you to switch between different environments from the admin bar", 6 | "homepage": "https://roots.io/plugin/stage-switcher/", 7 | "authors": [ 8 | { 9 | "name": "Ben Word", 10 | "email": "ben@benword.com", 11 | "homepage": "https://github.com/retlehs" 12 | }, 13 | { 14 | "name": "Scott Walkinshaw", 15 | "email": "scott.walkinshaw@gmail.com", 16 | "homepage": "https://github.com/swalkinshaw" 17 | } 18 | ], 19 | "keywords": [ 20 | "wordpress" 21 | ], 22 | "support": { 23 | "issues": "https://github.com/roots/wp-stage-switcher/issues", 24 | "forum": "https://discourse.roots.io" 25 | }, 26 | "require": { 27 | "php": ">=5.4.0", 28 | "composer/installers": "~1.0 || ~2.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "f39947e26d0a887ccdf8a53bf36ecfb0", 8 | "packages": [ 9 | { 10 | "name": "composer/installers", 11 | "version": "v1.0.23", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/composer/installers.git", 15 | "reference": "6213d900e92647831f7a406d5c530ea1f3d4360e" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/composer/installers/zipball/6213d900e92647831f7a406d5c530ea1f3d4360e", 20 | "reference": "6213d900e92647831f7a406d5c530ea1f3d4360e", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "composer-plugin-api": "^1.0" 25 | }, 26 | "replace": { 27 | "roundcube/plugin-installer": "*", 28 | "shama/baton": "*" 29 | }, 30 | "require-dev": { 31 | "composer/composer": "1.0.*@dev", 32 | "phpunit/phpunit": "4.1.*" 33 | }, 34 | "type": "composer-plugin", 35 | "extra": { 36 | "class": "Composer\\Installers\\Plugin", 37 | "branch-alias": { 38 | "dev-master": "1.0-dev" 39 | } 40 | }, 41 | "autoload": { 42 | "psr-0": { 43 | "Composer\\Installers\\": "src/" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "authors": [ 51 | { 52 | "name": "Kyle Robinson Young", 53 | "email": "kyle@dontkry.com", 54 | "homepage": "https://github.com/shama" 55 | } 56 | ], 57 | "description": "A multi-framework Composer library installer", 58 | "homepage": "http://composer.github.com/installers/", 59 | "keywords": [ 60 | "Craft", 61 | "Dolibarr", 62 | "Hurad", 63 | "MODX Evo", 64 | "OXID", 65 | "SMF", 66 | "Thelia", 67 | "WolfCMS", 68 | "agl", 69 | "aimeos", 70 | "annotatecms", 71 | "bitrix", 72 | "cakephp", 73 | "chef", 74 | "codeigniter", 75 | "concrete5", 76 | "croogo", 77 | "dokuwiki", 78 | "drupal", 79 | "elgg", 80 | "fuelphp", 81 | "grav", 82 | "installer", 83 | "joomla", 84 | "kohana", 85 | "laravel", 86 | "lithium", 87 | "magento", 88 | "mako", 89 | "mediawiki", 90 | "modulework", 91 | "moodle", 92 | "phpbb", 93 | "piwik", 94 | "ppi", 95 | "puppet", 96 | "roundcube", 97 | "shopware", 98 | "silverstripe", 99 | "symfony", 100 | "typo3", 101 | "wordpress", 102 | "zend", 103 | "zikula" 104 | ], 105 | "time": "2016-01-27T12:54:22+00:00" 106 | } 107 | ], 108 | "packages-dev": [], 109 | "aliases": [], 110 | "minimum-stability": "stable", 111 | "stability-flags": [], 112 | "prefer-stable": false, 113 | "prefer-lowest": false, 114 | "platform": { 115 | "php": ">=5.4.0" 116 | }, 117 | "platform-dev": [] 118 | } 119 | -------------------------------------------------------------------------------- /wp-stage-switcher.php: -------------------------------------------------------------------------------- 1 | 'url' elements: 19 | * 20 | * $envs = [ 21 | * 'development' => 'http://example.dev', 22 | * 'staging' => 'http://example-staging.com', 23 | * 'production' => 'http://example.com' 24 | * ]; 25 | * 26 | * define( 'ENVIRONMENTS', $envs ); 27 | * 28 | * If you're using PHP 5.6 or older you must serialize $envs first: 29 | * 30 | * define('ENVIRONMENTS', serialize($envs)); 31 | * 32 | * WP_ENV must be defined as the current environment. 33 | * 34 | * For multisite subdomain installations, the host portion of the specified 35 | * environment URL will be treated as a suffix in constructing a matching blog 36 | * URL in that environment. 37 | */ 38 | class StageSwitcher { 39 | private $stages; 40 | 41 | public function __construct() { 42 | add_action('admin_bar_menu', [$this, 'admin_bar_stage_switcher']); 43 | add_action('wp_before_admin_bar_render', [$this, 'admin_css']); 44 | } 45 | 46 | public function admin_bar_stage_switcher($admin_bar) { 47 | if (!defined('ENVIRONMENTS') || !defined('WP_ENV') || !apply_filters('bedrock/stage_switcher_visibility', is_super_admin())) { 48 | return; 49 | } 50 | 51 | $this->stages = maybe_unserialize(ENVIRONMENTS); 52 | $subdomain_multisite = is_multisite() && is_subdomain_install(); 53 | 54 | $admin_bar->add_menu([ 55 | 'id' => 'environment', 56 | 'parent' => 'top-secondary', 57 | 'title' => ucwords(WP_ENV), 58 | 'href' => '#', 59 | 'meta' => [ 60 | 'class' => 'environment-' . sanitize_html_class(strtolower(WP_ENV)), 61 | ], 62 | ]); 63 | 64 | foreach ($this->stages as $stage => $url) { 65 | if ($stage === WP_ENV) { 66 | continue; 67 | } 68 | 69 | if ($subdomain_multisite) { 70 | $url = $this->multisite_url($url); 71 | } 72 | 73 | $url = apply_filters('bedrock/stage_switcher_url', rtrim($url, '/') . $_SERVER['REQUEST_URI'], $url, $stage); 74 | 75 | $admin_bar->add_menu([ 76 | 'id' => "stage_$stage", 77 | 'parent' => 'environment', 78 | 'title' => ucwords($stage), 79 | 'href' => $url, 80 | 'meta' => [ 81 | 'class' => 'environment-' . sanitize_html_class(strtolower($stage)), 82 | ], 83 | ]); 84 | } 85 | } 86 | 87 | public function admin_css() { ?> 88 | 94 | stages[WP_ENV], PHP_URL_HOST); 103 | $target_stage_host_suffix = wp_parse_url($url, PHP_URL_HOST); 104 | 105 | // Using preg_replace to anchor to the end of the host string 106 | $target_host = preg_replace('/' . preg_quote($current_stage_host_suffix) . '$/', $target_stage_host_suffix, $current_host); 107 | 108 | // Use the stage URL as the base for replacement to keep scheme/port 109 | return str_replace($target_stage_host_suffix, $target_host, $url); 110 | } 111 | } 112 | 113 | new StageSwitcher; 114 | --------------------------------------------------------------------------------