Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit 5900671

Browse files
authored
Merge pull request #84 from xwp/feature/allow-deleting-settings
Issue #17 : Enable deleting settings in snapshot wp-admin/post page.
2 parents 2005189 + 88a83de commit 5900671

7 files changed

+223
-1
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ node_js:
1212
- stable
1313

1414
env:
15-
- WP_VERSION=trunk WP_MULTISITE=0
15+
- WP_VERSION=latest WP_MULTISITE=0
1616
- WP_VERSION=latest WP_MULTISITE=1
1717

1818
install:

css/customize-snapshots-admin.css

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
details.snapshot-setting-removed summary {
2+
text-decoration: line-through;
3+
}
4+
details:not(.snapshot-setting-removed) .snapshot-toggle-setting-removal {
5+
color: #a00
6+
}
7+
details:not(.snapshot-setting-removed) .snapshot-toggle-setting-removal:hover {
8+
color: #f00
9+
}
10+
details .snapshot-toggle-setting-removal {
11+
float: right;
12+
}

js/customize-snapshots-admin.js

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
( function( $ ) {
2+
'use strict';
3+
4+
$( function() {
5+
var component, $linkToRemoveOrRestore, linkActions, dataSlug, inputName;
6+
7+
component = {};
8+
$linkToRemoveOrRestore = $( '.snapshot-toggle-setting-removal' );
9+
linkActions = [ 'remove', 'restore' ];
10+
dataSlug = 'cs-action';
11+
inputName = 'customize_snapshot_remove_settings[]';
12+
13+
component.initializeLink = function() {
14+
$linkToRemoveOrRestore.data( dataSlug, linkActions[ 0 ] );
15+
};
16+
17+
component.initializeLink();
18+
19+
component.isLinkSetToRemoveSetting = function( $link ) {
20+
return linkActions[ 0 ] === component.getClickedLinkAction( $link );
21+
};
22+
23+
component.isLinkSetToRestoreSetting = function( $link ) {
24+
return linkActions[ 1 ] === component.getClickedLinkAction( $link );
25+
};
26+
27+
component.getClickedLinkAction = function( $link ) {
28+
return $link.data( dataSlug );
29+
};
30+
31+
component.hideSettingAndChangeLinkText = function( $link ) {
32+
var $settingDisplay, settingId;
33+
$settingDisplay = component.getSettingDisplay( $link );
34+
settingId = component.getSettingId( $link );
35+
36+
$link.data( dataSlug, linkActions[ 1 ] )
37+
.after( component.constructHiddenInputWithValue( settingId ) );
38+
component.changeLinkText( $link );
39+
$settingDisplay.removeAttr( 'open' )
40+
.addClass( 'snapshot-setting-removed' );
41+
};
42+
43+
component.getSettingDisplay = function( $link ) {
44+
return $link.parents( 'details' );
45+
};
46+
47+
component.getSettingId = function( $link ) {
48+
return $link.attr( 'id' );
49+
};
50+
51+
component.constructHiddenInputWithValue = function( settingId ) {
52+
return $( '<input>' ).attr( {
53+
'name': inputName,
54+
'type': 'hidden'
55+
} )
56+
.val( settingId );
57+
};
58+
59+
component.changeLinkText = function( $link ) {
60+
var oldLinkText, newLinkText;
61+
oldLinkText = $link.text();
62+
newLinkText = $link.data( 'text-restore' );
63+
64+
$link.data( 'text-restore', oldLinkText )
65+
.text( newLinkText );
66+
};
67+
68+
component.showSettingAndChangeLinkText = function( $link ) {
69+
var $settingDisplay, settingId;
70+
$settingDisplay = component.getSettingDisplay( $link );
71+
settingId = component.getSettingId( $link );
72+
73+
$link.data( dataSlug, linkActions[ 0 ] );
74+
component.changeLinkText( $link );
75+
component.removeHiddenInputWithValue( settingId );
76+
$settingDisplay.removeClass( 'snapshot-setting-removed' );
77+
};
78+
79+
component.removeHiddenInputWithValue = function( settingId ) {
80+
$( 'input[name="' + inputName + '"][value="' + settingId + '"]' ).remove();
81+
};
82+
83+
$linkToRemoveOrRestore.on( 'click', function( event ) {
84+
var $clickedLink = $( this );
85+
86+
event.preventDefault();
87+
88+
if ( component.isLinkSetToRemoveSetting( $clickedLink ) ) {
89+
component.hideSettingAndChangeLinkText( $clickedLink );
90+
} else if ( component.isLinkSetToRestoreSetting( $clickedLink ) ) {
91+
component.showSettingAndChangeLinkText( $clickedLink );
92+
}
93+
} );
94+
95+
} );
96+
} )( jQuery );

