Skip to content

Commit

Permalink
Adds wp_parsely_managed_options filter in Parse.ly integration (#4839)
Browse files Browse the repository at this point in the history
* ➕ ADDS: wp_parsely_managed_options in parsely integration

* ➕ ADDS: separate function for configuring the integration for VIP Platform
  • Loading branch information
mehmoodak authored Sep 8, 2023
1 parent e555023 commit 53793eb
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 18 deletions.
20 changes: 18 additions & 2 deletions integrations/block-data-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ class BlockDataApiIntegration extends Integration {
*/
protected string $version = '1.0';

/**
* Returns `true` if `Block Data API` is already available e.g. via customer code. We will use
* this function to prevent activating of integration from platform side.
*/
public function is_loaded(): bool {
return defined( 'VIP_BLOCK_DATA_API_LOADED' );
}

/**
* Applies hooks to load Block Data API plugin.
*
Expand All @@ -30,8 +38,11 @@ class BlockDataApiIntegration extends Integration {
public function load(): void {
// Wait until plugins_loaded to give precedence to the plugin in the customer repo.
add_action( 'plugins_loaded', function() {
// Do not load plugin if already loaded by customer code.
if ( defined( 'VIP_BLOCK_DATA_API_LOADED' ) ) {
// Return if the integration is already loaded.
//
// In activate() method we do make sure to not activate the integration if its already loaded
// but still adding it here as a safety measure i.e. if load() is called directly.
if ( $this->is_loaded() ) {
return;
}

Expand All @@ -44,4 +55,9 @@ public function load(): void {
}
} );
}

/**
* Configure `Block Data API` for VIP Platform.
*/
public function configure(): void {}
}
27 changes: 26 additions & 1 deletion integrations/integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,17 @@ public function __construct( string $slug ) {
* @private
*/
public function activate( array $options = [] ): void {
// If integration is already available in customer code then don't activate it from platform side.
if ( $this->is_loaded() ) {
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
sprintf( 'Prevented activating of integration with slug "%s" because it is already loaded.', esc_html( $this->slug ) ),
E_USER_WARNING
);
}

// Don't do anything if integration is already activated.
if ( $this->is_active() ) {
trigger_error( sprintf( 'VIP Integration with slug "%s" is already activated.', esc_html( $this->get_slug() ) ), E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
return;
}

$this->is_active = true;
Expand Down Expand Up @@ -102,6 +109,14 @@ public function get_slug(): string {
return $this->slug;
}

/**
* Returns `true` if the integration is already available e.g. via customer code. We will use
* this function to prevent activating of integration again.
*
* @private
*/
abstract public function is_loaded(): bool;

/**
* Implement custom action and filter calls to load integration here.
*
Expand All @@ -112,4 +127,14 @@ public function get_slug(): string {
* @private
*/
abstract public function load(): void;

/**
* Configure the integration for VIP platform.
*
* If we want to implement functionality only if the integration is enabled via VIP
* then we will use this function.
*
* @private
*/
abstract public function configure(): void;
}
5 changes: 5 additions & 0 deletions integrations/integrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ public function activate_platform_integrations() {
$this->activate( $slug, [
'config' => $vip_config->get_site_config(),
] );

// If integration is activated successfully without any error then configure.
if ( $integration->is_active() ) {
$integration->configure();
}
}
}
}
Expand Down
47 changes: 44 additions & 3 deletions integrations/parsely.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,45 @@
* @private
*/
class ParselyIntegration extends Integration {
/**
* Returns `true` if `Parse.ly` is already available e.g. customer code. We will use
* this function to prevent loading of integration again from platform side.
*/
public function is_loaded(): bool {
return class_exists( 'Parsely' ) || class_exists( 'Parsely\Parsely' );
}

/**
* Loads the plugin.
*
* @private
*/
public function load(): void {
// Do not load plugin if already loaded by customer code.
if ( class_exists( 'Parsely\Parsely' ) ) {
// Return if the integration is already loaded.
//
// In activate() method we do make sure to not activate the integration if its already loaded
// but still adding it here as a safety measure i.e. if load() is called directly.
if ( $this->is_loaded() ) {
return;
}

// Activating the integration via setting constant whose implementation is already
// handled via Automattic\VIP\WP_Parsely_Integration (ideally we should move
// all the implementation here such that there will be only one way of managing
// the plugin).
define( 'VIP_PARSELY_ENABLED', true );
if ( ! defined( 'VIP_PARSELY_ENABLED' ) ) {
define( 'VIP_PARSELY_ENABLED', true );
}
}

/**
* Configure `Parse.ly` for VIP Platform.
*
* @private
*/
public function configure(): void {
add_filter( 'wp_parsely_credentials', array( $this, 'wp_parsely_credentials_callback' ) );
add_filter( 'wp_parsely_managed_options', array( $this, 'wp_parsely_managed_options_callback' ) );
}

/**
Expand All @@ -55,4 +76,24 @@ public function wp_parsely_credentials_callback( $original_credentials ) {
// and we have to hide the credential banner warning or more.
return array_merge( array( 'is_managed' => true ), $credentials );
}

/**
* Callback for `wp_parsely_managed_options` filter.
*
* @param array $value Value passed to filter.
*
* @return array
*/
public function wp_parsely_managed_options_callback( $value ) {
return array(
'force_https_canonicals' => true,
'meta_type' => 'repeated_metas',
// Managed options that will obey the values on database.
'cats_as_tags' => null,
'content_id_prefix' => null,
'logo' => null,
'lowercase_tags' => null,
'use_top_level_cats' => null,
);
}
}
6 changes: 6 additions & 0 deletions tests/integrations/fake-integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,11 @@

class FakeIntegration extends Integration {

public function is_loaded(): bool {
return false;
}

public function load(): void { }

public function configure(): void { }
}
19 changes: 19 additions & 0 deletions tests/integrations/test-integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

// phpcs:disable Squiz.Commenting.ClassComment.Missing, Squiz.Commenting.FunctionComment.Missing, Squiz.Commenting.FunctionComment.MissingParamComment

use PHPUnit\Framework\MockObject\MockObject;
use WP_UnitTestCase;

require_once __DIR__ . '/fake-integration.php';
Expand Down Expand Up @@ -36,6 +37,22 @@ public function test__activate_is_setting_up_the_plugins_config(): void {
$this->assertEquals( [ 'config_test' ], $integration->get_config() );
}

public function test__calling_activate_when_the_integration_is_already_loaded_does_not_activate_the_integration_again(): void {
$this->expectException( 'PHPUnit_Framework_Error_Warning' );
$this->expectExceptionMessage( 'Prevented activating of integration with slug "fake" because it is already loaded.' );
/**
* Integration mock.
*
* @var MockObject|FakeIntegration
*/
$integration_mock = $this->getMockBuilder( FakeIntegration::class )->setConstructorArgs( [ 'fake' ] )->setMethods( [ 'is_loaded' ] )->getMock();
$integration_mock->expects( $this->once() )->method( 'is_loaded' )->willReturn( true );

$integration_mock->activate();

$this->assertFalse( $integration_mock->is_active() );
}

public function test__calling_activate_twice_on_same_integration_does_not_activate_the_plugin_second_time(): void {
$this->expectException( 'PHPUnit_Framework_Error_Warning' );
$this->expectExceptionMessage( 'VIP Integration with slug "fake" is already activated.' );
Expand All @@ -44,6 +61,8 @@ public function test__calling_activate_twice_on_same_integration_does_not_activa

$integration->activate();
$integration->activate();

$this->assertFalse( $integration->is_active() );
}

public function test__is_active_returns_false_when_integration_is_not_active(): void {
Expand Down
25 changes: 25 additions & 0 deletions tests/integrations/test-integrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,31 @@ public function test__integrations_are_activating_based_on_given_vip_config(): v
$this->assertEquals( [], $integration_3->get_config() );
}

public function test__configure_is_getting_called_when_the_integration_is_activated_via_vip_config(): void {
$config_mock = $this->getMockBuilder( IntegrationVipConfig::class )->disableOriginalConstructor()->setMethods( [ 'is_active_via_vip' ] )->getMock();
$config_mock->expects( $this->once() )->method( 'is_active_via_vip' )->willReturn( true );
/**
* Integrations mock.
*
* @var MockObject|Integrations
*/
$integrations_mock = $this->getMockBuilder( Integrations::class )->setMethods( [ 'get_integration_vip_config' ] )->getMock();
$integrations_mock->expects( $this->once() )->method( 'get_integration_vip_config' )->willReturn( $config_mock );
/**
* Integration mock.
*
* @var MockObject|FakeIntegration
*/
$integration_mock = $this->getMockBuilder( FakeIntegration::class )->setConstructorArgs( [ 'fake' ] )->setMethods( [ 'configure' ] )->getMock();
$integration_mock->expects( $this->once() )->method( 'configure' );

$integrations_mock->register( $integration_mock );
$integrations_mock->activate_platform_integrations();

$this->assertTrue( $integration_mock->is_active() );
$this->assertEquals( [], $integration_mock->get_config() );
}

public function test__get_integration_vip_config_returns_instance_of_IntegrationVipConfig(): void {
$integrations = new Integrations();

Expand Down
70 changes: 58 additions & 12 deletions tests/integrations/test-parsely.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,64 @@

namespace Automattic\VIP\Integrations;

use PHPUnit\Framework\MockObject\MockObject;
use WP_UnitTestCase;

use function Automattic\Test\Utils\get_class_property_as_public;
use function Automattic\Test\Utils\is_parsely_disabled;
use function Automattic\VIP\WP_Parsely_Integration\maybe_load_plugin;

// phpcs:disable Squiz.Commenting.ClassComment.Missing, Squiz.Commenting.FunctionComment.Missing, Squiz.Commenting.VariableComment.Missing

class VIP_Parsely_Integration_Test extends WP_UnitTestCase {
private string $slug = 'parsely';

public function test__load_call_is_defining_the_enabled_constant_and_adding_filter_if_plugin_is_not_enabled_already(): void {
public function test_is_loaded_returns_true_if_parsley_exist(): void {
require_once __DIR__ . '/../../wp-parsely/wp-parsely.php';

$parsely_integration = new ParselyIntegration( $this->slug );
$this->assertTrue( $parsely_integration->is_loaded() );
}

maybe_load_plugin();
$parsely_integration->load( [] );
public function test__load_call_returns_without_setting_constant_if_parsely_is_already_loaded(): void {
/**
* Integration mock.
*
* @var MockObject|ParselyIntegration
*/
$parsely_integration_mock = $this->getMockBuilder( ParselyIntegration::class )->setConstructorArgs( [ 'parsely' ] )->setMethods( [ 'is_loaded' ] )->getMock();
$parsely_integration_mock->expects( $this->once() )->method( 'is_loaded' )->willReturn( true );
$preload_state = defined( 'VIP_PARSELY_ENABLED' );

if ( is_parsely_disabled() ) {
$this->assertTrue( defined( 'VIP_PARSELY_ENABLED' ) );
$this->assertEquals( 10, has_filter( 'wp_parsely_credentials', [ $parsely_integration, 'wp_parsely_credentials_callback' ] ) );
$parsely_integration_mock->load();

$this->assertEquals( $preload_state, defined( 'VIP_PARSELY_ENABLED' ) );
}

return;
public function test__load_call_is_setting_the_enabled_constant_if_no_constant_is_defined(): void {
/**
* Integration mock.
*
* @var MockObject|ParselyIntegration
*/
$parsely_integration_mock = $this->getMockBuilder( ParselyIntegration::class )->setConstructorArgs( [ 'parsely' ] )->setMethods( [ 'is_loaded' ] )->getMock();
$parsely_integration_mock->expects( $this->once() )->method( 'is_loaded' )->willReturn( false );
$existing_value = defined( 'VIP_PARSELY_ENABLED' ) ? VIP_PARSELY_ENABLED : null;

$parsely_integration_mock->load();

if ( is_null( $existing_value ) || true == $existing_value ) {
$this->assertTrue( VIP_PARSELY_ENABLED );
} else {
$this->assertFalse( defined( 'VIP_PARSELY_ENABLED' ) );
}
}

public function test__configure_is_adding_necessary_hooks_need_for_configuration_on_vip_platform(): void {
$parsely_integration = new ParselyIntegration( $this->slug );

// Indicates enablement via filter or option.
$this->assertFalse( defined( 'VIP_PARSELY_ENABLED' ) );
$this->assertFalse( has_filter( 'wp_parsely_credentials' ) );
$parsely_integration->configure();

$this->assertEquals( 10, has_filter( 'wp_parsely_credentials', [ $parsely_integration, 'wp_parsely_credentials_callback' ] ) );
$this->assertEquals( 10, has_filter( 'wp_parsely_managed_options', [ $parsely_integration, 'wp_parsely_managed_options_callback' ] ) );
}

public function test__wp_parsely_credentials_callback_returns_original_credentials_of_the_integration_if_platform_config_is_empty(): void {
Expand Down Expand Up @@ -67,4 +98,19 @@ public function test__wp_parsely_credentials_callback_returns_platform_credentia
'api_secret' => null,
], $callback_value );
}

public function test__wp_parsely_managed_options_callback_returns_all_managed_options(): void {
$parsely_integration = new ParselyIntegration( $this->slug );
$callback_value = $parsely_integration->wp_parsely_managed_options_callback( false );

$this->assertEquals( [
'force_https_canonicals' => true,
'meta_type' => 'repeated_metas',
'cats_as_tags' => null,
'content_id_prefix' => null,
'logo' => null,
'lowercase_tags' => null,
'use_top_level_cats' => null,
], $callback_value );
}
}

0 comments on commit 53793eb

Please sign in to comment.