diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
deleted file mode 100644
index 7378254..0000000
--- a/.github/workflows/unit-test.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Testing Suite
-
-on:
- push:
- branches:
- - develop
- pull_request:
- schedule:
- - cron: '0 0 * * *'
-
-jobs:
- php-tests:
- strategy:
- matrix:
- php: [8.0, 8.1]
- wordpress: ["latest"]
- uses: alleyinteractive/.github/.github/workflows/php-tests.yml@main
- with:
- php: ${{ matrix.php }}
- wordpress: ${{ matrix.wordpress }}
diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml
deleted file mode 100644
index b20f3b6..0000000
--- a/.github/workflows/update-changelog.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-name: "Update Changelog"
-
-on:
- release:
- types: [released]
-
-jobs:
- update:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
- with:
- ref: main
-
- - name: Update Changelog
- uses: stefanzweifel/changelog-updater-action@v1
- with:
- latest-version: ${{ github.event.release.name }}
- release-notes: ${{ github.event.release.body }}
-
- - name: Commit updated CHANGELOG
- uses: stefanzweifel/git-auto-commit-action@v4
- with:
- branch: main
- commit_message: Update CHANGELOG
- file_pattern: CHANGELOG.md
diff --git a/.github/workflows/upgrade-wordpress-plugin.yml b/.github/workflows/upgrade-wordpress-plugin.yml
deleted file mode 100644
index ba41962..0000000
--- a/.github/workflows/upgrade-wordpress-plugin.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: Update WordPress Plugin
-
-on:
- schedule:
- - cron: '0 */6 * * *'
-
-permissions:
- contents: write
- pull-requests: write
-
-jobs:
- update-plugin:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: alleyinteractive/action-update-wordpress-plugin@v1.2.1
- with:
- plugin-file: 'wp-environment-switcher.php'
- upgrade-npm-dependencies: "true"
diff --git a/.phpcs.xml b/.phpcs.xml
index cf85b94..080e971 100644
--- a/.phpcs.xml
+++ b/.phpcs.xml
@@ -38,6 +38,7 @@
+
diff --git a/README.md b/README.md
index 525ff9f..eba1553 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,14 @@
# WordPress Environment Switcher
-Contributors: srtfisher
-
-Tags: alleyinteractive, wp-environment-switcher
-
-Stable tag: 0.1.0
-
-Requires at least: 5.9
-
-Tested up to: 6.1
-
-Requires PHP: 8.0
-
-License: GPL v2 or later
-
[![Coding Standards](https://github.com/alleyinteractive/wp-environment-switcher/actions/workflows/coding-standards.yml/badge.svg)](https://github.com/alleyinteractive/wp-environment-switcher/actions/workflows/coding-standards.yml)
-[![Testing Suite](https://github.com/alleyinteractive/wp-environment-switcher/actions/workflows/unit-test.yml/badge.svg)](https://github.com/alleyinteractive/wp-environment-switcher/actions/workflows/unit-test.yml)
-Easily switch between different site environments from the WordPress admin bar..
+Easily switch between different site environments from the WordPress admin bar.
+
+> Props to [WordPress Stage Switcher](https://github.com/roots/wp-stage-switcher) for the inspiration.
## Installation
-You can install the package via composer:
+You can install the package via Composer:
```bash
composer require alleyinteractive/wp-environment-switcher
@@ -29,60 +16,29 @@ composer require alleyinteractive/wp-environment-switcher
## Usage
-Activate the plugin in WordPress and use it like so:
-
-```php
-$plugin = Alley\WP\WordPress_Environment_Switcher\WordPress_Environment_Switcher\WordPress_Environment_Switcher();
-$plugin->perform_magic();
-```
-
-## Testing
-
-Run `npm run test` to run Jest tests against JavaScript files. Run
-`npm run test:watch` to keep the test runner open and watching for changes.
-
-Run `npm run lint` to run ESLint against all JavaScript files. Linting will also
-happen when running development or production builds.
+Activate the plugin in WordPress and you will see the switcher appear in the top right admin bar:
-Run `composer test` to run tests against PHPUnit and the PHP code in the plugin.
+![Screenshot of plugin](https://github.com/alleyinteractive/wp-environment-switcher/assets/346399/83684c99-4f74-4969-b302-a0c617c17190)
-### The `entries` directory and entry points
+The plugin reads the current WordPress environment from `wp_get_environment_type()` which can be set by defining `WP_ENVIRONMENT_TYPE` in your `wp-config.php` file. You can define the available environments by using the `wp_environment_switcher_environments` filter:
-All directories created in the `entries` directory can serve as entry points and will be compiled with [@wordpress/scripts](https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/README.md#scripts) into the `build` directory with an accompanied `index.asset.php` asset map.
-
-#### Enqueuing Entry Points
-
-You can also include an `index.php` file in the entry point directory for enqueueing or registering a script. This file will then be moved to the build directory and will be auto-loaded with the `load_scripts()` function in the `functions.php` file. Alternatively, if a script is to be enqueued elsewhere there are helper functions in the `src/assets.php` file for getting the assets.
-
-### Scaffold a dynamic block with `create-block`
-
-Use the `create-block` command to create custom blocks with [@alleyinteractive/create-block](https://github.com/alleyinteractive/alley-scripts/tree/main/packages/create-block) script and follow the prompts to generate all the block assets in the `blocks/` directory.
-Block registration, script creation, etc will be scaffolded from the `create-block` script. Run `npm run build` to compile and build the custom block. Blocks are enqueued using the `load_scripts()` function in `src/assets.php`.
-
-### Updating WP Dependencies
-
-Update the [WordPress dependency packages](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/#packages-update) used in the project to their latest version.
-
-To update `@wordpress` dependencies to their latest version use the packages-update command:
-
-```sh
-npx wp-scripts packages-update
+```php
+add_filter(
+ 'wp_environment_switcher_environments',
+ fn () => [
+ 'production' => 'https://example.org',
+ 'staging' => 'https://staging.example.org',
+ 'local' => 'https://example.test',
+ ]
+);
```
-This script provides the following custom options:
+The plugin will automatically detect the current environment and highlight it in
+the switcher.
-- `--dist-tag` – allows specifying a custom dist-tag when updating npm packages. Defaults to `latest`. This is especially useful when using [`@wordpress/dependency-extraction-webpack-plugin`](https://www.npmjs.com/package/@wordpress/dependency-extraction-webpack-plugin). It lets installing the npm dependencies at versions used by the given WordPress major version for local testing, etc. Example:
-
-```sh
-npx wp-scripts packages-update --dist-tag=wp-WPVERSION`
-```
-
-Where `WPVERSION` is the version of WordPress you are targeting. The version
-must include both the major and minor version (e.g., `6.1`). For example:
+## Testing
-```sh
-npx wp-scripts packages-update --dist-tag=wp-6.1`
-```
+Run `composer test` to run tests against PHPStan/PHPCS.
## Changelog
@@ -92,11 +48,11 @@ Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed re
This project is actively maintained by [Alley
Interactive](https://github.com/alleyinteractive). Like what you see? [Come work
-with us](https://alley.co/careers/).
+with us](https://alley.com/careers/).
-- [Sean Fisher](https://github.com/Sean Fisher)
+- [Sean Fisher](https://github.com/srtfisher)
- [All Contributors](../../contributors)
## License
-The GNU General Public License (GPL) license. Please see [License File](LICENSE) for more information.
\ No newline at end of file
+The GNU General Public License (GPL) license. Please see [License File](LICENSE) for more information.
diff --git a/composer.json b/composer.json
index 41b09f7..25c1739 100644
--- a/composer.json
+++ b/composer.json
@@ -11,16 +11,14 @@
"authors": [
{
"name": "Sean Fisher",
- "email": "srtfisher@gmail.com"
+ "email": "sean@alley.com"
}
],
"require": {
- "php": "^8.0",
- "alleyinteractive/composer-wordpress-autoloader": "^1.0"
+ "php": "^8.0"
},
"require-dev": {
"alleyinteractive/alley-coding-standards": "^1.0",
- "mantle-framework/testkit": "^0.11",
"szepeviktor/phpstan-wordpress": "^1.1"
},
"config": {
@@ -31,27 +29,15 @@
},
"sort-packages": true
},
- "extra": {
- "wordpress-autoloader": {
- "autoload": {
- "Alley\\WP\\WordPress_Environment_Switcher": "src"
- },
- "autoload-dev": {
- "Alley\\WP\\WordPress_Environment_Switcher\\Tests": "tests"
- }
- }
- },
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"phpcbf": "phpcbf .",
"phpcs": "phpcs .",
- "phpunit": "phpunit",
"phpstan": "phpstan --memory-limit=512M",
"test": [
"@phpcs",
- "@phpstan",
- "@phpunit"
+ "@phpstan"
]
}
}
diff --git a/phpstan.neon b/phpstan.neon
index 4e5ed90..5e0cefa 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -6,9 +6,6 @@ parameters:
level: max
paths:
- - blocks/
- - entries/
- - src/
- wp-environment-switcher.php
# ignoreErrors:
diff --git a/phpunit.xml b/phpunit.xml
deleted file mode 100644
index ab2a15e..0000000
--- a/phpunit.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- tests/feature
-
-
- tests/unit
-
-
-
diff --git a/src/class-wordpress-environment-switcher.php b/src/class-wordpress-environment-switcher.php
deleted file mode 100644
index d0f9daf..0000000
--- a/src/class-wordpress-environment-switcher.php
+++ /dev/null
@@ -1,15 +0,0 @@
- $args Optional. Additional arguments for register_post_meta or register_term_meta. Defaults to an empty array.
- * @return bool True if the meta key was successfully registered in the global array, false if not.
- */
-function register_meta_helper(
- string $object_type,
- array $object_slugs,
- string $meta_key,
- array $args = []
-) : bool {
-
- // Object type must be either post or term.
- if ( ! in_array( $object_type, [ 'post', 'term' ], true ) ) {
- throw new \InvalidArgumentException(
- __(
- 'Object type must be one of "post", "term".',
- 'wp-environment-switcher'
- )
- );
- }
-
- /**
- * Merge provided arguments with defaults and filter register_meta() args.
- *
- * @link https://developer.wordpress.org/reference/functions/register_meta/
- *
- * @param array $args {
- * Array of args to be passed to register_meta().
- *
- * @type string $object_subtype A subtype; e.g. if the object type is "post", the post type. If left empty,
- * the meta key will be registered on the entire object type. Default empty.
- * @type string $type The type of data associated with this meta key. Valid values are
- * 'string', 'boolean', 'integer', 'number', 'array', and 'object'.
- * @type string $description A description of the data attached to this meta key.
- * @type bool $single Whether the meta key has one value per object, or an array of values per object.
- * @type mixed $default The default value returned from get_metadata() if no value has been set yet.
- * When using a non-single meta key, the default value is for the first entry. In other words,
- * when calling get_metadata() with $single set to false, the default value given here will be wrapped in an array.
- * @type callable $sanitize_callback A function or method to call when sanitizing $meta_key data.
- * @type callable $auth_callback Optional. A function or method to call when performing edit_post_meta,
- * add_post_meta, and delete_post_meta capability checks.
- * @type bool|array $show_in_rest Whether data associated with this meta key can be considered public and should be
- * accessible via the REST API. A custom post type must also declare support
- * for custom fields for registered meta to be accessible via REST. When registering
- * complex meta values this argument may optionally be an array with 'schema'
- * or 'prepare_callback' keys instead of a boolean.
- * }
- * @param string $object_type The type of meta to register, which must be one of 'post' or 'term'.
- * @param array $object_slugs The post type or taxonomy slugs to register with.
- * @param string $meta_key The meta key to register.
- */
- $args = apply_filters(
- 'wp_environment_switcher_register_meta_helper_args', // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
- wp_parse_args(
- $args,
- [
- 'show_in_rest' => true,
- 'single' => true,
- 'type' => 'string',
- ]
- ),
- $object_type,
- $object_slugs,
- $meta_key
- );
-
- // Fork for object type.
- switch ( $object_type ) {
- case 'post':
- foreach ( $object_slugs as $object_slug ) {
- if ( ! register_post_meta( $object_slug, $meta_key, $args ) ) {
- return false;
- }
- }
- break;
- case 'term':
- foreach ( $object_slugs as $object_slug ) {
- if ( ! register_term_meta( $object_slug, $meta_key, $args ) ) {
- return false;
- }
- }
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-/**
- * Reads the post meta definitions from config and registers them.
- */
-function register_post_meta_from_defs(): void {
- // Ensure the config file exists.
- $filepath = dirname( __DIR__ ) . '/config/post-meta.json';
- if ( ! file_exists( $filepath )
- || 0 !== validate_file( $filepath )
- ) {
- return;
- }
-
- // Try to read the file's contents. We can dismiss the "uncached" warning here because it is a local file.
- // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
- $definitions = json_decode( (string) file_get_contents( $filepath ), true );
- if ( empty( $definitions ) || ! is_array( $definitions ) ) {
- return;
- }
-
- // Loop through definitions and register each.
- foreach ( $definitions as $meta_key => $definition ) {
- // Extract post types.
- $post_types = $definition['post_types'] ?? [];
- // Unset since $definition is passed as register_meta args.
- unset( $definition['post_types'] );
-
- // Relocate schema, if specified at the top level.
- if ( ! empty( $definition['schema'] ) ) {
- $definition['show_in_rest']['schema'] = $definition['schema'];
- // Unset since $definition is passed as register_meta args.
- unset( $definition['schema'] );
- }
-
- // Register the meta.
- register_meta_helper(
- 'post',
- $post_types,
- $meta_key,
- $definition
- );
- }
-}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
deleted file mode 100644
index 7376004..0000000
--- a/tests/bootstrap.php
+++ /dev/null
@@ -1,16 +0,0 @@
-maybe_rsync_plugin()
- ->with_sqlite()
- // Load the main file of the plugin.
- ->loaded( fn () => require_once __DIR__ . '/../wp-environment-switcher.php' )
- ->install();
diff --git a/tests/class-test-case.php b/tests/class-test-case.php
deleted file mode 100644
index 47d05c6..0000000
--- a/tests/class-test-case.php
+++ /dev/null
@@ -1,17 +0,0 @@
-assertTrue( true );
- $this->assertNotEmpty( home_url() );
- }
-}
diff --git a/tests/unit/class-example-unit-test.php b/tests/unit/class-example-unit-test.php
deleted file mode 100644
index 762abc5..0000000
--- a/tests/unit/class-example-unit-test.php
+++ /dev/null
@@ -1,24 +0,0 @@
-assertTrue( true );
- }
-}
diff --git a/wp-environment-switcher.php b/wp-environment-switcher.php
index 202940e..a6dfd6e 100644
--- a/wp-environment-switcher.php
+++ b/wp-environment-switcher.php
@@ -3,10 +3,10 @@
* Plugin Name: WordPress Environment Switcher
* Plugin URI: https://github.com/alleyinteractive/wp-environment-switcher
* Description: Easily switch between different site environments from the WordPress admin bar.
- * Version: 0.1.0
+ * Version: 1.0.0
* Author: Sean Fisher
* Author URI: https://github.com/alleyinteractive/wp-environment-switcher
- * Requires at least: 6.0
+ * Requires at least: 5.5.0
* Tested up to: 6.2
*
* Text Domain: wp-environment-switcher
@@ -21,17 +21,153 @@
}
/**
- * Root directory to this plugin.
+ * Instantiate the plugin.
*/
-define( 'WP_ENVIRONMENT_SWITCHER_DIR', __DIR__ );
+function main(): void {
+ add_action( 'admin_bar_menu', __NAMESPACE__ . '\\register_admin_bar', 300 );
+ add_action( 'wp_before_admin_bar_render', __NAMESPACE__ . '\\add_switcher_css' );
+}
+main();
-// Load the plugin's main files.
-require_once __DIR__ . '/src/meta.php';
+/**
+ * Retrieve all the available environments for the switcher.
+ *
+ * @return array
+ */
+function get_environments(): array {
+ return (array) apply_filters( 'wp_environment_switcher_environments', [] );
+}
/**
- * Instantiate the plugin.
+ * Translate the current request path to a different host.
+ *
+ * Used to translate www.example.org/the/path to staging.example.org/the/path
+ * for switching environments with ease.
+ *
+ * @param string $environment_url The new base URL.
+ * @return string
*/
-function main(): void {
- // ...
+function get_translated_url( string $environment_url ): string {
+ if ( empty( $_SERVER['REQUEST_URI'] ) ) {
+ return $environment_url;
+ }
+
+ return rtrim( $environment_url, '/' ) . sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
+}
+
+/**
+ * Register the admin environment switcher in the admin bar.
+ */
+function register_admin_bar(): void {
+ $environments = get_environments();
+
+ if ( empty( $environments ) ) {
+ return;
+ }
+
+ $current = wp_get_environment_type();
+
+ // Bail if we can't determine the current environment.
+ if ( empty( $current ) ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ esc_html__( 'The current environment could not be determined.', 'wp-environment-switcher' ),
+ '0.1.0'
+ );
+
+ return;
+ }
+
+ // Fire a warning if the current environment is not in the list of environments.
+ if ( ! isset( $environments[ $current ] ) ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: %s is the current environment */
+ esc_html__( 'The current environment (%s) is not in the list of environments.', 'wp-environment-switcher' ),
+ esc_html( $current )
+ ),
+ '0.1.0'
+ );
+ }
+
+ global $wp_admin_bar;
+
+ $wp_admin_bar->add_menu(
+ [
+ 'id' => 'wp-environment-switcher',
+ 'title' => ucwords( $current ),
+ 'href' => '#',
+ 'parent' => 'top-secondary',
+ 'meta' => [
+ 'class' => 'wp-environment-switcher',
+ ],
+ ]
+ );
+
+ /**
+ * Filter the method used to translate the URL to the new environment.
+ *
+ * @param callable $callback The callback to use to translate the URL.
+ */
+ $callback = apply_filters( 'wp_environment_switcher_url_translation', __NAMESPACE__ . '\\get_translated_url' );
+
+ // Fire a warning if the translation callback is not callable.
+ if ( ! is_callable( $callback ) ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ esc_html__( 'The URL translation callback is not callable.', 'wp-environment-switcher' ),
+ '0.1.0'
+ );
+
+ // Reverse the callback to the default.
+ $callback = __NAMESPACE__ . '\\get_translated_url';
+ }
+
+ foreach ( $environments as $environment => $url ) {
+ $wp_admin_bar->add_menu(
+ [
+ 'id' => 'wp-environment-switcher-' . $environment,
+ 'parent' => 'wp-environment-switcher',
+ 'title' => ucwords( $environment ),
+ 'href' => $callback( $url ),
+ 'meta' => [
+ 'class' => 'wp-environment-switcher__item ' . ( $environment === $current ? 'wp-environment-switcher__item--active' : '' ),
+ ],
+ ]
+ );
+ }
+}
+
+/**
+ * Add CSS to support the environment switcher.
+ */
+function add_switcher_css(): void {
+ if ( empty( get_environments() ) ) {
+ return;
+ }
+
+ ?>
+
+