php/class-customize-snapshot-manager.php

+18
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ function init() {
102102
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_controls_scripts' ) );
103103
add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
104104
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
105+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
105106

106107
add_action( 'customize_controls_init', array( $this, 'add_snapshot_uuid_to_return_url' ) );
107108
add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_templates' ) );
@@ -746,6 +747,23 @@ public function enqueue_frontend_scripts() {
746747
);
747748
}
748749

750+
/**
751+
* Enqueue admin scripts.
752+
*
753+
* These files control the behavior and styling of links to remove settings.
754+
* Published snapshots can't be edited, so these files are not needed on those pages.
755+
*
756+
* @param String $hook Current page in admin.
757+
*/
758+
public function enqueue_admin_scripts( $hook ) {
759+
global $post;
760+
$handle = 'customize-snapshots-admin';
761+
if ( ( 'post.php' === $hook ) && isset( $post->post_type ) && ( Post_Type::SLUG === $post->post_type ) && ( 'publish' !== $post->post_status ) ) {
762+
wp_enqueue_script( $handle );
763+
wp_enqueue_style( $handle );
764+
}
765+
}
766+
749767
/**
750768
* Include the snapshot nonce in the Customizer nonces.
751769
*

php/class-plugin.php

+9
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public function register_scripts( \WP_Scripts $wp_scripts ) {
8383
$src = $this->dir_url . 'js/customize-snapshots-frontend' . $min . '.js';
8484
$deps = array( 'jquery', 'underscore' );
8585
$wp_scripts->add( $handle, $src, $deps );
86+
87+
$handle = 'customize-snapshots-admin';
88+
$src = $this->dir_url . 'js/customize-snapshots-admin' . $min . '.js';
89+
$deps = array( 'jquery' );
90+
$wp_scripts->add( $handle, $src, $deps );
8691
}
8792

8893
/**
@@ -105,5 +110,9 @@ public function register_styles( \WP_Styles $wp_styles ) {
105110
$src = $this->dir_url . 'css/customize-snapshots-preview' . $min . '.css';
106111
$deps = array( 'customize-preview' );
107112
$wp_styles->add( $handle, $src, $deps );
113+
114+
$handle = 'customize-snapshots-admin';
115+
$src = $this->dir_url . 'css/customize-snapshots-admin' . $min . '.css';
116+
$wp_styles->add( $handle, $src );
108117
}
109118
}

php/class-post-type.php

+54
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ public function register() {
114114
add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 );
115115
add_action( 'admin_notices', array( $this, 'show_publish_error_admin_notice' ) );
116116
add_action( 'post_submitbox_minor_actions', array( $this, 'hide_disabled_publishing_actions' ) );
117+
add_filter( 'content_save_pre', array( $this, 'filter_out_settings_if_removed_in_metabox' ), 10 );
117118
add_action( 'admin_print_scripts-revision.php', array( $this, 'disable_revision_ui_for_published_posts' ) );
118119

119120
// Version check for bulk action.
@@ -361,6 +362,7 @@ public function render_data_metabox( $post ) {
361362
echo '<hr>';
362363

363364
ksort( $snapshot_content );
365+
wp_nonce_field( static::SLUG . '_settings', static::SLUG );
364366
echo '<ul id="snapshot-settings">';
365367
foreach ( $snapshot_content as $setting_id => $setting_params ) {
366368
if ( ! isset( $setting_params['value'] ) && ! isset( $setting_params['publish_error'] ) ) {
@@ -370,6 +372,7 @@ public function render_data_metabox( $post ) {
370372
echo '<li>';
371373
echo '<details open>';
372374
echo '<summary><code>' . esc_html( $setting_id ) . '</code> ';
375+
echo '<a href="#" id="' . esc_attr( $setting_id ) . '" data-text-restore="' . esc_attr__( 'Restore setting', 'customize-snapshots' ) . '" class="snapshot-toggle-setting-removal remove">' . esc_html__( 'Remove setting', 'customize-snapshots' ) . '</a>';
373376

374377
// Show error message when there was a publishing error.
375378
if ( isset( $setting_params['publish_error'] ) ) {
@@ -822,4 +825,55 @@ public function admin_show_merge_error() {
822825
}
823826
printf( '<div class="notice notice-error is-dismissible"><p>%s</p></div>', esc_html( $error[ $error_code ] ) );
824827
}
828+
829+
/**
830+
* Filter settings out of post content, if they were removed in the meta box.
831+
*
832+
* In each snapshot's edit page, there are JavaScript-controlled links to remove each setting.
833+
* On clicking a setting, the JS sets a hidden input field with that setting's ID.
834+
* And these settings appear in $_REQUEST as the array 'customize_snapshot_remove_settings.'
835+
* So look for these removed settings in that array, on saving.
836+
* And possibly filter out those settings from the post content.
837+
*
838+
* @param String $content Post content to filter.
839+
* @return String $content Post content, possibly filtered.
840+
*/
841+
public function filter_out_settings_if_removed_in_metabox( $content ) {
842+
global $post;
843+
$key_for_settings = static::SLUG . '_remove_settings';
844+
$post_type_object = get_post_type_object( static::SLUG );
845+
846+
$should_filter_content = (
847+
isset( $post->post_status )
848+
&&
849+
( 'publish' !== $post->post_status )
850+
&&
851+
current_user_can( $post_type_object->cap->edit_post, $post->ID )
852+
&&
853+
( static::SLUG === $post->post_type )
854+
&&
855+
! empty( $_REQUEST[ $key_for_settings ] )
856+
&&
857+
is_array( $_REQUEST[ $key_for_settings ] )
858+
&&
859+
isset( $_REQUEST[ static::SLUG ] )
860+
&&
861+
wp_verify_nonce( $_REQUEST[ static::SLUG ], static::SLUG . '_settings' )
862+
&&
863+
! ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
864+
);
865+
866+
if ( ! $should_filter_content ) {
867+
return $content;
868+
}
869+
870+
$setting_ids_to_unset = $_REQUEST[ $key_for_settings ];
871+
$data = json_decode( wp_unslash( $content ), true );
872+
foreach ( $setting_ids_to_unset as $setting_id ) {
873+
unset( $data[ $setting_id ] );
874+
}
875+
$content = Customize_Snapshot_Manager::encode_json( $data );
876+
877+
return $content;
878+
}
825879
}

