This repository was archived by the owner on May 28, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwp-appcache.php
More file actions
233 lines (196 loc) · 7.48 KB
/
wp-appcache.php
File metadata and controls
233 lines (196 loc) · 7.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
<?php
/**
* Plugin Name: WP Appcache
* Plugin URI: http://haveposts.com
* Description: Allows your site to leverage the awesomeness of the HTML 5 Application Cache.
* Version: 0.1.3
* Author: Jack Lenox
* Author URI: http://haveposts.com
* License: GPL2
*/
/**
* Plugin activation
*
* Sets a site option with the current timestamp
*
* @since 0.1.1
*/
register_activation_hook( __FILE__, 'wp_appcache_update_timestamp' );
/**
* Add the reference to the manifest file to the <html> tag by way of language_attributes
*
* @since 0.1.1
*/
if ( ! is_admin() ) {
add_filter( 'init', 'wp_appcache_add_manifest' );
function wp_appcache_add_manifest() {
if ( ! is_user_logged_in() && ! in_array( $GLOBALS['pagenow'], array( 'wp-login.php', 'wp-register.php' ) ) ) {
add_filter( 'language_attributes', 'wp_appcache_add_manifest_to_language_attributes' );
// Set the timestamp as a session variable
$session = session_id();
if ( empty( $session ) ) session_start();
$_SESSION['wp_appcache_manifest_timestamp'] = get_option( '_wp_appcache_manifest_timestamp' );
function wp_appcache_add_manifest_to_language_attributes( $output ) {
return $output . ' manifest="' . plugins_url( 'manifest.php', __FILE__ ) . '"';
}
}
}
}
/**
* Hook onto all relevant actions to update the manifest timestamp
*
* The idea here is that anything that might change the appearance of a website will update
* the manifest.
*
* @since 0.1.1
*/
// Attachments
add_action( 'add_attachment', 'wp_appcache_update_timestamp' );
add_action( 'edit_attachment', 'wp_appcache_update_timestamp' );
add_action( 'delete_attachment', 'wp_appcache_update_timestamp' );
// Comments
add_action( 'commment_post', 'wp_appcache_update_timestamp' );
add_action( 'edit_comment', 'wp_appcache_update_timestamp' );
add_action( 'deleted_comment', 'wp_appcache_update_timestamp' );
// Options
add_action( 'added_option', 'wp_appcache_update_timestamp' );
add_action( 'deleted_option', 'wp_appcache_update_timestamp' );
// Plugins
add_action( 'activated_plugin', 'wp_appcache_update_timestamp' );
add_action( 'deactivated_plugin', 'wp_appcache_update_timestamp' );
// Posts and pages
add_action( 'save_post', 'wp_appcache_update_timestamp' );
add_action( 'deleted_post', 'wp_appcache_update_timestamp' );
add_action( 'trashed_post', 'wp_appcache_update_timestamp' );
// Themes
add_action( 'after_switch_theme', 'wp_appcache_update_timestamp' );
// Login/Logout
add_action( 'wp_login', 'wp_appcache_update_timestamp' );
add_action( 'wp_logout', 'wp_appcache_update_timestamp' );
function wp_appcache_update_timestamp() {
update_option( '_wp_appcache_manifest_timestamp', current_time( 'mysql' ) );
}
/**
* Load the WP Appcache JS
*
* @since 0.1.1
*/
add_action( 'wp_enqueue_scripts', 'wp_appcache_enqueue_javascript' );
function wp_appcache_enqueue_javascript() {
wp_enqueue_script(
'wp-appcache',
plugins_url( '/js/wp-appcache.js', __FILE__ ),
array( 'jquery', 'heartbeat' )
);
}
/**
* Load in wp_footer() the site's most recent timestamp
*
* @since 0.1.1
*/
add_action( 'wp_footer', 'wp_appcache_footer_timestamp' );
function wp_appcache_footer_timestamp() {
echo '<div id="wp-appcache-timestamp" style="display: none">' . get_option( '_wp_appcache_manifest_timestamp' ) . '</div>';
}
/**
* Speed up the heartbeat!
*
* @since 0.1.1
*/
add_filter( 'heartbeat_settings', 'wp_appcache_heartbeat_settings' );
function wp_appcache_heartbeat_settings( $settings ) {
$settings['interval'] = 15;
return $settings;
}
/**
* Load in wp_head() the JS that handles certain AppCache sync issues
*
* So, this is what might appear like a messy chunk of JS and CSS. It is injected into the head
* mainly in the interests of it running quickly (hence no jQuery here).
*
* What this does is check if the user is already engaged in a current session with the website.
* If not, it runs a JS XMLHttpRequest almost as soon as the page starts to load to see if the
* website in question has been updated
*
* @since 0.1.1
*/
add_action( 'wp_head', 'wp_appcache_javascript_and_css' );
function wp_appcache_javascript_and_css() {
$wp_appcache_js = "<script type='text/javascript'>
var request, currentSession, siteUpdated, returningUser;
// Has the user ever been here before?
returningUser = window.localStorage.getItem( 'wp_appcache_returning_user' );
// Some local storage items that help us deduce what the user's browser has cached
siteUpdated = window.localStorage.getItem( 'wp_appcache_timestamp' );
currentSession = window.sessionStorage.getItem( 'wp_appcache_session' );
// If the user has never been here before, we set the meta so that things load normally
if ( returningUser !== 'true' ) {
window.sessionStorage.setItem( 'wp_appcache_session', true );
window.sessionStorage.setItem( 'wp_appcache_page_visible', true );
window.localStorage.setItem( 'wp_appcache_returning_user', true );
// Otherwise they've been here before but it's a new session, things get interesting
} else if ( currentSession !== 'true' ) {
// DOMParser function for browser compatibility
( function ( DOMParser) {
'use strict';
var DOMParser_proto = DOMParser.prototype, real_parseFromString = DOMParser_proto.parseFromString;
// Firefox/Opera/IE throw errors on unsupported types
try {
// WebKit returns null on unsupported types
if ((new DOMParser).parseFromString('', 'text/html')) {
// text/html parsing is natively supported
return;
}
} catch (ex) {}
DOMParser_proto.parseFromString = function(markup, type) {
if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
var doc = document.implementation.createHTMLDocument(''), doc_elt = doc.documentElement, first_elt;
doc_elt.innerHTML = markup;
first_elt = doc_elt.firstElementChild;
if (doc_elt.childElementCount === 1 && first_elt.localName.toLowerCase() === 'html') {
doc.replaceChild(first_elt, doc_elt);
}
return doc;
} else {
return real_parseFromString.apply(this, arguments);
}
};
}( DOMParser ) );
request = new XMLHttpRequest();
request.onreadystatechange = function() {
if ( request.readyState == 4 ) {
if ( request.status == 200 ) {
var parser = new DOMParser();
var responseDoc = parser.parseFromString( request.responseText, 'text/html' );
responseDocDate = responseDoc.getElementById('wp-appcache-timestamp');
if ( siteUpdated < responseDocDate ) {
// It's different, therefore repaint the page with the latest data
document.open('text/html');
document.write(request.responseText);
document.close();
document.getElementsByTagName('body')[0].style.visibility = 'visible';
window.localStorage.setItem( 'wp_appcache_timestamp', responseDocDate );
} else {
// It's the same, just show it
document.getElementsByTagName('body')[0].style.visibility = 'visible';
}
} else if ( request.status == 400 ) {
document.getElementsByTagName('body')[0].style.visibility = 'visible';
} else {
document.getElementsByTagName('body')[0].style.visibility = 'visible';
}
// Update the local storage meta
window.sessionStorage.setItem( 'wp_appcache_session', true );
window.sessionStorage.setItem( 'wp_appcache_page_visible', true );
window.localStorage.setItem( 'wp_appcache_returning_user', true );
}
}
var timeInMs = Date.now();
request.open('GET', '" . $_SERVER['REQUEST_URI'] . "?' + timeInMs, true);
request.send();
}
</script>";
echo $wp_appcache_js;
$wp_appcache_css = '<style>body { visibility: hidden; }</style>';
echo $wp_appcache_css;
}