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

Commit 244debe

Browse files
committed
Resolves conflicts in \CustomizeSnapshots\Customize_Snapshot_Manager::enqueue_controls_scripts()
2 parents e98c6f1 + b53f954 commit 244debe

14 files changed

+1453
-165
lines changed

css/customize-snapshots-preview.css

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
form[method="post"] button[type="submit"],
2+
form[method="post"] button[type=""],
3+
form[method="post"] input[type="submit"] {
4+
cursor: not-allowed;
5+
}
6+
form[method="post"] button:not([type]) {
7+
cursor: not-allowed;
8+
}

customize-snapshots.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
* Admin notice for incompatible versions of PHP.
4545
*/
4646
function customize_snapshots_php_version_error() {
47-
printf( '<div class="error"><p>%s</p></div>', customize_snapshots_php_version_text() );
47+
printf( '<div class="error"><p>%s</p></div>', customize_snapshots_php_version_text() ); // WPCS: XSS OK.
4848
}
4949

5050
/**

instance.php

+28
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,31 @@ function get_plugin_instance() {
2323
global $customize_snapshots_plugin;
2424
return $customize_snapshots_plugin;
2525
}
26+
27+
/**
28+
* Convenience function for whether settings are being previewed.
29+
*
30+
* @see Customize_Snapshot_Manager::is_previewing_settings()
31+
* @see Customize_Snapshot_Manager::preview_snapshot_settings()
32+
*
33+
* @return bool Whether previewing settings.
34+
*/
35+
function is_previewing_settings() {
36+
return get_plugin_instance()->customize_snapshot_manager->is_previewing_settings();
37+
}
38+
39+
/**
40+
* Convenience function to get the current snapshot UUID.
41+
*
42+
* @see Customize_Snapshot_Manager::$current_snapshot_uuid
43+
*
44+
* @return string|null The current snapshot UUID or null if no snapshot.
45+
*/
46+
function current_snapshot_uuid() {
47+
$customize_snapshot_uuid = get_plugin_instance()->customize_snapshot_manager->current_snapshot_uuid;
48+
if ( empty( $customize_snapshot_uuid ) ) {
49+
return null;
50+
} else {
51+
return $customize_snapshot_uuid;
52+
}
53+
}

js/customize-snapshots-frontend.js

