diff --git a/.circleci/config.yml b/.circleci/config.yml index 4332cae35a..7da0023c20 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -259,6 +259,7 @@ jobs: JIRA_USERNAME=planet4 python /home/circleci/book-test-instance.py \ --pr-url $(cat /tmp/workspace/pr) \ --results /tmp/workspace/booking.json >/tmp/workspace/test-instance + echo "https://app.circleci.com/pipelines/github/greenpeace/planet4-test-$(cat /tmp/workspace/test-instance)/" - run: activate-gcloud-account.sh - run: name: "Put zip in cloud storage" diff --git a/src/Commands.php b/src/Commands.php new file mode 100644 index 0000000000..87b59f0bba --- /dev/null +++ b/src/Commands.php @@ -0,0 +1,27 @@ +getValue( 'debug' ) ); + $data_store = new DataStore( $logger ); + $integration_api = new WordPressAPI( $data_store ); + $integration = new DefaultIntegration( $config, $integration_api, $data_store, $logger ); + $api = new WordPressClientAPI( $integration ); + + $zone_id = $api->getZoneTag( get_option( 'cloudflare_cached_domain_name' ) ); + + $urls = self::get_urls( $assoc_args ); + WP_CLI::log( 'About to purge ' . count( $urls ) . ' urls.' ); + + // 30 is Cloudflare's purge api limit. + $chunks = array_chunk( $urls, 30 ); + + foreach ( $chunks as $i => $chunk ) { + // We only use $i to be human readable, increment it immediately. + ++ $i; + + $ok = $api->zonePurgeFiles( $zone_id, $chunk ); + // It's unlikely that only some of the chunks will fail, as Cloudflare's API responds with success + // for any url, even if on non-existent domains. Giving a warning per chunk anyway, just in case. + if ( ! $ok ) { + $joined = implode( $chunk, "\n" ); + WP_CLI::warning( "Chunk $i failed, one or more of these didn't work out: \n$joined" ); + } + } + } + + /** + * Determine which urls to purge. Throws error if right args were not passed. + * + * @param array|null $assoc_args The named args passed to the command. + * + * @throws \RuntimeException If you don't provide the right args. + * + * @return array The urls to purge + */ + private static function get_urls( ?array $assoc_args ): array { + if ( isset( $assoc_args['urls'] ) ) { + return explode( ',', $assoc_args['urls'] ); + } + + if ( isset( $assoc_args['all'] ) ) { + $post_types = isset( $assoc_args['post-types'] ) + ? explode( ',', $assoc_args['post-types'] ) + : [ + 'post', + 'page', + 'campaign', + ]; + $query_args = [ + 'post_type' => $post_types, + 'posts_per_page' => - 1, + 'post_status' => 'publish', + 'ignore_sticky_posts' => 1, + 'fields' => 'ids', + ]; + + $ids = get_posts( $query_args ); + + return array_map( 'get_permalink', $ids ); + } + + throw new \RuntimeException( 'Please provide either --urls, or purge all urls with --all.' ); + } +} diff --git a/src/Commands/Command.php b/src/Commands/Command.php new file mode 100644 index 0000000000..b4984c93cf --- /dev/null +++ b/src/Commands/Command.php @@ -0,0 +1,47 @@ + static::get_short_description(), + ] + ); + } + + /** + * The name to access the command. + * + * @return string The command name. + */ + abstract protected static function get_name(): string; + + /** + * The description shown in the argument's help. + * + * @return string The description text. + */ + abstract protected static function get_short_description(): string; + + /** + * The logic of the command. Has WP_CLI command signature. + * + * @param array|null $args Positional arguments. + * @param array|null $assoc_args Named arguments. + */ + abstract public static function execute( ?array $args, ?array $assoc_args ): void; +} diff --git a/src/Commands/RunActivator.php b/src/Commands/RunActivator.php new file mode 100644 index 0000000000..c0a23a68cf --- /dev/null +++ b/src/Commands/RunActivator.php @@ -0,0 +1,39 @@ + 1 ] ); + update_option( 'cloudflare_cached_domain_name', $root_domain ); + } +} diff --git a/src/Features.php b/src/Features.php index 489e354c4e..96f5e775a8 100644 --- a/src/Features.php +++ b/src/Features.php @@ -14,6 +14,8 @@ class Features { public const ENGAGING_NETWORKS = 'feature_engaging_networks'; + public const CLOUDFLARE_DEPLOY_PURGE = 'cloudflare_deploy_purge'; + /** * Get the features options page settings. * @@ -55,6 +57,15 @@ private static function get_fields(): array { 'id' => self::ENGAGING_NETWORKS, 'type' => 'checkbox', ], + [ + 'name' => __( 'Purge HTML from Cloudflare on deploy.', 'planet4-master-theme-backend' ), + 'desc' => __( + 'WARNING: Do not change this setting without checking with Planet4 team. This will purge all URLs from Cloudflare after a deploy. We are still experimenting with the effects of that on Cloudflare performance.', + 'planet4-master-theme-backend' + ), + 'id' => self::CLOUDFLARE_DEPLOY_PURGE, + 'type' => 'checkbox', + ], ]; } diff --git a/src/Loader.php b/src/Loader.php index c7951999aa..ce2b04a6e1 100644 --- a/src/Loader.php +++ b/src/Loader.php @@ -3,7 +3,6 @@ namespace P4\MasterTheme; use RuntimeException; -use WP_CLI; /** * Class Loader. @@ -52,7 +51,7 @@ public static function get_instance( $services = [] ) : Loader { private function __construct( $services ) { $this->load_services( $services ); $this->add_filters(); - $this->load_commands(); + Commands::load(); } /** @@ -146,42 +145,6 @@ private function add_filters(): void { add_filter( 'pre_delete_post', [ $this, 'do_not_delete_autosave' ], 1, 3 ); } - /** - * Registers WP_CLI commands. - */ - public function load_commands() { - if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { - return; - } - - $activator_command = static function ( $args, $assoc_args ) { - Activator::run(); - }; - WP_CLI::add_command( 'p4-run-activator', $activator_command ); - - /** - * Put the CF API key into the options table, where the CF plugin uses it from. - */ - $put_cf_key_in_db = static function ( $args ) { - $hostname = $args[0]; - if ( empty( $hostname ) ) { - WP_CLI::error( 'Please specify the hostname.' ); - } - - if ( ! defined( 'CLOUDFLARE_API_KEY' ) || empty( CLOUDFLARE_API_KEY ) ) { - WP_CLI::error( 'CLOUDFLARE_API_KEY constant is not set.' ); - } - - $domain_parts = explode( '.', $hostname ); - - $root_domain = implode( '.', array_slice( $domain_parts, - 2 ) ); - update_option( 'cloudflare_api_key', CLOUDFLARE_API_KEY ); - update_option( 'automatic_platform_optimization', [ 'value' => 1 ] ); - update_option( 'cloudflare_cached_domain_name', $root_domain ); - }; - WP_CLI::add_command( 'p4-cf-key-in-db', $put_cf_key_in_db ); - } - /** * Due to a bug in WordPress core the "autosave revision" of a post is created and deleted all of the time. * This is pretty pointless and makes it impractical to add any post meta to that revision.