diff --git a/composer.json b/composer.json index 26a979b..99910f9 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "php": "~7.1 || 8.*" }, "require-dev": { - "automattic/jetpack-codesniffer": "^2.0", + "automattic/jetpack-codesniffer": "2.6.0", "brain/monkey": "^2.6", "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", "phpunit/phpunit": "7.* || 8.*", diff --git a/features/woocommerce-beta-tester.php b/features/woocommerce-beta-tester.php index 59b2deb..dc677a1 100644 --- a/features/woocommerce-beta-tester.php +++ b/features/woocommerce-beta-tester.php @@ -7,13 +7,27 @@ namespace jn; -define( 'WOOCOMMERCE_BETA_TESTER_PLUGIN_URL', 'https://github.com/woocommerce/woocommerce-beta-tester/archive/refs/heads/trunk.zip' ); +add_action( + 'jurassic_ninja_added_rest_api_endpoints', + function () { + add_get_endpoint( + 'woocommerce-beta-tester/branches', + function () { + $manifest_url = 'https://betadownload.jetpack.me/woocommerce-branches.json'; + $manifest = json_decode( wp_remote_retrieve_body( wp_remote_get( $manifest_url ) ) ); + + return $manifest; + } + ); + } +); add_action( 'jurassic_ninja_init', function () { $defaults = array( 'woocommerce-beta-tester' => false, + 'woocommerce-beta-tester-live-branch' => false, ); add_action( @@ -23,6 +37,13 @@ function ( &$app = null, $features, $domain ) use ( $defaults ) { if ( $features['woocommerce-beta-tester'] ) { debug( '%s: Adding WooCommerce Beta Tester Plugin', $domain ); add_woocommerce_beta_tester_plugin(); + + if ( $features['woocommerce-beta-tester-live-branch'] ) { + $branch = $features['woocommerce-beta-tester-live-branch']; + + debug( '%s: Adding WooCommerce Live Branch: %s', $domain, $branch ); + add_woocommerce_live_branch( $branch ); + } } }, 10, @@ -46,11 +67,12 @@ function ( $defaults ) { function ( $features, $json_params ) { if ( isset( $json_params['woocommerce-beta-tester'] ) ) { $features['woocommerce-beta-tester'] = $json_params['woocommerce-beta-tester']; - // The WooCommerce Beta Tester Plugin works only when woocommerce is installed and active too. - if ( $features['woocommerce-beta-tester'] ) { - $features['woocommerce'] = true; - } } + + if ( isset( $json_params['woocommerce-beta-tester-live-branch'] ) ) { + $features['woocommerce-beta-tester-live-branch'] = $json_params['woocommerce-beta-tester-live-branch']; + } + return $features; }, 10, @@ -83,11 +105,78 @@ function ( $fields ) { ); /** - * Installs and activates WooCommerce Beta Tester plugin on the site. + * Get the WooCommerce Beta Tester Plugin Zip URL from Github. + */ +function get_woocommerce_beta_tester_zip_url() { + $url = 'https://api.github.com/repos/woocommerce/woocommerce/releases'; + $response = wp_remote_get( $url ); + + if ( is_wp_error( $response ) ) { + return false; + } else { + $releases = json_decode( wp_remote_retrieve_body( $response ), true ); + + $filtered_releases = array_filter( + $releases, + function ( $release ) { + return strpos( $release['tag_name'], 'wc-beta-tester' ) !== false; + } + ); + + usort( + $filtered_releases, + function ( $a, $b ) { + return strtotime( $b['created_at'] ) - strtotime( $a['created_at'] ); + } + ); + + $latest_release = $filtered_releases[0]; + + $assets = $latest_release['assets']; + $zip = array_filter( + $assets, + function ( $asset ) { + return strpos( $asset['name'], 'zip' ) !== false; + } + ); + + if ( count( $zip ) > 0 ) { + return $zip[0]['browser_download_url']; + } else { + return false; + } + } +} + +/** + * Retrieve and install the WooCommerce Beta Tester Plugin. + * + * @throws Exception If the plugin zip file cannot be found. */ function add_woocommerce_beta_tester_plugin() { - $woocommerce_beta_tester_plugin_url = WOOCOMMERCE_BETA_TESTER_PLUGIN_URL; - $cmd = "wp plugin install $woocommerce_beta_tester_plugin_url --activate"; + $zip_url = get_woocommerce_beta_tester_zip_url(); + + if ( $zip_url ) { + $cmd = "wp plugin install $zip_url --activate"; + add_filter( + 'jurassic_ninja_feature_command', + function ( $s ) use ( $cmd ) { + return "$s && $cmd"; + } + ); + } else { + throw new Exception( 'Could not find WooCommerce Beta Tester plugin zip file.' ); + } +} + +/** + * Installs and activates a live branch of WooCommerce on the site. + * + * @param string $branch_name The name of the branch to install. + */ +function add_woocommerce_live_branch( $branch_name ) { + $cmd = "wp wc-beta-tester deactivate_woocommerce && wp wc-beta-tester install $branch_name && wp wc-beta-tester activate $branch_name"; + add_filter( 'jurassic_ninja_feature_command', function ( $s ) use ( $cmd ) { diff --git a/jurassic.ninja.php b/jurassic.ninja.php index 1386ccb..149fca9 100644 --- a/jurassic.ninja.php +++ b/jurassic.ninja.php @@ -2,7 +2,7 @@ /** * Plugin Name: Jurassic Ninja * Description: Launch ephemeral instances of WordPress + Jetpack using ServerPilot and an Ubuntu Box. - * Version: 5.20 + * Version: 5.21 * Author: Automattic * * @package jurassic-ninja diff --git a/jurassicninja.js b/jurassicninja.js index 31e13a3..0512274 100644 --- a/jurassicninja.js +++ b/jurassicninja.js @@ -19,6 +19,7 @@ function init() { if ( isSpecialOpsPage() ) { hookJetpackBranches(); + hookWooCommerceBetaBranches(); hookAvailableLanguages(); jQuery( '[data-is-create-button]' ).click( function () { const $this = jQuery( this ); @@ -319,6 +320,18 @@ function favicon_update_colour( colour ) { } } +function getAvailableWooCommerceBetaBranches() { + return fetch( '/wp-json/jurassic.ninja/woocommerce-beta-tester/branches' ) + .then( response => response.json() ) + .then( body => { + if (body.data && body.data.pr) { + return Object.values(body.data.pr).sort((a, b) => a.branch.localeCompare(b.branch)); + } + + return []; + } ); +} + function getAvailableJetpackBetaPlugins() { return fetch( '/wp-json/jurassic.ninja/jetpack-beta/plugins') .then( response => response.json() ) @@ -330,6 +343,7 @@ function getAvailableJetpackBetaPlugins() { return plugins; } ); } + function getAvailableJetpackBetaBranches( plugin_slug ) { return fetch( '/wp-json/jurassic.ninja/jetpack-beta/plugins/' + ( plugin_slug || 'jetpack' ) + '/branches' ) .then( response => response.json() ) @@ -463,3 +477,48 @@ function hookJetpackBranches() { } ); } ); } + +function hookWooCommerceBetaBranches() { + getAvailableWooCommerceBetaBranches().then( branches => { + const wooBetaCheckBox = document.querySelector('[data-feature=woocommerce-beta-tester]'); + + if (branches.length && wooBetaCheckBox) { + const checkboxContainer = wooBetaCheckBox.closest('.checkbox'); + const wooBetaSelect = document.createElement('input'); + + wooBetaSelect.id = 'woocommerce_beta_branch'; + wooBetaSelect.name = 'woocommerce_beta_branch'; + wooBetaSelect.className = 'form-control'; + wooBetaSelect.setAttribute('role' , 'search') ; + wooBetaSelect.setAttribute('list', 'woocommerce_branches'); + wooBetaSelect.setAttribute('type', 'text'); + wooBetaSelect.setAttribute('Placeholder', 'Select a branch to enable'); + wooBetaSelect.setAttribute('data-feature', 'woocommerce-beta-tester-live-branch'); + wooBetaSelect.style.display = "none"; + + const datalist = document.createElement('datalist'); + datalist.id = 'woocommerce_branches'; + + branches.forEach( branch => { + const option = document.createElement('option'); + option.innerHTML = branch.branch; + option.value = branch.branch; + datalist.appendChild(option); + } ); + + checkboxContainer.appendChild(wooBetaSelect); + checkboxContainer.appendChild(datalist); + + // Toggle display of the select list + wooBetaCheckBox.addEventListener('change', function() { + if (this.checked) { + wooBetaSelect.style.display = "block"; + } else { + wooBetaSelect.style.display = "none"; + } + }); + } + }); +} + +