feat: save admin sync settings
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Handles admin settings saves.
|
||||||
|
*
|
||||||
|
* @package WPContentSync
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPContentSync\Admin;
|
||||||
|
|
||||||
|
use WPContentSync\Settings\Settings;
|
||||||
|
use WPContentSync\Settings\SettingsRepository;
|
||||||
|
|
||||||
|
final class SettingsController {
|
||||||
|
private SettingsRepository $settings_repository;
|
||||||
|
|
||||||
|
public function __construct( SettingsRepository $settings_repository ) {
|
||||||
|
$this->settings_repository = $settings_repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register(): void {
|
||||||
|
add_action( 'admin_post_wpcs_save_settings', array( $this, 'handleSave' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleSave(): void {
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
throw new \RuntimeException( 'You do not have permission to save WP Content Sync settings.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! check_admin_referer( 'wpcs_save_settings', 'wpcs_settings_nonce' ) ) {
|
||||||
|
throw new \RuntimeException( 'The settings save request could not be verified.' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified above; Settings::fromArray sanitizes the full option payload.
|
||||||
|
$data = isset( $_POST['wpcs_settings'] ) ? wp_unslash( $_POST['wpcs_settings'] ) : array();
|
||||||
|
$data = is_array( $data ) ? $data : array();
|
||||||
|
|
||||||
|
$this->settings_repository->save( Settings::fromArray( $data ) );
|
||||||
|
|
||||||
|
wp_safe_redirect(
|
||||||
|
add_query_arg(
|
||||||
|
array( 'wpcs_settings_saved' => '1' ),
|
||||||
|
admin_url( 'admin.php?page=wp-content-sync' )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ namespace WPContentSync;
|
|||||||
|
|
||||||
use WPContentSync\Admin\AdminPage;
|
use WPContentSync\Admin\AdminPage;
|
||||||
use WPContentSync\Admin\FileImportController;
|
use WPContentSync\Admin\FileImportController;
|
||||||
|
use WPContentSync\Admin\SettingsController;
|
||||||
use WPContentSync\Content\ContentHandlerRegistry;
|
use WPContentSync\Content\ContentHandlerRegistry;
|
||||||
use WPContentSync\Content\ContentRecordNormalizer;
|
use WPContentSync\Content\ContentRecordNormalizer;
|
||||||
use WPContentSync\Content\MediaContentHandler;
|
use WPContentSync\Content\MediaContentHandler;
|
||||||
@@ -169,6 +170,15 @@ final class Plugin {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$container->factory(
|
||||||
|
SettingsController::class,
|
||||||
|
static function () use ( $container ): SettingsController {
|
||||||
|
return new SettingsController(
|
||||||
|
$container->get( SettingsRepository::class )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$container->factory(
|
$container->factory(
|
||||||
RestTransportClient::class,
|
RestTransportClient::class,
|
||||||
static function (): RestTransportClient {
|
static function (): RestTransportClient {
|
||||||
@@ -209,8 +219,12 @@ final class Plugin {
|
|||||||
/** @var RestPackageController $rest_package_controller */
|
/** @var RestPackageController $rest_package_controller */
|
||||||
$rest_package_controller = $this->container->get( RestPackageController::class );
|
$rest_package_controller = $this->container->get( RestPackageController::class );
|
||||||
|
|
||||||
|
/** @var SettingsController $settings_controller */
|
||||||
|
$settings_controller = $this->container->get( SettingsController::class );
|
||||||
|
|
||||||
$admin_page->register();
|
$admin_page->register();
|
||||||
$file_import_controller->register();
|
$file_import_controller->register();
|
||||||
$rest_package_controller->register();
|
$rest_package_controller->register();
|
||||||
|
$settings_controller->register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Tests for admin settings saves.
|
||||||
|
*
|
||||||
|
* @package WPContentSync
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPContentSync\Tests\Unit\Admin;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use WPContentSync\Admin\SettingsController;
|
||||||
|
use WPContentSync\Settings\SettingsRepository;
|
||||||
|
|
||||||
|
class SettingsControllerTest extends TestCase {
|
||||||
|
protected function tearDown(): void {
|
||||||
|
unset(
|
||||||
|
$GLOBALS['wpcs_current_user_can'],
|
||||||
|
$GLOBALS['wpcs_nonce_valid'],
|
||||||
|
$GLOBALS['wpcs_redirect_location'],
|
||||||
|
$GLOBALS['wpcs_test_options'],
|
||||||
|
$GLOBALS['wpcs_test_option_autoloads']
|
||||||
|
);
|
||||||
|
|
||||||
|
$_POST = array();
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_saves_settings_with_nonce_and_capability(): void {
|
||||||
|
$GLOBALS['wpcs_current_user_can']['manage_options'] = true;
|
||||||
|
|
||||||
|
$GLOBALS['wpcs_nonce_valid']['wpcs_save_settings']['wpcs_settings_nonce'] = true;
|
||||||
|
|
||||||
|
$_POST['wpcs_settings'] = array(
|
||||||
|
'logging_level' => 'debug',
|
||||||
|
'conflict_strategy' => 'manual_review',
|
||||||
|
'sync_pairs' => array(
|
||||||
|
array(
|
||||||
|
'name' => 'Staging',
|
||||||
|
'source_url' => 'https://example.test',
|
||||||
|
'destination_url' => 'https://staging.example.test',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
( new SettingsController( new SettingsRepository() ) )->handleSave();
|
||||||
|
|
||||||
|
self::assertSame( 'debug', $GLOBALS['wpcs_test_options'][ SettingsRepository::OPTION_NAME ]['logging_level'] );
|
||||||
|
self::assertSame( 'manual_review', $GLOBALS['wpcs_test_options'][ SettingsRepository::OPTION_NAME ]['conflict_strategy'] );
|
||||||
|
self::assertStringContainsString( 'wpcs_settings_saved=1', $GLOBALS['wpcs_redirect_location'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_rejects_users_without_manage_options(): void {
|
||||||
|
$GLOBALS['wpcs_current_user_can']['manage_options'] = false;
|
||||||
|
|
||||||
|
$this->expectException( \RuntimeException::class );
|
||||||
|
$this->expectExceptionMessage( 'You do not have permission to save WP Content Sync settings.' );
|
||||||
|
|
||||||
|
( new SettingsController( new SettingsRepository() ) )->handleSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_rejects_invalid_nonces(): void {
|
||||||
|
$GLOBALS['wpcs_nonce_valid']['wpcs_save_settings']['wpcs_settings_nonce'] = false;
|
||||||
|
|
||||||
|
$this->expectException( \RuntimeException::class );
|
||||||
|
$this->expectExceptionMessage( 'The settings save request could not be verified.' );
|
||||||
|
|
||||||
|
( new SettingsController( new SettingsRepository() ) )->handleSave();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ namespace WPContentSync\Tests\Unit;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use WPContentSync\Admin\FileImportController;
|
use WPContentSync\Admin\FileImportController;
|
||||||
|
use WPContentSync\Admin\SettingsController;
|
||||||
use WPContentSync\Content\ContentHandlerRegistry;
|
use WPContentSync\Content\ContentHandlerRegistry;
|
||||||
use WPContentSync\Content\ContentRecordNormalizer;
|
use WPContentSync\Content\ContentRecordNormalizer;
|
||||||
use WPContentSync\Content\MediaContentHandler;
|
use WPContentSync\Content\MediaContentHandler;
|
||||||
@@ -51,6 +52,15 @@ class PluginTest extends TestCase {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_it_registers_settings_controller(): void {
|
||||||
|
$container = $this->getPluginContainer( Plugin::create() );
|
||||||
|
|
||||||
|
self::assertInstanceOf(
|
||||||
|
SettingsController::class,
|
||||||
|
$container->get( SettingsController::class )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_it_registers_rest_transport_services(): void {
|
public function test_it_registers_rest_transport_services(): void {
|
||||||
$container = $this->getPluginContainer( Plugin::create() );
|
$container = $this->getPluginContainer( Plugin::create() );
|
||||||
|
|
||||||
@@ -85,6 +95,15 @@ class PluginTest extends TestCase {
|
|||||||
self::assertArrayHasKey( 'rest_api_init', $GLOBALS['wpcs_test_actions'] );
|
self::assertArrayHasKey( 'rest_api_init', $GLOBALS['wpcs_test_actions'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_it_hooks_settings_controller_on_register(): void {
|
||||||
|
unset( $GLOBALS['wpcs_test_actions'] );
|
||||||
|
|
||||||
|
$plugin = Plugin::create();
|
||||||
|
$plugin->register();
|
||||||
|
|
||||||
|
self::assertArrayHasKey( 'admin_post_wpcs_save_settings', $GLOBALS['wpcs_test_actions'] );
|
||||||
|
}
|
||||||
|
|
||||||
private function getPluginContainer( Plugin $plugin ): Container {
|
private function getPluginContainer( Plugin $plugin ): Container {
|
||||||
$reflection = new \ReflectionClass( $plugin );
|
$reflection = new \ReflectionClass( $plugin );
|
||||||
$property = $reflection->getProperty( 'container' );
|
$property = $reflection->getProperty( 'container' );
|
||||||
|
|||||||
Reference in New Issue
Block a user