mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-08-11 12:20:22 +00:00
Customize: Add selective refresh framework with implementation for widgets and re-implementation for nav menus.
See https://make.wordpress.org/core/2016/02/16/selective-refresh-in-the-customizer/. Props westonruter, valendesigns, DrewAPicture, ocean90. Fixes #27355. git-svn-id: https://develop.svn.wordpress.org/trunk@36586 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -425,7 +425,7 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase {
|
||||
$data = json_decode( $json, true );
|
||||
$this->assertNotEmpty( $data );
|
||||
|
||||
$this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices' ), array_keys( $data ) );
|
||||
$this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'selectiveRefreshEnabled' ), array_keys( $data ) );
|
||||
$this->assertEquals( $autofocus, $data['autofocus'] );
|
||||
$this->assertArrayHasKey( 'save', $data['nonce'] );
|
||||
$this->assertArrayHasKey( 'preview', $data['nonce'] );
|
||||
|
||||
@@ -69,7 +69,6 @@ class Test_WP_Customize_Nav_Menu_Item_Setting extends WP_UnitTestCase {
|
||||
|
||||
$setting = new WP_Customize_Nav_Menu_Item_Setting( $this->wp_customize, 'nav_menu_item[123]' );
|
||||
$this->assertEquals( 'nav_menu_item', $setting->type );
|
||||
$this->assertEquals( 'postMessage', $setting->transport );
|
||||
$this->assertEquals( 123, $setting->post_id );
|
||||
$this->assertNull( $setting->previous_post_id );
|
||||
$this->assertNull( $setting->update_status );
|
||||
|
||||
@@ -353,11 +353,11 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
|
||||
|
||||
$expected = array( 'type' => 'nav_menu_item' );
|
||||
$results = $menus->filter_dynamic_setting_args( $this->wp_customize, 'nav_menu_item[123]' );
|
||||
$this->assertEquals( $expected, $results );
|
||||
$this->assertEquals( $expected['type'], $results['type'] );
|
||||
|
||||
$expected = array( 'type' => 'nav_menu' );
|
||||
$results = $menus->filter_dynamic_setting_args( $this->wp_customize, 'nav_menu[123]' );
|
||||
$this->assertEquals( $expected, $results );
|
||||
$this->assertEquals( $expected['type'], $results['type'] );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -522,6 +522,28 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
|
||||
$this->assertContains( 'data-object="custom_object"', $template );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Nav_Menus::customize_dynamic_partial_args().
|
||||
*
|
||||
* @see WP_Customize_Nav_Menus::customize_dynamic_partial_args()
|
||||
*/
|
||||
function test_customize_dynamic_partial_args() {
|
||||
do_action( 'customize_register', $this->wp_customize );
|
||||
|
||||
$args = apply_filters( 'customize_dynamic_partial_args', false, 'nav_menu_instance[68b329da9893e34099c7d8ad5cb9c940]' );
|
||||
$this->assertInternalType( 'array', $args );
|
||||
$this->assertEquals( 'nav_menu_instance', $args['type'] );
|
||||
$this->assertEquals( array( $this->wp_customize->nav_menus, 'render_nav_menu_partial' ), $args['render_callback'] );
|
||||
$this->assertTrue( $args['container_inclusive'] );
|
||||
|
||||
$args = apply_filters( 'customize_dynamic_partial_args', array( 'fallback_refresh' => false ), 'nav_menu_instance[4099c7d8ad5cb9c94068b329da9893e3]' );
|
||||
$this->assertInternalType( 'array', $args );
|
||||
$this->assertEquals( 'nav_menu_instance', $args['type'] );
|
||||
$this->assertEquals( array( $this->wp_customize->nav_menus, 'render_nav_menu_partial' ), $args['render_callback'] );
|
||||
$this->assertTrue( $args['container_inclusive'] );
|
||||
$this->assertFalse( $args['fallback_refresh'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the customize_preview_init method.
|
||||
*
|
||||
@@ -532,13 +554,9 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
|
||||
$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
|
||||
|
||||
$menus->customize_preview_init();
|
||||
$this->assertEquals( 10, has_action( 'template_redirect', array( $menus, 'render_menu' ) ) );
|
||||
$this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $menus, 'customize_preview_enqueue_deps' ) ) );
|
||||
|
||||
if ( ! isset( $_REQUEST[ WP_Customize_Nav_Menus::RENDER_QUERY_VAR ] ) ) {
|
||||
$this->assertEquals( 1000, has_filter( 'wp_nav_menu_args', array( $menus, 'filter_wp_nav_menu_args' ) ) );
|
||||
$this->assertEquals( 10, has_filter( 'wp_nav_menu', array( $menus, 'filter_wp_nav_menu' ) ) );
|
||||
}
|
||||
$this->assertEquals( 1000, has_filter( 'wp_nav_menu_args', array( $menus, 'filter_wp_nav_menu_args' ) ) );
|
||||
$this->assertEquals( 10, has_filter( 'wp_nav_menu', array( $menus, 'filter_wp_nav_menu' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -548,37 +566,36 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
|
||||
*/
|
||||
function test_filter_wp_nav_menu_args() {
|
||||
do_action( 'customize_register', $this->wp_customize );
|
||||
$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
|
||||
$menus = $this->wp_customize->nav_menus;
|
||||
|
||||
$results = $menus->filter_wp_nav_menu_args( array(
|
||||
'echo' => true,
|
||||
'fallback_cb' => 'wp_page_menu',
|
||||
'walker' => '',
|
||||
'menu' => wp_create_nav_menu( 'Foo' ),
|
||||
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
|
||||
) );
|
||||
$this->assertEquals( 1, $results['can_partial_refresh'] );
|
||||
$this->assertArrayHasKey( 'customize_preview_nav_menus_args', $results );
|
||||
|
||||
$expected = array(
|
||||
'echo',
|
||||
'can_partial_refresh',
|
||||
'fallback_cb',
|
||||
'instance_number',
|
||||
'walker',
|
||||
);
|
||||
$results = $menus->filter_wp_nav_menu_args( array(
|
||||
'echo' => false,
|
||||
'fallback_cb' => 'wp_page_menu',
|
||||
'walker' => new Walker_Nav_Menu(),
|
||||
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
|
||||
) );
|
||||
$this->assertEqualSets( $expected, array_keys( $results ) );
|
||||
$this->assertArrayNotHasKey( 'customize_preview_nav_menus_args', $results );
|
||||
$this->assertEquals( 'wp_page_menu', $results['fallback_cb'] );
|
||||
$this->assertEquals( 0, $results['can_partial_refresh'] );
|
||||
|
||||
$this->assertNotEmpty( $menus->preview_nav_menu_instance_args[ $results['instance_number'] ] );
|
||||
$preview_nav_menu_instance_args = $menus->preview_nav_menu_instance_args[ $results['instance_number'] ];
|
||||
$this->assertEquals( '', $preview_nav_menu_instance_args['fallback_cb'] );
|
||||
$this->assertEquals( '', $preview_nav_menu_instance_args['walker'] );
|
||||
$this->assertNotEmpty( $preview_nav_menu_instance_args['args_hash'] );
|
||||
$nav_menu_term = get_term( wp_create_nav_menu( 'Bar' ) );
|
||||
$results = $menus->filter_wp_nav_menu_args( array(
|
||||
'echo' => true,
|
||||
'fallback_cb' => 'wp_page_menu',
|
||||
'walker' => '',
|
||||
'menu' => $nav_menu_term,
|
||||
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
|
||||
) );
|
||||
$this->assertArrayHasKey( 'customize_preview_nav_menus_args', $results );
|
||||
$this->assertEquals( $nav_menu_term->term_id, $results['customize_preview_nav_menus_args']['menu'] );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -595,19 +612,18 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
|
||||
'menu' => wp_create_nav_menu( 'Foo' ),
|
||||
'fallback_cb' => 'wp_page_menu',
|
||||
'walker' => '',
|
||||
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
|
||||
) );
|
||||
|
||||
ob_start();
|
||||
wp_nav_menu( $args );
|
||||
$nav_menu_content = ob_get_clean();
|
||||
|
||||
$object_args = json_decode( json_encode( $args ), false );
|
||||
$result = $menus->filter_wp_nav_menu( $nav_menu_content, $object_args );
|
||||
$expected = sprintf(
|
||||
'<div class="partial-refreshable-nav-menu partial-refreshable-nav-menu-%1$d menu">',
|
||||
$args['instance_number']
|
||||
);
|
||||
$this->assertStringStartsWith( $expected, $result );
|
||||
$result = $menus->filter_wp_nav_menu( $nav_menu_content, (object) $args );
|
||||
|
||||
$this->assertContains( sprintf( ' data-customize-partial-id="nav_menu_instance[%s]"', $args['customize_preview_nav_menus_args']['args_hmac'] ), $result );
|
||||
$this->assertContains( ' data-customize-partial-type="nav_menu_instance"', $result );
|
||||
$this->assertContains( ' data-customize-partial-placement-context="', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -622,31 +638,62 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
|
||||
$menus->customize_preview_enqueue_deps();
|
||||
|
||||
$this->assertTrue( wp_script_is( 'customize-preview-nav-menus' ) );
|
||||
$this->assertEquals( 10, has_action( 'wp_print_footer_scripts', array( $menus, 'export_preview_data' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the export_preview_data method.
|
||||
* Test WP_Customize_Nav_Menus::export_preview_data() method.
|
||||
*
|
||||
* @see WP_Customize_Nav_Menus::export_preview_data()
|
||||
*/
|
||||
function test_export_preview_data() {
|
||||
do_action( 'customize_register', $this->wp_customize );
|
||||
$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
|
||||
$this->setExpectedDeprecated( 'WP_Customize_Nav_Menus::export_preview_data' );
|
||||
$this->wp_customize->nav_menus->export_preview_data();
|
||||
}
|
||||
|
||||
$request_uri = $_SERVER['REQUEST_URI'];
|
||||
/**
|
||||
* Test WP_Customize_Nav_Menus::render_nav_menu_partial() method.
|
||||
*
|
||||
* @see WP_Customize_Nav_Menus::render_nav_menu_partial()
|
||||
*/
|
||||
function test_render_nav_menu_partial() {
|
||||
$this->wp_customize->nav_menus->customize_preview_init();
|
||||
|
||||
ob_start();
|
||||
$_SERVER['REQUEST_URI'] = '/wp-admin';
|
||||
$menus->export_preview_data();
|
||||
$data = ob_get_clean();
|
||||
$menu = wp_create_nav_menu( 'Foo' );
|
||||
wp_update_nav_menu_item( $menu, 0, array(
|
||||
'menu-item-type' => 'custom',
|
||||
'menu-item-title' => 'WordPress.org',
|
||||
'menu-item-url' => 'https://wordpress.org',
|
||||
'menu-item-status' => 'publish',
|
||||
) );
|
||||
|
||||
$_SERVER['REQUEST_URI'] = $request_uri;
|
||||
$nav_menu_args = $this->wp_customize->nav_menus->filter_wp_nav_menu_args( array(
|
||||
'echo' => true,
|
||||
'menu' => $menu,
|
||||
'fallback_cb' => 'wp_page_menu',
|
||||
'walker' => '',
|
||||
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
|
||||
) );
|
||||
|
||||
$this->assertContains( '_wpCustomizePreviewNavMenusExports', $data );
|
||||
$this->assertContains( 'renderQueryVar', $data );
|
||||
$this->assertContains( 'renderNonceValue', $data );
|
||||
$this->assertContains( 'renderNoncePostKey', $data );
|
||||
$this->assertContains( 'navMenuInstanceArgs', $data );
|
||||
$partial_id = sprintf( 'nav_menu_instance[%s]', $nav_menu_args['customize_preview_nav_menus_args']['args_hmac'] );
|
||||
$partials = $this->wp_customize->selective_refresh->add_dynamic_partials( array( $partial_id ) );
|
||||
$this->assertNotEmpty( $partials );
|
||||
$partial = array_shift( $partials );
|
||||
$this->assertEquals( $partial_id, $partial->id );
|
||||
|
||||
$missing_args_hmac_args = array_merge(
|
||||
$nav_menu_args['customize_preview_nav_menus_args'],
|
||||
array( 'args_hmac' => null )
|
||||
);
|
||||
$this->assertFalse( $partial->render( $missing_args_hmac_args ) );
|
||||
|
||||
$args_hmac_mismatch_args = array_merge(
|
||||
$nav_menu_args['customize_preview_nav_menus_args'],
|
||||
array( 'args_hmac' => strrev( $nav_menu_args['customize_preview_nav_menus_args']['args_hmac'] ) )
|
||||
);
|
||||
$this->assertFalse( $partial->render( $args_hmac_mismatch_args ) );
|
||||
|
||||
$rendered = $partial->render( $nav_menu_args['customize_preview_nav_menus_args'] );
|
||||
$this->assertContains( 'data-customize-partial-type="nav_menu_instance"', $rendered );
|
||||
$this->assertContains( 'WordPress.org', $rendered );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
/**
|
||||
* Test_WP_Customize_Partial tests.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for the Test_WP_Customize_Partial class.
|
||||
*
|
||||
* @group customize
|
||||
*/
|
||||
class Test_WP_Customize_Partial extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Manager.
|
||||
*
|
||||
* @var WP_Customize_Manager
|
||||
*/
|
||||
public $wp_customize;
|
||||
|
||||
/**
|
||||
* Component.
|
||||
*
|
||||
* @var WP_Customize_Selective_Refresh
|
||||
*/
|
||||
public $selective_refresh;
|
||||
|
||||
/**
|
||||
* Set up.
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
|
||||
// @codingStandardsIgnoreStart
|
||||
$GLOBALS['wp_customize'] = new WP_Customize_Manager();
|
||||
// @codingStandardsIgnoreEnd
|
||||
$this->wp_customize = $GLOBALS['wp_customize'];
|
||||
if ( isset( $this->wp_customize->selective_refresh ) ) {
|
||||
$this->selective_refresh = $this->wp_customize->selective_refresh;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::__construct().
|
||||
*
|
||||
* @see WP_Customize_Partial::__construct()
|
||||
*/
|
||||
function test_construct_default_args() {
|
||||
$partial_id = 'blogname';
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id );
|
||||
$this->assertEquals( $partial_id, $partial->id );
|
||||
$this->assertEquals( $this->selective_refresh, $partial->component );
|
||||
$this->assertEquals( 'default', $partial->type );
|
||||
$this->assertEmpty( $partial->selector );
|
||||
$this->assertEquals( array( $partial_id ), $partial->settings );
|
||||
$this->assertEquals( $partial_id, $partial->primary_setting );
|
||||
$this->assertEquals( array( $partial, 'render_callback' ), $partial->render_callback );
|
||||
$this->assertEquals( false, $partial->container_inclusive );
|
||||
$this->assertEquals( true, $partial->fallback_refresh );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render post content partial.
|
||||
*
|
||||
* @param WP_Customize_Partial $partial Partial.
|
||||
* @return string|false Content or false if error.
|
||||
*/
|
||||
function render_post_content_partial( $partial ) {
|
||||
$id_data = $partial->id_data();
|
||||
$post_id = intval( $id_data['keys'][0] );
|
||||
if ( empty( $post_id ) ) {
|
||||
return false;
|
||||
}
|
||||
$post = get_post( $post_id );
|
||||
if ( ! $post ) {
|
||||
return false;
|
||||
}
|
||||
return apply_filters( 'the_content', $post->post_content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::__construct().
|
||||
*
|
||||
* @see WP_Customize_Partial::__construct()
|
||||
*/
|
||||
function test_construct_non_default_args() {
|
||||
|
||||
$post_id = self::factory()->post->create( array(
|
||||
'post_title' => 'Hello World',
|
||||
'post_content' => 'Lorem Ipsum',
|
||||
) );
|
||||
|
||||
$partial_id = sprintf( 'post_content[%d]', $post_id );
|
||||
$args = array(
|
||||
'type' => 'post',
|
||||
'selector' => "article.post-$post_id .entry-content",
|
||||
'settings' => array( 'user[1]', "post[$post_id]" ),
|
||||
'primary_setting' => "post[$post_id]",
|
||||
'render_callback' => array( $this, 'render_post_content_partial' ),
|
||||
'container_inclusive' => false,
|
||||
'fallback_refresh' => false,
|
||||
);
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id, $args );
|
||||
$this->assertEquals( $partial_id, $partial->id );
|
||||
$this->assertEquals( $this->selective_refresh, $partial->component );
|
||||
$this->assertEquals( $args['type'], $partial->type );
|
||||
$this->assertEquals( $args['selector'], $partial->selector );
|
||||
$this->assertEqualSets( $args['settings'], $partial->settings );
|
||||
$this->assertEquals( $args['primary_setting'], $partial->primary_setting );
|
||||
$this->assertEquals( $args['render_callback'], $partial->render_callback );
|
||||
$this->assertEquals( false, $partial->container_inclusive );
|
||||
$this->assertEquals( false, $partial->fallback_refresh );
|
||||
$this->assertContains( 'Lorem Ipsum', $partial->render() );
|
||||
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id, array(
|
||||
'settings' => 'blogdescription',
|
||||
) );
|
||||
$this->assertEquals( array( 'blogdescription' ), $partial->settings );
|
||||
$this->assertEquals( 'blogdescription', $partial->primary_setting );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::id_data().
|
||||
*
|
||||
* @see WP_Customize_Partial::id_data()
|
||||
*/
|
||||
function test_id_data() {
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo' );
|
||||
$id_data = $partial->id_data();
|
||||
$this->assertEquals( 'foo', $id_data['base'] );
|
||||
$this->assertEquals( array(), $id_data['keys'] );
|
||||
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, 'bar[baz][quux]' );
|
||||
$id_data = $partial->id_data();
|
||||
$this->assertEquals( 'bar', $id_data['base'] );
|
||||
$this->assertEquals( array( 'baz', 'quux' ), $id_data['keys'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of filter calls to customize_partial_render.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $count_filter_customize_partial_render = 0;
|
||||
|
||||
/**
|
||||
* Keep track of filter calls to customize_partial_render_{$partial->id}.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $count_filter_customize_partial_render_with_id = 0;
|
||||
|
||||
/**
|
||||
* Filter customize_partial_render.
|
||||
*
|
||||
* @param string|false $rendered Content.
|
||||
* @param WP_Customize_Partial $partial Partial.
|
||||
* @param array $container_context Data.
|
||||
* @return string|false Content.
|
||||
*/
|
||||
function filter_customize_partial_render( $rendered, $partial, $container_context ) {
|
||||
$this->assertTrue( false === $rendered || is_string( $rendered ) );
|
||||
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
|
||||
$this->assertInternalType( 'array', $container_context );
|
||||
$this->count_filter_customize_partial_render += 1;
|
||||
return $rendered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter customize_partial_render_{$partial->id}.
|
||||
*
|
||||
* @param string|false $rendered Content.
|
||||
* @param WP_Customize_Partial $partial Partial.
|
||||
* @param array $container_context Data.
|
||||
* @return string|false Content.
|
||||
*/
|
||||
function filter_customize_partial_render_with_id( $rendered, $partial, $container_context ) {
|
||||
$this->assertEquals( sprintf( 'customize_partial_render_%s', $partial->id ), current_filter() );
|
||||
$this->assertTrue( false === $rendered || is_string( $rendered ) );
|
||||
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
|
||||
$this->assertInternalType( 'array', $container_context );
|
||||
$this->count_filter_customize_partial_render_with_id += 1;
|
||||
return $rendered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bad render_callback().
|
||||
*
|
||||
* @return string Content.
|
||||
*/
|
||||
function render_echo_and_return() {
|
||||
echo 'foo';
|
||||
return 'bar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Echo render_callback().
|
||||
*/
|
||||
function render_echo() {
|
||||
echo 'foo';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return render_callback().
|
||||
*
|
||||
* @return string Content.
|
||||
*/
|
||||
function render_return() {
|
||||
return 'bar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::render() with a bad return_callback.
|
||||
*
|
||||
* @see WP_Customize_Partial::render()
|
||||
*/
|
||||
function test_render_bad_callback() {
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo', array(
|
||||
'render_callback' => array( $this, 'render_echo_and_return' ),
|
||||
) );
|
||||
$this->setExpectedIncorrectUsage( 'render' );
|
||||
$partial->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::render() with a return_callback that echos.
|
||||
*
|
||||
* @see WP_Customize_Partial::render()
|
||||
*/
|
||||
function test_render_echo_callback() {
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo', array(
|
||||
'render_callback' => array( $this, 'render_echo' ),
|
||||
) );
|
||||
$count_filter_customize_partial_render = $this->count_filter_customize_partial_render;
|
||||
$count_filter_customize_partial_render_with_id = $this->count_filter_customize_partial_render_with_id;
|
||||
add_filter( 'customize_partial_render', array( $this, 'filter_customize_partial_render' ), 10, 3 );
|
||||
add_filter( "customize_partial_render_{$partial->id}", array( $this, 'filter_customize_partial_render_with_id' ), 10, 3 );
|
||||
$rendered = $partial->render();
|
||||
$this->assertEquals( 'foo', $rendered );
|
||||
$this->assertEquals( $count_filter_customize_partial_render + 1, $this->count_filter_customize_partial_render );
|
||||
$this->assertEquals( $count_filter_customize_partial_render_with_id + 1, $this->count_filter_customize_partial_render_with_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::render() with a return_callback that echos.
|
||||
*
|
||||
* @see WP_Customize_Partial::render()
|
||||
*/
|
||||
function test_render_return_callback() {
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo', array(
|
||||
'render_callback' => array( $this, 'render_return' ),
|
||||
) );
|
||||
$count_filter_customize_partial_render = $this->count_filter_customize_partial_render;
|
||||
$count_filter_customize_partial_render_with_id = $this->count_filter_customize_partial_render_with_id;
|
||||
add_filter( 'customize_partial_render', array( $this, 'filter_customize_partial_render' ), 10, 3 );
|
||||
add_filter( "customize_partial_render_{$partial->id}", array( $this, 'filter_customize_partial_render_with_id' ), 10, 3 );
|
||||
$rendered = $partial->render();
|
||||
$this->assertEquals( 'bar', $rendered );
|
||||
$this->assertEquals( $count_filter_customize_partial_render + 1, $this->count_filter_customize_partial_render );
|
||||
$this->assertEquals( $count_filter_customize_partial_render_with_id + 1, $this->count_filter_customize_partial_render_with_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::render_callback() default.
|
||||
*
|
||||
* @see WP_Customize_Partial::render_callback()
|
||||
*/
|
||||
function test_render_callback_default() {
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, 'foo' );
|
||||
$this->assertFalse( $partial->render_callback() );
|
||||
$this->assertFalse( call_user_func( $partial->render_callback ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Partial::json() default.
|
||||
*
|
||||
* @see WP_Customize_Partial::json()
|
||||
*/
|
||||
function test_json() {
|
||||
$post_id = 123;
|
||||
$partial_id = sprintf( 'post_content[%d]', $post_id );
|
||||
$args = array(
|
||||
'type' => 'post',
|
||||
'selector' => "article.post-$post_id .entry-content",
|
||||
'settings' => array( 'user[1]', "post[$post_id]" ),
|
||||
'primary_setting' => "post[$post_id]",
|
||||
'render_callback' => array( $this, 'render_post_content_partial' ),
|
||||
'container_inclusive' => false,
|
||||
'fallback_refresh' => false,
|
||||
);
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, $partial_id, $args );
|
||||
|
||||
$exported = $partial->json();
|
||||
$this->assertArrayHasKey( 'settings', $exported );
|
||||
$this->assertArrayHasKey( 'primarySetting', $exported );
|
||||
$this->assertArrayHasKey( 'selector', $exported );
|
||||
$this->assertArrayHasKey( 'type', $exported );
|
||||
$this->assertArrayHasKey( 'fallbackRefresh', $exported );
|
||||
$this->assertArrayHasKey( 'containerInclusive', $exported );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down.
|
||||
*/
|
||||
function tearDown() {
|
||||
$this->wp_customize = null;
|
||||
unset( $GLOBALS['wp_customize'] );
|
||||
parent::tearDown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
<?php
|
||||
/**
|
||||
* WP_Customize_Selective_Refresh Ajax tests.
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage UnitTests
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for the WP_Customize_Selective_Refresh class Ajax.
|
||||
*
|
||||
* Note that this is intentionally not extending WP_Ajax_UnitTestCase because it
|
||||
* is not admin ajax.
|
||||
*
|
||||
* @since 4.5.0
|
||||
* @group ajax
|
||||
*/
|
||||
class Test_WP_Customize_Selective_Refresh_Ajax extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Manager.
|
||||
*
|
||||
* @var WP_Customize_Manager
|
||||
*/
|
||||
public $wp_customize;
|
||||
|
||||
/**
|
||||
* Component.
|
||||
*
|
||||
* @var WP_Customize_Selective_Refresh
|
||||
*/
|
||||
public $selective_refresh;
|
||||
|
||||
/**
|
||||
* Set up the test fixture.
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Define DOING_AJAX so that wp_die() will be used instead of die().
|
||||
if ( ! defined( 'DOING_AJAX' ) ) {
|
||||
define( 'DOING_AJAX', true );
|
||||
}
|
||||
add_filter( 'wp_die_ajax_handler', array( $this, 'get_wp_die_handler' ), 1, 1 );
|
||||
|
||||
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
|
||||
// @codingStandardsIgnoreStart
|
||||
$GLOBALS['wp_customize'] = new WP_Customize_Manager();
|
||||
// @codingStandardsIgnoreEnd
|
||||
$this->wp_customize = $GLOBALS['wp_customize'];
|
||||
if ( isset( $this->wp_customize->selective_refresh ) ) {
|
||||
$this->selective_refresh = $this->wp_customize->selective_refresh;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Customizer boot actions.
|
||||
*/
|
||||
function do_customize_boot_actions() {
|
||||
// Remove actions that call add_theme_support( 'title-tag' ).
|
||||
remove_action( 'after_setup_theme', 'twentyfifteen_setup' );
|
||||
remove_action( 'after_setup_theme', 'twentysixteen_setup' );
|
||||
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||
do_action( 'setup_theme' );
|
||||
do_action( 'after_setup_theme' );
|
||||
do_action( 'init' );
|
||||
do_action( 'customize_register', $this->wp_customize );
|
||||
$this->wp_customize->customize_preview_init();
|
||||
do_action( 'wp', $GLOBALS['wp'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::handle_render_partials_request().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
|
||||
*/
|
||||
function test_handle_render_partials_request_for_unauthenticated_user() {
|
||||
$_POST[ WP_Customize_Selective_Refresh::RENDER_QUERY_VAR ] = '1';
|
||||
|
||||
// Check current_user_cannot_customize.
|
||||
ob_start();
|
||||
try {
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
unset( $e );
|
||||
}
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertFalse( $output['success'] );
|
||||
$this->assertEquals( 'expected_customize_preview', $output['data'] );
|
||||
|
||||
// Check expected_customize_preview.
|
||||
wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
|
||||
$_REQUEST['nonce'] = wp_create_nonce( 'preview-customize_' . $this->wp_customize->theme()->get_stylesheet() );
|
||||
ob_start();
|
||||
try {
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
unset( $e );
|
||||
}
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertFalse( $output['success'] );
|
||||
$this->assertEquals( 'expected_customize_preview', $output['data'] );
|
||||
|
||||
// Check missing_partials.
|
||||
$this->do_customize_boot_actions();
|
||||
ob_start();
|
||||
try {
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
unset( $e );
|
||||
}
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertFalse( $output['success'] );
|
||||
$this->assertEquals( 'missing_partials', $output['data'] );
|
||||
|
||||
// Check missing_partials.
|
||||
$_POST['partials'] = 'bad';
|
||||
$this->do_customize_boot_actions();
|
||||
ob_start();
|
||||
try {
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
$this->assertEquals( '', $e->getMessage() );
|
||||
}
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertFalse( $output['success'] );
|
||||
$this->assertEquals( 'malformed_partials', $output['data'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current user to be an admin, add the preview nonce, and set the query var.
|
||||
*/
|
||||
function setup_valid_render_partials_request_environment() {
|
||||
wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
|
||||
$_REQUEST['nonce'] = wp_create_nonce( 'preview-customize_' . $this->wp_customize->theme()->get_stylesheet() );
|
||||
$_POST[ WP_Customize_Selective_Refresh::RENDER_QUERY_VAR ] = '1';
|
||||
$this->do_customize_boot_actions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the Customizer "signature" is not included in partial render responses.
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
|
||||
*/
|
||||
function test_handle_render_partials_request_removes_customize_signature() {
|
||||
$this->setup_valid_render_partials_request_environment();
|
||||
$this->assertTrue( is_customize_preview() );
|
||||
$this->assertEquals( 1000, has_action( 'shutdown', array( $this->wp_customize, 'customize_preview_signature' ) ) );
|
||||
ob_start();
|
||||
try {
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
unset( $e );
|
||||
}
|
||||
ob_end_clean();
|
||||
$this->assertFalse( has_action( 'shutdown', array( $this->wp_customize, 'customize_preview_signature' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() for an unrecognized partial.
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
|
||||
*/
|
||||
function test_handle_render_partials_request_for_unrecognized_partial() {
|
||||
$this->setup_valid_render_partials_request_environment();
|
||||
$context_data = array();
|
||||
$placements = array( $context_data );
|
||||
|
||||
$_POST['partials'] = wp_slash( wp_json_encode( array(
|
||||
'foo' => $placements,
|
||||
) ) );
|
||||
|
||||
ob_start();
|
||||
try {
|
||||
$this->expected_partial_ids = array( 'foo' );
|
||||
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
|
||||
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
|
||||
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
$this->assertEquals( '', $e->getMessage() );
|
||||
}
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertTrue( $output['success'] );
|
||||
$this->assertInternalType( 'array', $output['data'] );
|
||||
$this->assertArrayHasKey( 'contents', $output['data'] );
|
||||
$this->assertArrayHasKey( 'errors', $output['data'] );
|
||||
$this->assertArrayHasKey( 'foo', $output['data']['contents'] );
|
||||
$this->assertEquals( null, $output['data']['contents']['foo'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() for a partial that does not render.
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
|
||||
*/
|
||||
function test_handle_render_partials_request_for_non_rendering_partial() {
|
||||
$this->setup_valid_render_partials_request_environment();
|
||||
$this->wp_customize->selective_refresh->add_partial( 'foo', array( 'settings' => array( 'home' ) ) );
|
||||
$context_data = array();
|
||||
$placements = array( $context_data );
|
||||
|
||||
$_POST['partials'] = wp_slash( wp_json_encode( array(
|
||||
'foo' => $placements,
|
||||
) ) );
|
||||
|
||||
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
|
||||
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
|
||||
ob_start();
|
||||
try {
|
||||
$this->expected_partial_ids = array( 'foo' );
|
||||
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
|
||||
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
|
||||
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
$this->assertEquals( '', $e->getMessage() );
|
||||
}
|
||||
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
|
||||
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertEquals( array( false ), $output['data']['contents']['foo'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rendered blogname.
|
||||
*
|
||||
* @param WP_Customize_Partial $partial Partial.
|
||||
* @param array $context Context data.
|
||||
* @return string
|
||||
*/
|
||||
function render_callback_blogname( $partial, $context ) {
|
||||
$this->assertInternalType( 'array', $context );
|
||||
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
|
||||
return get_bloginfo( 'name', 'display' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rendered blogdescription.
|
||||
*
|
||||
* @param WP_Customize_Partial $partial Partial.
|
||||
* @param array $context Context data.
|
||||
* @return string
|
||||
*/
|
||||
function render_callback_blogdescription( $partial, $context ) {
|
||||
$this->assertInternalType( 'array', $context );
|
||||
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
|
||||
$x = get_bloginfo( 'description', 'display' );
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() for a partial that does render.
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
|
||||
*/
|
||||
function test_handle_render_partials_request_with_single_valid_placement() {
|
||||
$this->setup_valid_render_partials_request_environment();
|
||||
|
||||
$this->wp_customize->selective_refresh->add_partial( 'test_blogname', array(
|
||||
'settings' => array( 'blogname' ),
|
||||
'render_callback' => array( $this, 'render_callback_blogname' ),
|
||||
) );
|
||||
|
||||
$context_data = array();
|
||||
$placements = array( $context_data );
|
||||
|
||||
$_POST['partials'] = wp_slash( wp_json_encode( array(
|
||||
'test_blogname' => $placements,
|
||||
) ) );
|
||||
|
||||
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
|
||||
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
|
||||
ob_start();
|
||||
try {
|
||||
$this->expected_partial_ids = array( 'test_blogname' );
|
||||
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
|
||||
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
|
||||
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
$this->assertEquals( '', $e->getMessage() );
|
||||
}
|
||||
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
|
||||
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertEquals( array( get_bloginfo( 'name', 'display' ) ), $output['data']['contents']['test_blogname'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter customize_dynamic_partial_args.
|
||||
*
|
||||
* @param array $partial_args Partial args.
|
||||
* @param string $partial_id Partial ID.
|
||||
*
|
||||
* @return array|false Args.
|
||||
*/
|
||||
function filter_customize_dynamic_partial_args( $partial_args, $partial_id ) {
|
||||
if ( 'test_dynamic_blogname' === $partial_id ) {
|
||||
$partial_args = array(
|
||||
'settings' => array( 'blogname' ),
|
||||
'render_callback' => array( $this, 'render_callback_blogname' ),
|
||||
);
|
||||
}
|
||||
return $partial_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter customize_render_partials_response.
|
||||
*
|
||||
* @param array $response Response.
|
||||
* @param WP_Customize_Selective_Refresh $component Selective refresh component.
|
||||
* @param array $partial_placements Placements' context data for the partials rendered in the request.
|
||||
* The array is keyed by partial ID, with each item being an array of
|
||||
* the placements' context data.
|
||||
* @return array Response.
|
||||
*/
|
||||
function filter_customize_render_partials_response( $response, $component, $partial_placements ) {
|
||||
$this->assertInternalType( 'array', $response );
|
||||
$this->assertInstanceOf( 'WP_Customize_Selective_Refresh', $component );
|
||||
if ( isset( $this->expected_partial_ids ) ) {
|
||||
$this->assertEqualSets( $this->expected_partial_ids, array_keys( $partial_placements ) );
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected partial IDs.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $expected_partial_ids;
|
||||
|
||||
/**
|
||||
* Handle 'customize_render_partials_before' action.
|
||||
*
|
||||
* @param WP_Customize_Selective_Refresh $component Selective refresh component.
|
||||
* @param array $partial_placements Partial IDs.
|
||||
*/
|
||||
function handle_action_customize_render_partials_after( $component, $partial_placements ) {
|
||||
$this->assertInstanceOf( 'WP_Customize_Selective_Refresh', $component );
|
||||
if ( isset( $this->expected_partial_ids ) ) {
|
||||
$this->assertEqualSets( $this->expected_partial_ids, array_keys( $partial_placements ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'customize_render_partials_after' action.
|
||||
*
|
||||
* @param WP_Customize_Selective_Refresh $component Selective refresh component.
|
||||
* @param array $partial_placements Partial IDs.
|
||||
*/
|
||||
function handle_action_customize_render_partials_before( $component, $partial_placements ) {
|
||||
$this->assertInstanceOf( 'WP_Customize_Selective_Refresh', $component );
|
||||
if ( isset( $this->expected_partial_ids ) ) {
|
||||
$this->assertEqualSets( $this->expected_partial_ids, array_keys( $partial_placements ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::handle_render_partials_request()dynamic partials are recognized.
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
|
||||
*/
|
||||
function test_handle_render_partials_request_for_dynamic_partial() {
|
||||
$this->setup_valid_render_partials_request_environment();
|
||||
add_filter( 'customize_dynamic_partial_args', array( $this, 'filter_customize_dynamic_partial_args' ), 10, 2 );
|
||||
|
||||
$context_data = array();
|
||||
$placements = array( $context_data );
|
||||
|
||||
$_POST['partials'] = wp_slash( wp_json_encode( array(
|
||||
'test_dynamic_blogname' => $placements,
|
||||
) ) );
|
||||
|
||||
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
|
||||
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
|
||||
ob_start();
|
||||
try {
|
||||
$this->expected_partial_ids = array( 'test_dynamic_blogname' );
|
||||
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
|
||||
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
|
||||
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
$this->assertEquals( '', $e->getMessage() );
|
||||
}
|
||||
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
|
||||
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertEquals( array( get_bloginfo( 'name', 'display' ) ), $output['data']['contents']['test_dynamic_blogname'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::handle_render_partials_request() to multiple partials can be requested at once.
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::handle_render_partials_request()
|
||||
*/
|
||||
function test_handle_render_partials_request_for_multiple_partials_placements() {
|
||||
$this->setup_valid_render_partials_request_environment();
|
||||
|
||||
$this->wp_customize->selective_refresh->add_partial( 'test_blogname', array(
|
||||
'settings' => array( 'blogname' ),
|
||||
'render_callback' => array( $this, 'render_callback_blogname' ),
|
||||
) );
|
||||
$this->wp_customize->selective_refresh->add_partial( 'test_blogdescription', array(
|
||||
'settings' => array( 'blogdescription' ),
|
||||
'render_callback' => array( $this, 'render_callback_blogdescription' ),
|
||||
) );
|
||||
|
||||
$placement_context_data = array();
|
||||
|
||||
$_POST['partials'] = wp_slash( wp_json_encode( array(
|
||||
'test_blogname' => array( $placement_context_data ),
|
||||
'test_blogdescription' => array( $placement_context_data, $placement_context_data ),
|
||||
) ) );
|
||||
|
||||
$count_customize_render_partials_before = has_action( 'customize_render_partials_before' );
|
||||
$count_customize_render_partials_after = has_action( 'customize_render_partials_after' );
|
||||
ob_start();
|
||||
try {
|
||||
$this->expected_partial_ids = array( 'test_blogname', 'test_blogdescription' );
|
||||
add_filter( 'customize_render_partials_response', array( $this, 'filter_customize_render_partials_response' ), 10, 3 );
|
||||
add_action( 'customize_render_partials_before', array( $this, 'handle_action_customize_render_partials_before' ), 10, 2 );
|
||||
add_action( 'customize_render_partials_after', array( $this, 'handle_action_customize_render_partials_after' ), 10, 2 );
|
||||
$this->selective_refresh->handle_render_partials_request();
|
||||
} catch ( WPDieException $e ) {
|
||||
$this->assertEquals( '', $e->getMessage() );
|
||||
}
|
||||
$this->assertEquals( $count_customize_render_partials_before + 1, has_action( 'customize_render_partials_before' ) );
|
||||
$this->assertEquals( $count_customize_render_partials_after + 1, has_action( 'customize_render_partials_after' ) );
|
||||
$output = json_decode( ob_get_clean(), true );
|
||||
$this->assertEquals( array( get_bloginfo( 'name', 'display' ) ), $output['data']['contents']['test_blogname'] );
|
||||
$this->assertEquals( array_fill( 0, 2, get_bloginfo( 'description', 'display' ) ), $output['data']['contents']['test_blogdescription'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down.
|
||||
*/
|
||||
function tearDown() {
|
||||
$this->expected_partial_ids = null;
|
||||
$this->wp_customize = null;
|
||||
unset( $GLOBALS['wp_customize'] );
|
||||
unset( $GLOBALS['wp_scripts'] );
|
||||
parent::tearDown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
/**
|
||||
* WP_Customize_Selective_Refresh tests.
|
||||
*
|
||||
* @package WordPress
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for the WP_Customize_Selective_Refresh class.
|
||||
*
|
||||
* @group customize
|
||||
*/
|
||||
class Test_WP_Customize_Selective_Refresh extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Manager.
|
||||
*
|
||||
* @var WP_Customize_Manager
|
||||
*/
|
||||
public $wp_customize;
|
||||
|
||||
/**
|
||||
* Component.
|
||||
*
|
||||
* @var WP_Customize_Selective_Refresh
|
||||
*/
|
||||
public $selective_refresh;
|
||||
|
||||
/**
|
||||
* Set up the test fixture.
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
require_once( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
|
||||
// @codingStandardsIgnoreStart
|
||||
$GLOBALS['wp_customize'] = new WP_Customize_Manager();
|
||||
// @codingStandardsIgnoreEnd
|
||||
$this->wp_customize = $GLOBALS['wp_customize'];
|
||||
if ( isset( $this->wp_customize->selective_refresh ) ) {
|
||||
$this->selective_refresh = $this->wp_customize->selective_refresh;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::__construct().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::__construct()
|
||||
*/
|
||||
function test_construct() {
|
||||
$this->assertEquals( $this->selective_refresh, $this->wp_customize->selective_refresh );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::register_scripts().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::register_scripts()
|
||||
*/
|
||||
function test_register_scripts() {
|
||||
$scripts = new WP_Scripts();
|
||||
$handles = array(
|
||||
'customize-selective-refresh',
|
||||
'customize-preview-nav-menus',
|
||||
'customize-preview-widgets',
|
||||
);
|
||||
foreach ( $handles as $handle ) {
|
||||
$this->assertArrayHasKey( $handle, $scripts->registered );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::partials().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::partials()
|
||||
*/
|
||||
function test_partials() {
|
||||
$this->assertInternalType( 'array', $this->selective_refresh->partials() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CRUD methods for partials.
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::get_partial()
|
||||
* @see WP_Customize_Selective_Refresh::add_partial()
|
||||
* @see WP_Customize_Selective_Refresh::remove_partial()
|
||||
*/
|
||||
function test_crud_partial() {
|
||||
$partial = $this->selective_refresh->add_partial( 'foo' );
|
||||
$this->assertEquals( $this->selective_refresh, $partial->component );
|
||||
$this->assertInstanceOf( 'WP_Customize_Partial', $partial );
|
||||
$this->assertEquals( $partial, $this->selective_refresh->get_partial( $partial->id ) );
|
||||
$this->assertArrayHasKey( $partial->id, $this->selective_refresh->partials() );
|
||||
|
||||
$this->selective_refresh->remove_partial( $partial->id );
|
||||
$this->assertEmpty( $this->selective_refresh->get_partial( $partial->id ) );
|
||||
$this->assertArrayNotHasKey( $partial->id, $this->selective_refresh->partials() );
|
||||
|
||||
$partial = new WP_Customize_Partial( $this->selective_refresh, 'bar' );
|
||||
$this->assertEquals( $partial, $this->selective_refresh->add_partial( $partial ) );
|
||||
$this->assertEquals( $partial, $this->selective_refresh->get_partial( 'bar' ) );
|
||||
$this->assertEqualSets( array( 'bar' ), array_keys( $this->selective_refresh->partials() ) );
|
||||
|
||||
add_filter( 'customize_dynamic_partial_args', array( $this, 'filter_customize_dynamic_partial_args' ), 10, 2 );
|
||||
add_filter( 'customize_dynamic_partial_class', array( $this, 'filter_customize_dynamic_partial_class' ), 10, 3 );
|
||||
|
||||
$partial = $this->selective_refresh->add_partial( 'recognized-class' );
|
||||
$this->assertInstanceOf( 'Tested_Custom_Partial', $partial );
|
||||
$this->assertEquals( '.recognized', $partial->selector );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::init_preview().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::init_preview()
|
||||
*/
|
||||
function test_init_preview() {
|
||||
$this->selective_refresh->init_preview();
|
||||
$this->assertEquals( 10, has_action( 'template_redirect', array( $this->selective_refresh, 'handle_render_partials_request' ) ) );
|
||||
$this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $this->selective_refresh, 'enqueue_preview_scripts' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::enqueue_preview_scripts().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::enqueue_preview_scripts()
|
||||
*/
|
||||
function test_enqueue_preview_scripts() {
|
||||
$scripts = wp_scripts();
|
||||
$this->assertNotContains( 'customize-selective-refresh', $scripts->queue );
|
||||
$this->selective_refresh->enqueue_preview_scripts();
|
||||
$this->assertContains( 'customize-selective-refresh', $scripts->queue );
|
||||
$this->assertEquals( 1000, has_action( 'wp_footer', array( $this->selective_refresh, 'export_preview_data' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::export_preview_data().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::export_preview_data()
|
||||
*/
|
||||
function test_export_preview_data() {
|
||||
$this->selective_refresh->add_partial( 'blogname', array(
|
||||
'selector' => '#site-title',
|
||||
) );
|
||||
ob_start();
|
||||
$this->selective_refresh->export_preview_data();
|
||||
$html = ob_get_clean();
|
||||
$this->assertTrue( (bool) preg_match( '/_customizePartialRefreshExports = ({.+})/s', $html, $matches ) );
|
||||
$exported_data = json_decode( $matches[1], true );
|
||||
$this->assertInternalType( 'array', $exported_data );
|
||||
$this->assertArrayHasKey( 'partials', $exported_data );
|
||||
$this->assertInternalType( 'array', $exported_data['partials'] );
|
||||
$this->assertArrayHasKey( 'blogname', $exported_data['partials'] );
|
||||
$this->assertEquals( '#site-title', $exported_data['partials']['blogname']['selector'] );
|
||||
$this->assertArrayHasKey( 'renderQueryVar', $exported_data );
|
||||
$this->assertArrayHasKey( 'l10n', $exported_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::add_dynamic_partials().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::add_dynamic_partials()
|
||||
*/
|
||||
function test_add_dynamic_partials() {
|
||||
$partial_ids = array( 'recognized', 'recognized-class', 'unrecognized', 'already-added' );
|
||||
|
||||
$partials = $this->selective_refresh->add_dynamic_partials( $partial_ids );
|
||||
$this->assertEmpty( $partials );
|
||||
|
||||
$this->selective_refresh->add_partial( 'already-added' );
|
||||
|
||||
add_filter( 'customize_dynamic_partial_args', array( $this, 'filter_customize_dynamic_partial_args' ), 10, 2 );
|
||||
add_filter( 'customize_dynamic_partial_class', array( $this, 'filter_customize_dynamic_partial_class' ), 10, 3 );
|
||||
|
||||
$partials = $this->selective_refresh->add_dynamic_partials( $partial_ids );
|
||||
$this->assertEqualSets( array( 'recognized', 'recognized-class' ), wp_list_pluck( $partials, 'id' ) );
|
||||
|
||||
$this->assertInstanceOf( 'Tested_Custom_Partial', $this->selective_refresh->get_partial( 'recognized-class' ) );
|
||||
$this->assertNotInstanceOf( 'Tested_Custom_Partial', $this->selective_refresh->get_partial( 'recognized' ) );
|
||||
$this->assertEquals( '.recognized', $this->selective_refresh->get_partial( 'recognized' )->selector );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter customize_dynamic_partial_args.
|
||||
*
|
||||
* @see Test_WP_Customize_Selective_Refresh::test_add_dynamic_partials()
|
||||
*
|
||||
* @param false|array $partial_args The arguments to the WP_Customize_Partial constructor.
|
||||
* @param string $partial_id ID for dynamic partial.
|
||||
* @return false|array $args Dynamic partial args.
|
||||
*/
|
||||
function filter_customize_dynamic_partial_args( $partial_args, $partial_id ) {
|
||||
$this->assertTrue( false === $partial_args || is_array( $partial_args ) );
|
||||
$this->assertInternalType( 'string', $partial_id );
|
||||
|
||||
if ( preg_match( '/^recognized/', $partial_id ) ) {
|
||||
$partial_args = array(
|
||||
'selector' => '.recognized',
|
||||
);
|
||||
}
|
||||
|
||||
return $partial_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter customize_dynamic_partial_class.
|
||||
*
|
||||
* @see Test_WP_Customize_Selective_Refresh::test_add_dynamic_partials()
|
||||
*
|
||||
* @param string $partial_class WP_Customize_Partial or a subclass.
|
||||
* @param string $partial_id ID for dynamic partial.
|
||||
* @param array $partial_args The arguments to the WP_Customize_Partial constructor.
|
||||
* @return string
|
||||
*/
|
||||
function filter_customize_dynamic_partial_class( $partial_class, $partial_id, $partial_args ) {
|
||||
$this->assertInternalType( 'array', $partial_args );
|
||||
$this->assertInternalType( 'string', $partial_id );
|
||||
$this->assertInternalType( 'string', $partial_class );
|
||||
|
||||
if ( 'recognized-class' === $partial_id ) {
|
||||
$partial_class = 'Tested_Custom_Partial';
|
||||
}
|
||||
|
||||
return $partial_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Selective_Refresh::is_render_partials_request().
|
||||
*
|
||||
* @see WP_Customize_Selective_Refresh::is_render_partials_request()
|
||||
*/
|
||||
function test_is_render_partials_request() {
|
||||
$this->assertFalse( $this->selective_refresh->is_render_partials_request() );
|
||||
$_POST[ WP_Customize_Selective_Refresh::RENDER_QUERY_VAR ] = '1';
|
||||
$this->assertTrue( $this->selective_refresh->is_render_partials_request() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down.
|
||||
*/
|
||||
function tearDown() {
|
||||
$this->wp_customize = null;
|
||||
unset( $GLOBALS['wp_customize'] );
|
||||
unset( $GLOBALS['wp_scripts'] );
|
||||
parent::tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
require_once ABSPATH . WPINC . '/customize/class-wp-customize-partial.php';
|
||||
|
||||
/**
|
||||
* Class Tested_Custom_Partial
|
||||
*/
|
||||
class Tested_Custom_Partial extends WP_Customize_Partial {
|
||||
|
||||
/**
|
||||
* Type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'custom';
|
||||
}
|
||||
@@ -39,6 +39,7 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
|
||||
// @todo We should not be including a theme anyway
|
||||
remove_action( 'after_setup_theme', 'twentyfifteen_setup' );
|
||||
remove_action( 'after_setup_theme', 'twentysixteen_setup' );
|
||||
remove_action( 'customize_register', 'twentysixteen_customize_register', 11 );
|
||||
|
||||
$user_id = self::factory()->user->create( array( 'role' => 'administrator' ) );
|
||||
wp_set_current_user( $user_id );
|
||||
@@ -121,7 +122,7 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
|
||||
$default_args = array(
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'transport' => 'refresh',
|
||||
'transport' => 'postMessage',
|
||||
'default' => array(),
|
||||
'sanitize_callback' => array( $this->manager->widgets, 'sanitize_widget_instance' ),
|
||||
'sanitize_js_callback' => array( $this->manager->widgets, 'sanitize_widget_js_instance' ),
|
||||
@@ -150,7 +151,7 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
|
||||
$default_args = array(
|
||||
'type' => 'option',
|
||||
'capability' => 'edit_theme_options',
|
||||
'transport' => 'refresh',
|
||||
'transport' => 'postMessage',
|
||||
'default' => array(),
|
||||
'sanitize_callback' => array( $this->manager->widgets, 'sanitize_sidebar_widgets' ),
|
||||
'sanitize_js_callback' => array( $this->manager->widgets, 'sanitize_sidebar_widgets_js_instance' ),
|
||||
@@ -346,4 +347,146 @@ class Tests_WP_Customize_Widgets extends WP_UnitTestCase {
|
||||
$this->assertArrayHasKey( 'is_widget_customizer_js_value', $post_value );
|
||||
$this->assertEquals( $post_value, $this->manager->widgets->sanitize_widget_js_instance( $instance ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Widgets::customize_dynamic_partial_args().
|
||||
*
|
||||
* @see WP_Customize_Widgets::customize_dynamic_partial_args()
|
||||
*/
|
||||
function test_customize_dynamic_partial_args() {
|
||||
do_action( 'customize_register', $this->manager );
|
||||
|
||||
$args = apply_filters( 'customize_dynamic_partial_args', false, 'widget[search-2]' );
|
||||
$this->assertInternalType( 'array', $args );
|
||||
$this->assertEquals( 'widget', $args['type'] );
|
||||
$this->assertEquals( array( $this->manager->widgets, 'render_widget_partial' ), $args['render_callback'] );
|
||||
$this->assertTrue( $args['container_inclusive'] );
|
||||
|
||||
$args = apply_filters( 'customize_dynamic_partial_args', array( 'fallback_refresh' => false ), 'widget[search-2]' );
|
||||
$this->assertInternalType( 'array', $args );
|
||||
$this->assertEquals( 'widget', $args['type'] );
|
||||
$this->assertEquals( array( $this->manager->widgets, 'render_widget_partial' ), $args['render_callback'] );
|
||||
$this->assertTrue( $args['container_inclusive'] );
|
||||
$this->assertFalse( $args['fallback_refresh'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Widgets::selective_refresh_init().
|
||||
*
|
||||
* @see WP_Customize_Widgets::selective_refresh_init()
|
||||
*/
|
||||
function test_selective_refresh_init() {
|
||||
$this->manager->widgets->selective_refresh_init();
|
||||
$this->assertEquals( 10, has_action( 'wp_enqueue_scripts', array( $this->manager->widgets, 'customize_preview_enqueue_deps' ) ) );
|
||||
$this->assertEquals( 10, has_action( 'dynamic_sidebar_before', array( $this->manager->widgets, 'start_dynamic_sidebar' ) ) );
|
||||
$this->assertEquals( 10, has_action( 'dynamic_sidebar_after', array( $this->manager->widgets, 'end_dynamic_sidebar' ) ) );
|
||||
$this->assertEquals( 10, has_filter( 'dynamic_sidebar_params', array( $this->manager->widgets, 'filter_dynamic_sidebar_params' ) ) );
|
||||
$this->assertEquals( 10, has_filter( 'wp_kses_allowed_html', array( $this->manager->widgets, 'filter_wp_kses_allowed_data_attributes' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Widgets::customize_preview_enqueue_deps().
|
||||
*
|
||||
* @see WP_Customize_Widgets::customize_preview_enqueue_deps()
|
||||
*/
|
||||
function test_customize_preview_enqueue_deps() {
|
||||
$this->manager->widgets->customize_preview_enqueue_deps();
|
||||
$this->assertTrue( wp_script_is( 'customize-preview-widgets', 'enqueued' ) );
|
||||
$this->assertTrue( wp_style_is( 'customize-preview', 'enqueued' ) );
|
||||
$script = wp_scripts()->registered['customize-preview-widgets'];
|
||||
$this->assertContains( 'customize-selective-refresh', $script->deps );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test extensions to dynamic_sidebar().
|
||||
*
|
||||
* @see WP_Customize_Widgets::filter_dynamic_sidebar_params()
|
||||
* @see WP_Customize_Widgets::start_dynamic_sidebar()
|
||||
* @see WP_Customize_Widgets::end_dynamic_sidebar()
|
||||
*/
|
||||
function test_filter_dynamic_sidebar_params() {
|
||||
global $wp_registered_sidebars;
|
||||
register_sidebar( array(
|
||||
'id' => 'foo',
|
||||
) );
|
||||
|
||||
$this->manager->widgets->selective_refresh_init();
|
||||
|
||||
$params = array(
|
||||
array_merge(
|
||||
$wp_registered_sidebars['foo'],
|
||||
array(
|
||||
'widget_id' => 'search-2',
|
||||
)
|
||||
),
|
||||
array(),
|
||||
);
|
||||
$this->assertEquals( $params, $this->manager->widgets->filter_dynamic_sidebar_params( $params ), 'Expected short-circuit if not called after dynamic_sidebar_before.' );
|
||||
|
||||
ob_start();
|
||||
do_action( 'dynamic_sidebar_before', 'foo' );
|
||||
$output = ob_get_clean();
|
||||
$this->assertEquals( '<!--dynamic_sidebar_before:foo:1-->', trim( $output ) );
|
||||
|
||||
$bad_params = $params;
|
||||
unset( $bad_params[0]['id'] );
|
||||
$this->assertEquals( $bad_params, $this->manager->widgets->filter_dynamic_sidebar_params( $bad_params ) );
|
||||
|
||||
$bad_params = $params;
|
||||
$bad_params[0]['id'] = 'non-existing';
|
||||
$this->assertEquals( $bad_params, $this->manager->widgets->filter_dynamic_sidebar_params( $bad_params ) );
|
||||
|
||||
$bad_params = $params;
|
||||
$bad_params[0]['before_widget'] = ' <oops>';
|
||||
$this->assertEquals( $bad_params, $this->manager->widgets->filter_dynamic_sidebar_params( $bad_params ) );
|
||||
|
||||
$filtered_params = $this->manager->widgets->filter_dynamic_sidebar_params( $params );
|
||||
$this->assertNotEquals( $params, $filtered_params );
|
||||
ob_start();
|
||||
do_action( 'dynamic_sidebar_after', 'foo' );
|
||||
$output = ob_get_clean();
|
||||
$this->assertEquals( '<!--dynamic_sidebar_after:foo:1-->', trim( $output ) );
|
||||
|
||||
$output = wp_kses_post( $filtered_params[0]['before_widget'] );
|
||||
$this->assertContains( 'data-customize-partial-id="widget[search-2]"', $output );
|
||||
$this->assertContains( 'data-customize-partial-type="widget"', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Widgets::render_widget_partial() method.
|
||||
*
|
||||
* @see WP_Customize_Widgets::render_widget_partial()
|
||||
*/
|
||||
function test_render_widget_partial() {
|
||||
$this->manager->widgets->selective_refresh_init();
|
||||
|
||||
$partial_id = 'widget[search-2]';
|
||||
$partials = $this->manager->selective_refresh->add_dynamic_partials( array( $partial_id ) );
|
||||
$this->assertNotEmpty( $partials );
|
||||
$partial = array_shift( $partials );
|
||||
$this->assertEquals( $partial_id, $partial->id );
|
||||
|
||||
$this->assertFalse( $this->manager->widgets->render_widget_partial( $partial, array() ) );
|
||||
$this->assertFalse( $this->manager->widgets->render_widget_partial( $partial, array( 'sidebar_id' => 'non-existing' ) ) );
|
||||
|
||||
$output = $this->manager->widgets->render_widget_partial( $partial, array( 'sidebar_id' => 'sidebar-1' ) );
|
||||
|
||||
$this->assertEquals( 1, substr_count( $output, 'data-customize-partial-id' ) );
|
||||
$this->assertEquals( 1, substr_count( $output, 'data-customize-partial-type="widget"' ) );
|
||||
$this->assertContains( ' id="search-2"', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deprecated methods.
|
||||
*/
|
||||
public function test_deprecated_methods() {
|
||||
$this->setExpectedDeprecated( 'WP_Customize_Widgets::setup_widget_addition_previews' );
|
||||
$this->setExpectedDeprecated( 'WP_Customize_Widgets::prepreview_added_sidebars_widgets' );
|
||||
$this->setExpectedDeprecated( 'WP_Customize_Widgets::prepreview_added_widget_instance' );
|
||||
$this->setExpectedDeprecated( 'WP_Customize_Widgets::remove_prepreview_filters' );
|
||||
$this->manager->widgets->setup_widget_addition_previews();
|
||||
$this->manager->widgets->prepreview_added_sidebars_widgets();
|
||||
$this->manager->widgets->prepreview_added_widget_instance();
|
||||
$this->manager->widgets->remove_prepreview_filters();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user