+335
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
/* global jQuery, confirm */
2+
/* exported CustomizeSnapshotsFrontend */
3+
/* eslint consistent-this: [ "error", "section" ], no-magic-numbers: [ "error", { "ignore": [-1,0,1] } ] */
4+
/* eslint-disable no-alert */
5+
6+
/*
7+
* The code here is derived from the initial Transactions pull request: https://github.com/xwp/wordpress-develop/pull/61
8+
* See https://github.com/xwp/wordpress-develop/blob/97fd5019c488a0713d34b517bdbff67c62c48a5d/src/wp-includes/js/customize-preview.js#L98-L111
9+
*/
10+
11+
var CustomizeSnapshotsFrontend = ( function( $ ) {
12+
'use strict';
13+
14+
var component = {
15+
data: {
16+
uuid: '',
17+
home_url: {
18+
scheme: '',
19+
host: '',
20+
path: ''
21+
},
22+
l10n: {
23+
restoreSessionPrompt: ''
24+
}
25+
}
26+
};
27+
28+
/**
29+
* Init.
30+
*
31+
* @param {object} args Args.
32+
* @param {string} args.uuid UUID.
33+
* @returns {void}
34+
*/
35+
component.init = function init( args ) {
36+
_.extend( component.data, args );
37+
38+
component.hasSessionStorage = 'undefined' !== typeof sessionStorage;
39+
40+
component.keepSessionAlive();
41+
component.rememberSessionSnapshot();
42+
component.injectSnapshotIntoLinks();
43+
component.handleExitSnapshotSessionLink();
44+
component.injectSnapshotIntoAjaxRequests();
45+
component.injectSnapshotIntoForms();
46+
};
47+
48+
/**
49+
* Prompt to restore session.
50+
*
51+
* @returns {void}
52+
*/
53+
component.keepSessionAlive = function keepSessionAlive() {
54+
var currentSnapshotUuid, urlParser, adminBarItem;
55+
if ( ! component.hasSessionStorage ) {
56+
return;
57+
}
58+
currentSnapshotUuid = sessionStorage.getItem( 'customize_snapshot_uuid' );
59+
if ( ! currentSnapshotUuid || component.data.uuid ) {
60+
return;
61+
}
62+
63+
urlParser = document.createElement( 'a' );
64+
urlParser.href = location.href;
65+
if ( urlParser.search.length > 1 ) {
66+
urlParser.search += '&';
67+
}
68+
urlParser.search += 'customize_snapshot_uuid=' + encodeURIComponent( sessionStorage.getItem( 'customize_snapshot_uuid' ) );
69+
70+
$( function() {
71+
adminBarItem = $( '#wp-admin-bar-resume-customize-snapshot' );
72+
if ( adminBarItem.length ) {
73+
adminBarItem.find( '> a' ).prop( 'href', urlParser.href );
74+
adminBarItem.show();
75+
} else if ( confirm( component.data.l10n.restoreSessionPrompt ) ) {
76+
location.replace( urlParser.href );
77+
} else {
78+
sessionStorage.removeItem( 'customize_snapshot_uuid' );
79+
}
80+
} );
81+
};
82+
83+
/**
84+
* Remember the session's snapshot.
85+
*
86+
* Persist the snapshot UUID in session storage so that we can prompt to restore the snapshot query param if inadvertently dropped.
87+
*
88+
* @returns {void}
89+
*/
90+
component.rememberSessionSnapshot = function rememberSessionSnapshot() {
91+
if ( ! component.hasSessionStorage || ! component.data.uuid ) {
92+
return;
93+
}
94+
sessionStorage.setItem( 'customize_snapshot_uuid', component.data.uuid );
95+
};
96+
97+
/**
98+
* Inject the snapshot UUID into links in the document.
99+
*
100+
* @returns {void}
101+
*/
102+
component.injectSnapshotIntoLinks = function injectSnapshotIntoLinks() {
103+
var linkSelectors = 'a, area';
104+
105+
if ( ! component.data.uuid ) {
106+
return;
107+
}
108+
$( function() {
109+
110+
// Inject links into initial document.
111+
$( document.body ).find( linkSelectors ).each( function() {
112+
component.injectSnapshotLinkParam( this );
113+
} );
114+
115+
// Inject links for new elements added to the page
116+
if ( 'undefined' !== typeof MutationObserver ) {
117+
component.mutationObserver = new MutationObserver( function( mutations ) {
118+
_.each( mutations, function( mutation ) {
119+
$( mutation.target ).find( linkSelectors ).each( function() {
120+
component.injectSnapshotLinkParam( this );
121+
} );
122+
} );
123+
} );
124+
component.mutationObserver.observe( document.documentElement, {
125+
childList: true,
126+
subtree: true
127+
} );
128+
} else {
129+
130+
// If mutation observers aren't available, fallback to just-in-time injection.
131+
$( document.documentElement ).on( 'click focus mouseover', linkSelectors, function() {
132+
component.injectSnapshotLinkParam( this );
133+
} );
134+
}
135+
} );
136+
};
137+
138+
/**
139+
* Is matching base URL (host and path)?
140+
*
141+
* @param {HTMLAnchorElement} parsedUrl Parsed URL.
142+
* @param {string} parsedUrl.hostname Host.
143+
* @param {string} parsedUrl.pathname Path.
144+
* @returns {boolean} Whether matched.
145+
*/
146+
component.isMatchingBaseUrl = function isMatchingBaseUrl( parsedUrl ) {
147+
return parsedUrl.hostname === component.data.home_url.host && 0 === parsedUrl.pathname.indexOf( component.data.home_url.path );
148+
};
149+
150+
/**
151+
* Should the supplied link have a snapshot UUID added (or does it have one already)?
152+
*
153+
* @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
154+
* @param {string} element.search Query string.
155+
* @param {string} element.pathname Path.
156+
* @param {string} element.hostname Hostname.
157+
* @returns {boolean} Is appropriate for snapshot link.
158+
*/
159+
component.shouldLinkHaveSnapshotParam = function shouldLinkHaveSnapshotParam( element ) {
160+
if ( ! component.isMatchingBaseUrl( element ) ) {
161+
return false;
162+
}
163+
164+
// Skip wp login and signup pages.
165+
if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) ) {
166+
return false;
167+
}
168+
169+
// Allow links to admin ajax as faux frontend URLs.
170+
if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) ) {
171+
return true;
172+
}
173+
174+
// Disallow links to admin.
175+
if ( /\/wp-admin(\/|$)/.test( element.pathname ) ) {
176+
return false;
177+
}
178+
179+
// Skip links in admin bar.
180+
if ( $( element ).closest( '#wpadminbar' ).length ) {
181+
return false;
182+
}
183+
184+
return true;
185+
};
186+
187+
/**
188+
* Return whether the supplied link element has the snapshot query param.
189+
*
190+
* @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
191+
* @param {object} element.search Query string.
192+
* @returns {boolean} Whether query param is present.
193+
*/
194+
component.doesLinkHaveSnapshotQueryParam = function( element ) {
195+
return /(^|&)customize_snapshot_uuid=/.test( element.search.substr( 1 ) );
196+
};
197+
198+
/**
199+
* Inject the customize_snapshot_uuid query param into links on the frontend.
200+
*
201+
* @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
202+
* @param {object} element.search Query string.
203+
* @returns {void}
204+
*/
205+
component.injectSnapshotLinkParam = function injectSnapshotLinkParam( element ) {
206+
if ( component.doesLinkHaveSnapshotQueryParam( element ) || ! component.shouldLinkHaveSnapshotParam( element ) ) {
207+
return;
208+
}
209+
210+
if ( element.search.length > 1 ) {
211+
element.search += '&';
212+
}
213+
element.search += 'customize_snapshot_uuid=' + encodeURIComponent( component.data.uuid );
214+
};
215+
216+
/**
217+
* Handle electing to exit from the snapshot session.
218+
*
219+
* @returns {void}
220+
*/
221+
component.handleExitSnapshotSessionLink = function handleExitSnapshotSessionLink() {
222+
$( function() {
223+
if ( ! component.hasSessionStorage ) {
224+
return;
225+
}
226+
$( '#wpadminbar' ).on( 'click', '#wp-admin-bar-exit-customize-snapshot', function() {
227+
sessionStorage.removeItem( 'customize_snapshot_uuid' );
228+
} );
229+
} );
230+
};
231+
232+
/**
233+
* Inject the snapshot UUID into Ajax requests.
234+
*
235+
* @return {void}
236+
*/
237+
component.injectSnapshotIntoAjaxRequests = function injectSnapshotIntoAjaxRequests() {
238+
$.ajaxPrefilter( component.prefilterAjax );
239+
};
240+
241+
/**
242+
* Rewrite Ajax requests to inject Customizer state.
243+
*
244+
* @param {object} options Options.
245+
* @param {string} options.type Type.
246+
* @param {string} options.url URL.
247+
* @returns {void}
248+
*/
249+
component.prefilterAjax = function prefilterAjax( options ) {
250+
var urlParser;
251+
if ( ! component.data.uuid ) {
252+
return;
253+
}
254+
255+
urlParser = document.createElement( 'a' );
256+
urlParser.href = options.url;
257+
258+
// Abort if the request is not for this site.
259+
if ( ! component.isMatchingBaseUrl( urlParser ) ) {
260+
return;
261+
}
262+
263+
// Skip if snapshot UUID already in URL.
264+
if ( -1 !== urlParser.search.indexOf( 'customize_snapshot_uuid=' + component.data.uuid ) ) {
265+
return;
266+
}
267+
268+
if ( urlParser.search.substr( 1 ).length > 0 ) {
269+
urlParser.search += '&';
270+
}
271+
urlParser.search += 'customize_snapshot_uuid=' + component.data.uuid;
272+
273+
options.url = urlParser.href;
274+
};
275+
276+
/**
277+
* Inject snapshot into forms, allowing preview to persist through submissions.
278+
*
279+
* @returns {void}
280+
*/
281+
component.injectSnapshotIntoForms = function injectSnapshotIntoForms() {
282+
if ( ! component.data.uuid ) {
283+
return;
284+
}
285+
$( function() {
286+
287+
// Inject inputs for forms in initial document.
288+
$( document.body ).find( 'form' ).each( function() {
289+
component.injectSnapshotFormInput( this );
290+
} );
291+
292+
// Inject inputs for new forms added to the page.
293+
if ( 'undefined' !== typeof MutationObserver ) {
294+
component.mutationObserver = new MutationObserver( function( mutations ) {
295+
_.each( mutations, function( mutation ) {
296+
$( mutation.target ).find( 'form' ).each( function() {
297+
component.injectSnapshotFormInput( this );
298+
} );
299+
} );
300+
} );
301+
component.mutationObserver.observe( document.documentElement, {
302+
childList: true,
303+
subtree: true
304+
} );
305+
}
306+
} );
307+
};
308+
309+
/**
310+
* Inject snapshot into form inputs.
311+
*
312+
* @param {HTMLFormElement} form Form.
313+
* @returns {void}
314+
*/
315+
component.injectSnapshotFormInput = function injectSnapshotFormInput( form ) {
316+
var urlParser;
317+
if ( $( form ).find( 'input[name=customize_snapshot_uuid]' ).length > 0 ) {
318+
return;
319+
}
320+
urlParser = document.createElement( 'a' );
321+
urlParser.href = form.action;
322+
if ( ! component.isMatchingBaseUrl( urlParser ) ) {
323+
return;
324+
}
325+
326+
$( form ).prepend( $( '<input>', {
327+
type: 'hidden',
328+
name: 'customize_snapshot_uuid',
329+
value: component.data.uuid
330+
} ) );
331+
};
332+
333+
return component;
334+
} )( jQuery );
335+

0 commit comments

Comments
 (0)