tests/php/test-class-post-type.php

+33
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public function test_register() {
5858
$this->assertEquals( 10, has_action( 'transition_post_status', array( $post_type->snapshot_manager, 'save_settings_with_publish_snapshot' ) ) );
5959
$this->assertEquals( 10, has_filter( 'wp_insert_post_data', array( $post_type->snapshot_manager, 'prepare_snapshot_post_content_for_publish' ) ) );
6060
$this->assertEquals( 10, has_action( 'display_post_states', array( $post_type, 'display_post_states' ) ) );
61+
$this->assertEquals( 10, has_filter( 'content_save_pre', array( $post_type, 'filter_out_settings_if_removed_in_metabox' ) ) );
6162

6263
if ( version_compare( get_bloginfo( 'version' ), '4.7', '>=' ) ) {
6364
$this->assertEquals( 10, has_filter( 'bulk_actions-edit-' . Post_Type::SLUG, array( $post_type, 'add_snapshot_bulk_actions' ) ) );
@@ -886,4 +887,36 @@ public function test_admin_show_merge_error() {
886887
$notice_content = ob_get_clean();
887888
$this->assertEmpty( $notice_content );
888889
}
890+
891+
/**
892+
* Test filter_out_settings_if_removed_in_metabox.
893+
*
894+
* @covers CustomizeSnapshots\Post_Type::filter_out_settings_if_removed_in_metabox()
895+
*/
896+
public function test_filter_out_settings_if_removed_in_metabox() {
897+
global $post;
898+
$post_type_obj = new Post_Type( $this->plugin->customize_snapshot_manager );
899+
$post_type_obj->register();
900+
wp_set_current_user( $admin_user_id = $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
901+
$post_id = $post_type_obj->save( array(
902+
'uuid' => self::UUID,
903+
'data' => array(
904+
'foo' => array(
905+
'value' => 'foo_value',
906+
),
907+
'bar' => array(
908+
'value' => 'bar_value',
909+
),
910+
),
911+
'status' => 'draft',
912+
) );
913+
$post = get_post( $post_id ); // WPCS: override ok.
914+
$nonce_key = Post_Type::SLUG;
915+
$key_for_settings = Post_Type::SLUG . '_remove_settings';
916+
$_REQUEST[ $nonce_key ] = $_POST[ $nonce_key ] = wp_create_nonce( Post_Type::SLUG . '_settings' );
917+
$_REQUEST[ $key_for_settings ] = $_POST[ $key_for_settings ] = array( 'foo' );
918+
$content = $post_type_obj->filter_out_settings_if_removed_in_metabox( $post->post_content );
919+
$data = json_decode( $content, true );
920+
$this->assertArrayNotHasKey( 'foo', $data );
921+
}
889922
}

0 commit comments

Comments
 (0)