Skip to content
Newer
Older
100644 896 lines (749 sloc) 29.1 KB
8ff4206 @mjangda v1
mjangda authored
1 <?php
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
2
8ff4206 @mjangda v1
mjangda authored
3 /**
4 * Plugin Name: Liveblog
1fc681a @nb Add metadata URLs
nb authored
5 * Plugin URI: http://wordpress.org/extend/plugins/liveblog/
8ff4206 @mjangda v1
mjangda authored
6 * Description: Blogging: at the speed of live.
1f2170f @nb Bump 1.3
nb authored
7 * Version: 1.3
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
8 * Author: WordPress.com VIP, Automattic
1fc681a @nb Add metadata URLs
nb authored
9 * Author URI: http://vip.wordpress.com/
10 * Text Domain: liveblog
8ff4206 @mjangda v1
mjangda authored
11 */
12
13 if ( ! class_exists( 'WPCOM_Liveblog' ) ) :
14
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
15 /**
16 * The main Liveblog class used to setup everything this plugin needs.
17 *
18 * Liveblog currently uses a custom comment-type to circumvent post cache
19 * issues frequently experienced by other live-blog implimentations. It comes
20 * with a simple and effective templating mechanism, complete with all of the
21 * CSS, JS, and AJAX needed to make this a turn-key installation.
22 *
23 * This class is a big container for a bunch of static methods, similar to a
24 * factory but without object inheritance or instantiation.
8413aff @johnjamesjacoby Uploading:
johnjamesjacoby authored
25 *
5ad84ba @nb Fix typo
nb authored
26 * Things yet to be implemented:
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
27 *
28 * -- Change "Read More" to "View Liveblog"
29 * -- Manual refresh button
30 * -- Allow marking of liveblog as ended
31 * -- Allow comment modifications; need to store modified date as comment_meta
32 */
33 final class WPCOM_Liveblog {
34
35 /** Constants *************************************************************/
8ff4206 @mjangda v1
mjangda authored
36
1f2170f @nb Bump 1.3
nb authored
37 const version = '1.3';
1d5d7f9 @nb Flush the rewrite rules on rules update
nb authored
38 const rewrites_version = 1;
a823f5d @nb Show an admin notice if WP is older than 3.5
nb authored
39 const min_wp_version = '3.5';
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
40 const key = 'liveblog';
41 const url_endpoint = 'liveblog';
42 const edit_cap = 'publish_posts';
43 const nonce_key = 'liveblog_nonce';
8ff4206 @mjangda v1
mjangda authored
44
1d7244f @mjangda Increase the default refresh interval
mjangda authored
45 const refresh_interval = 10; // how often should we refresh
7af87b5 @nb Use shorter refresh interval when debugging
nb authored
46 const debug_refresh_interval = 2; // how often we refresh in development mode
ed1991c @nb Shut the auto-update only on consecutive failures
nb authored
47 const max_consecutive_retries = 100; // max number of failed tries before polling is disabled
ef3a225 @nb Use human time diff instead of absolute timestamps
nb authored
48 const human_time_diff_update_interval = 60; // how often we change the entry human timestamps: "a minute ago"
ed1991c @nb Shut the auto-update only on consecutive failures
nb authored
49 const delay_threshold = 5; // how many failed tries after which we should increase the refresh interval
50 const delay_multiplier = 2; // by how much should we inscrease the refresh interval
fdef301 @nb Switch to adding new entries unobtrusively
nb authored
51 const fade_out_duration = 5; // how much time should take fading out the background of new entries
8ff4206 @mjangda v1
mjangda authored
52
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
53 /** Variables *************************************************************/
54
55 private static $post_id = null;
56 private static $entry_query = null;
57 private static $do_not_cache_response = false;
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
58
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
59 /** Load Methods **********************************************************/
60
61 /**
62 * @uses add_action() to hook methods into WordPress actions
63 * @uses add_filter() to hook methods into WordPress filters
64 */
65 public static function load() {
e5351e5 @mjangda load_plugin_textdomain so the plugin can be translated.
mjangda authored
66 load_plugin_textdomain( 'liveblog', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
67
a823f5d @nb Show an admin notice if WP is older than 3.5
nb authored
68 if ( self::is_wp_too_old() ) {
69 self::add_old_wp_notice();
70 return;
71 }
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
72 self::includes();
73 self::add_actions();
74 self::add_filters();
75 self::add_admin_actions();
186ea96 @nb Add an image URL handler
nb authored
76 self::register_embed_handlers();
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
77 }
78
a823f5d @nb Show an admin notice if WP is older than 3.5
nb authored
79 private static function add_old_wp_notice() {
80 add_action( 'admin_notices', array( 'WPCOM_Liveblog', 'show_old_wp_notice' ) );
81 }
82
83 public static function show_old_wp_notice() {
84 global $wp_version;
85 $min_version = self::min_wp_version;
86 echo self::get_template_part( 'old-wp-notice.php', compact( 'wp_version', 'min_version' ) );
87 }
88
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
89 /**
90 * Include the necessary files
91 */
92 private static function includes() {
93 require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry.php' );
94 require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry-query.php' );
e691fe3 @johnjamesjacoby Include ms.php theme-side for its filesize and available space functi…
johnjamesjacoby authored
95
96 // Manually include ms.php theme-side in multisite environments because
97 // we need its filesize and available space functions.
98 if ( ! is_admin() && is_multisite() ) {
8f5fb3c @johnjamesjacoby Remove preceding slash. ABSPATH is already slashed for us.
johnjamesjacoby authored
99 require_once( ABSPATH . 'wp-admin/includes/ms.php' );
e691fe3 @johnjamesjacoby Include ms.php theme-side for its filesize and available space functi…
johnjamesjacoby authored
100 }
02b5fdb @nb Add convertor from extend read me to github readme
nb authored
101
102 if ( defined( 'WP_CLI' ) && WP_CLI ) {
103 require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-wp-cli.php' );
104 }
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
105 }
8ff4206 @mjangda v1
mjangda authored
106
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
107 /**
108 * Hook actions in that run on every page-load
109 *
110 * @uses add_action()
111 */
112 private static function add_actions() {
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
113 add_action( 'init', array( __CLASS__, 'init' ) );
7994c3e @nb Re-add the rewrite rules on permalink change
nb authored
114 add_action( 'init', array( __CLASS__, 'add_rewrite_rules' ) );
115 add_action( 'permalink_structure_changed', array( __CLASS__, 'add_rewrite_rules' ) );
4221823 @nb Flush the rewrite rules later
nb authored
116 // flush the rewrite rules a lot later so that we don't interfere with other plugins using rewrite rules
117 add_action( 'init', array( __CLASS__, 'flush_rewrite_rules' ), 1000 );
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
118 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
ea5a8a6 @nb Introduce archiving
nb authored
119 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) );
120 add_action( 'wp_ajax_set_liveblog_state_for_post', array( __CLASS__, 'admin_ajax_set_liveblog_state_for_post' ) );
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
121 }
8ff4206 @mjangda v1
mjangda authored
122
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
123 /**
124 * Hook filters in that run on every page-load
125 *
126 * @uses add_filter()
127 */
128 private static function add_filters() {
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
129 add_filter( 'template_redirect', array( __CLASS__, 'handle_request' ) );
c3dc8bd @mjangda Only apply liveblog-entry CSS class to liveblog comment types.
mjangda authored
130 add_filter( 'comment_class', array( __CLASS__, 'add_comment_class' ), 10, 3 );
8ff4206 @mjangda v1
mjangda authored
131 }
132
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
133 /**
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
134 * Hook actions in that run on every admin page-load
135 *
136 * @uses add_action()
137 * @uses is_admin()
138 */
139 private static function add_admin_actions() {
140
141 // Bail if not in admin area
142 if ( ! is_admin() )
143 return;
144
145 add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_box' ) );
146 }
147
186ea96 @nb Add an image URL handler
nb authored
148 private static function register_embed_handlers() {
149 // register it to run later, because the regex is pretty general and we don't want it to prevent more specific handlers from running
150 wp_embed_register_handler( 'liveblog_image', '/\.(png|jpe?g|gif)(\?.*)?$/', array( 'WPCOM_Liveblog', 'image_embed_handler' ), 99 );
151 }
152
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
153 /** Public Methods ********************************************************/
154
155 /**
156 * Liveblog initialization functions.
157 *
158 * This is where Liveblog sets up any additional things it needs to run
159 * inside of WordPress. Where some plugins would register post types or
160 * taxonomies, we modify endpoints and add post type support for Liveblog.
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
161 */
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
162 public static function init() {
163 /**
164 * Add liveblog support to the 'post' post type. This is done here so
165 * we can possibly introduce this to other post types later.
166 */
8ff4206 @mjangda v1
mjangda authored
167 add_post_type_support( 'post', self::key );
8314495 @nb Add an action after liveblog's init
nb authored
168 do_action( 'after_liveblog_init' );
8ff4206 @mjangda v1
mjangda authored
169 }
170
7994c3e @nb Re-add the rewrite rules on permalink change
nb authored
171 public function add_rewrite_rules() {
1d5d7f9 @nb Flush the rewrite rules on rules update
nb authored
172 add_rewrite_endpoint( self::url_endpoint, EP_PERMALINK );
7994c3e @nb Re-add the rewrite rules on permalink change
nb authored
173 }
1d5d7f9 @nb Flush the rewrite rules on rules update
nb authored
174
7994c3e @nb Re-add the rewrite rules on permalink change
nb authored
175 public static function flush_rewrite_rules() {
1d5d7f9 @nb Flush the rewrite rules on rules update
nb authored
176 if ( get_option( 'liveblog_rewrites_version' ) != self::rewrites_version ) {
177 flush_rewrite_rules();
178 update_option( 'liveblog_rewrites_version', self::rewrites_version );
179 }
180 }
181
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
182 /**
183 * This is where a majority of the magic happens.
184 *
185 * Hooked to template_redirect, this method tries to add anything it can to
186 * the current post output. If nothing needs to be added, we redirect back
187 * to the permalink.
188 *
189 * @return If request has been handled
190 */
191 public static function handle_request() {
192
8ff4206 @mjangda v1
mjangda authored
193 if ( ! self::is_viewing_liveblog_post() )
194 return;
195
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
196 self::$post_id = get_the_ID();
b28b38d @nb Rename the query class to match WP conventions
nb authored
197 self::$entry_query = new WPCOM_Liveblog_Entry_Query( self::$post_id, self::key );
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
198
167d167 @nb Add entries after the shortcodes had been run
nb authored
199 if ( self::is_initial_page_request() ) {
200 // we need to add the liveblog after the shortcodes are run, because we already
201 // process shortcodes in the comment contents and if we left any (like in the original content)
202 // we wouldn't like them to be processed
203 add_filter( 'the_content', array( __CLASS__, 'add_liveblog_to_content' ), 20 );
204 } else {
4872b2a @nb Use front-end AJAX URLs for same-origin requests
nb authored
205 self::handle_ajax_request();
167d167 @nb Add entries after the shortcodes had been run
nb authored
206 }
4872b2a @nb Use front-end AJAX URLs for same-origin requests
nb authored
207 }
208
209 private static function handle_ajax_request() {
210
211 $endpoint_suffix = get_query_var( self::url_endpoint );
212
213 if ( !$endpoint_suffix ) {
214 // we redirect, because if somebody accessed <permalink>/liveblog
215 // they probably did that in the URL bar, not via AJAX
216 wp_safe_redirect( get_permalink() );
217 exit();
8ff4206 @mjangda v1
mjangda authored
218 }
2b0244c @nb Remove trailing whitespace
nb authored
219 wp_cache_delete( self::key . '_entries_asc_' . self::$post_id, 'liveblog' );
8ff4206 @mjangda v1
mjangda authored
220
4872b2a @nb Use front-end AJAX URLs for same-origin requests
nb authored
221 $suffix_to_method = array(
222 '\d+/\d+' => 'ajax_entries_between',
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
223 'crud' => 'ajax_crud_entry',
4872b2a @nb Use front-end AJAX URLs for same-origin requests
nb authored
224 'preview' => 'ajax_preview_entry',
225 );
226
227 $response_method = 'ajax_unknown';
228
229 foreach( $suffix_to_method as $suffix_re => $method ) {
230 if ( preg_match( "%^$suffix_re/?%", $endpoint_suffix ) ) {
231 $response_method = $method;
232 break;
233 }
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
234 }
235
4872b2a @nb Use front-end AJAX URLs for same-origin requests
nb authored
236 self::$response_method();
237
8ff4206 @mjangda v1
mjangda authored
238 }
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
239
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
240 /**
241 * Look for any new Liveblog entries, and return them via JSON
242 */
243 public static function ajax_entries_between() {
244
245 // Set some defaults
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
246 $latest_timestamp = 0;
247 $entries_for_json = array();
558008c @nb Use the same current timestamp at all places
nb authored
248
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
249 // Look for entry boundaries
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
250 list( $start_timestamp, $end_timestamp ) = self::get_timestamps_from_query();
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
251
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
252 // Bail if there is no end timestamp
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
253 if ( empty( $end_timestamp ) ) {
70b347a @mjangda Add missing textdomain to translated strings
mjangda authored
254 self::send_user_error( __( 'A timestamp is missing. Correct URL: <permalink>/liveblog/<from>/</to>/', 'liveblog' ) );
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
255 }
256
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
257 // Do not cache if it's too soon
bd6c841 @nb Use the Date header to get server-side date
nb authored
258 if ( $end_timestamp > time() )
6c66757 @nb Do not let the client cache future requests
nb authored
259 self::$do_not_cache_response = true;
260
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
261 // Get liveblog entries within the start and end boundaries
b28b38d @nb Rename the query class to match WP conventions
nb authored
262 $entries = self::$entry_query->get_between_timestamps( $start_timestamp, $end_timestamp );
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
263 if ( empty( $entries ) ) {
7e39692 @mjangda Introduce some new hooks.
mjangda authored
264 do_action( 'liveblog_entry_request_empty' );
265
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
266 self::json_return( array(
267 'entries' => array(),
268 'latest_timestamp' => null
269 ) );
270 }
d79a82d @nb Gather common entry functionality in a new class
nb authored
271
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
272 /**
273 * Loop through each liveblog entry, set the most recent timestamp, and
274 * put the JSON data for each entry into a neat little array.
275 */
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
276 foreach( $entries as $entry ) {
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
277 $latest_timestamp = max( $latest_timestamp, $entry->get_timestamp() );
d79a82d @nb Gather common entry functionality in a new class
nb authored
278 $entries_for_json[] = $entry->for_json();
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
279 }
280
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
281 // Setup our data to return via JSON
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
282 $result_for_json = array(
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
283 'entries' => $entries_for_json,
284 'latest_timestamp' => $latest_timestamp,
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
285 );
286
7e39692 @mjangda Introduce some new hooks.
mjangda authored
287 do_action( 'liveblog_entry_request', $result_for_json );
288
e977561 @nb Get rid of extra json_return() arguments
nb authored
289 self::json_return( $result_for_json );
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
290 }
291
508b444 @cfg Expose is_liveblog_post and get_liveblog_state methods - they're usef…
cfg authored
292 /**
293 * Is a given post_id a liveblog enabled post?
294 *
295 * @global WP_Post $post
296 * @param int $post_id
297 * @return bool
298 */
299 public static function is_liveblog_post( $post_id = null ) {
300 $state = self::get_liveblog_state( $post_id );
301 return (bool)$state;
302 }
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
303
304 /**
305 * Are we viewing a liveblog post?
306 *
307 * @uses is_single()
308 * @uses is_liveblog_post()
309 * @return bool
310 */
508b444 @cfg Expose is_liveblog_post and get_liveblog_state methods - they're usef…
cfg authored
311 public static function is_viewing_liveblog_post() {
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
312 return (bool) ( is_single() && self::is_liveblog_post() );
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
313 }
314
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
315 /**
508b444 @cfg Expose is_liveblog_post and get_liveblog_state methods - they're usef…
cfg authored
316 * One of: 'enable', 'archive', false.
317 */
318 public static function get_liveblog_state( $post_id = null ) {
319 if ( empty( $post_id ) ) {
320 global $post;
321 $post_id = $post->ID;
322 }
323 $state = get_post_meta( $post_id, self::key, true );
324 // backwards compatibility with older values
325 if ( 1 == $state ) {
326 $state = 'enable';
327 }
328 return $state;
329 }
330
331 /** Private _is_ Methods **************************************************/
332
333 /**
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
334 * Is this the initial page request?
335 *
336 * Note that we do not use get_query_var() - it returns '' for all requests,
337 * which is valid for /post-name/liveblog/
338 *
339 * @global WP_Query $wp_query
340 * @return bool
341 */
342 private static function is_initial_page_request() {
8ff4206 @mjangda v1
mjangda authored
343 global $wp_query;
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
344
345 return (bool) ! isset( $wp_query->query_vars[self::key] );
8ff4206 @mjangda v1
mjangda authored
346 }
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
347
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
348 /**
349 * Is this an ajax request for the entries?
350 *
351 * @uses get_query_var() to check for the url_endpoint
352 * @return bool
353 */
354 private static function is_entries_ajax_request() {
355 return (bool) get_query_var( self::url_endpoint );
356 }
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
357
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
358 /**
359 * Get timestamps from the current WP_Query
360 *
361 * Ensures that two timestamps exist, and returns a properly formatted empty
362 * array if not.
363 *
364 * @return array
365 */
366 private static function get_timestamps_from_query() {
367
368 // Look for timestamps and bail if none
25be635 @mjangda Support for non-pretty permalinks
mjangda authored
369 $stamps = rtrim( get_query_var( self::url_endpoint ), '/' );
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
370 if ( empty( $stamps ) )
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
371 return array( false, false );
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
372
373 // Get timestamps from the query variable
374 $timestamps = explode( '/', $stamps );
375
376 // Bail if there are not 2 timestamps
377 if ( 2 !== count( $timestamps ) )
378 return array( false, false );
379
380 // Return integer timestamps in an array
381 return array_map( 'intval', $timestamps );
1b8e8d5 @nb Streamline logic for getting recent entries
nb authored
382 }
383
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
384 public static function ajax_crud_entry() {
b58c3a0 @nb Remove leading underscores from function names
nb authored
385 self::ajax_current_user_can_edit_liveblog();
386 self::ajax_check_nonce();
8ff4206 @mjangda v1
mjangda authored
387
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
388 $args = array();
8ff4206 @mjangda v1
mjangda authored
389
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
390 $crud_action = isset( $_POST['crud_action'] ) ? $_POST['crud_action'] : 0;
8ff4206 @mjangda v1
mjangda authored
391
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
392 if ( !in_array( $crud_action, array( 'insert', 'update', 'delete' ) ) ) {
393 self::send_user_error( sprintf( __( 'Invalid entry crud_action: %s', 'liveblog' ), $crud_action ) );
a2723d4 @nb Commit entry modifications
nb authored
394 }
395
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
396 $args['post_id'] = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
397 $args['content'] = isset( $_POST['content'] ) ? $_POST['content'] : '';
398 $args['entry_id'] = isset( $_POST['entry_id'] ) ? intval( $_POST['entry_id'] ) : 0;
e92599e @nb Switch the delete endpoint to use the new method
nb authored
399
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
400 $args['user'] = wp_get_current_user();
e92599e @nb Switch the delete endpoint to use the new method
nb authored
401
4c7e77b @nb Consolidate all CRUD AJAX actions
nb authored
402 $entry = call_user_func( array( 'WPCOM_Liveblog_Entry', $crud_action ), $args );
e92599e @nb Switch the delete endpoint to use the new method
nb authored
403
404 if ( is_wp_error( $entry ) ) {
405 self::send_server_error( $entry->get_error_message() );
406 }
407
408 // Do not send latest_timestamp. If we send it the client won't get
409 // older entries. Since we send only the new one, we don't know if there
410 // weren't any entries in between.
411 self::json_return( array(
412 'entries' => array( $entry->for_json() ),
413 'latest_timestamp' => null
414 ) );
415 }
416
5aee585 @nb Add ajax endpoint for preview
nb authored
417 function ajax_preview_entry() {
418 $entry_content = isset( $_REQUEST['entry_content'] ) ? $_REQUEST['entry_content'] : '';
5460519 @mjangda Fix preview which was returning slashed data.
mjangda authored
419 $entry_content = stripslashes( wp_filter_post_kses( $entry_content ) );
5aee585 @nb Add ajax endpoint for preview
nb authored
420 $entry_content = WPCOM_Liveblog_Entry::render_content( $entry_content );
7e39692 @mjangda Introduce some new hooks.
mjangda authored
421
422 do_action( 'liveblog_preview_entry', $entry_content );
423
5aee585 @nb Add ajax endpoint for preview
nb authored
424 self::json_return( array( 'html' => $entry_content ) );
425 }
426
4872b2a @nb Use front-end AJAX URLs for same-origin requests
nb authored
427 public function ajax_unknown() {
428 self::send_user_error( __( 'Unknown liveblog action', 'liveblog' ) );
429 }
430
431
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
432 /** Comment Methods *******************************************************/
8ff4206 @mjangda v1
mjangda authored
433
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
434 /**
435 * Add a liveblog class to each comment, so they can be styled
436 *
437 * @param array $classes
438 * @return string
439 */
c3dc8bd @mjangda Only apply liveblog-entry CSS class to liveblog comment types.
mjangda authored
440 public static function add_comment_class( $classes, $class, $comment_id ) {
441 if ( self::key == get_comment_type( $comment_id ) )
442 $classes[] = 'liveblog-entry';
8ff4206 @mjangda v1
mjangda authored
443 return $classes;
444 }
445
ea5a8a6 @nb Introduce archiving
nb authored
446 public static function admin_enqueue_scripts() {
447 wp_enqueue_style( self::key, plugins_url( 'css/liveblog-admin.css', __FILE__ ) );
281438d @nb Use actual information for AJAX action
nb authored
448 wp_enqueue_script( 'liveblog-admin', plugins_url( 'js/liveblog-admin.js', __FILE__ ) );
449 wp_localize_script( 'liveblog-admin', 'liveblog_admin_settings', array(
450 'nonce_key' => self::nonce_key,
451 'nonce' => wp_create_nonce( self::nonce_key ),
f4e54ce @nb Translate JS error messages
nb authored
452 'error_message_template' => __( 'Error {error-code}: {error-message}', 'liveblog' ),
9bc391a @nb Show error callback status for non-HTTP errors
nb authored
453 'short_error_message_template' => __( 'Error: {error-message}', 'liveblog' ),
281438d @nb Use actual information for AJAX action
nb authored
454 ) );
ea5a8a6 @nb Introduce archiving
nb authored
455 }
f157181 @johnjamesjacoby Comment Status:
johnjamesjacoby authored
456
457 /**
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
458 * Enqueue the necessary CSS and JS that liveblog needs to function.
459 *
460 * @return If not a liveblog post
461 */
462 public static function enqueue_scripts() {
463
8ff4206 @mjangda v1
mjangda authored
464 if ( ! self::is_viewing_liveblog_post() )
465 return;
466
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
467 wp_enqueue_style( self::key, plugins_url( 'css/liveblog.css', __FILE__ ) );
fdef301 @nb Switch to adding new entries unobtrusively
nb authored
468 wp_register_script( 'jquery-throttle', plugins_url( 'js/jquery.ba-throttle-debounce.min.js', __FILE__ ) );
ef3a225 @nb Use human time diff instead of absolute timestamps
nb authored
469 wp_register_script( 'moment', plugins_url( 'js/moment.min.js', __FILE__ ), array(), '1.7.2' );
470 wp_localize_script( 'moment', 'momentLang', array(
471 'locale' => get_locale(),
472 'relativeTime' => array(
473 'past' => __( '%s ago' ),
474 's' => __( 'a few seconds', 'liveblog' ),
475 'm' => __( 'a minute', 'liveblog' ),
476 'mm' => __( '%d minutes', 'liveblog' ),
477 'h' => __( 'an hour', 'liveblog' ),
478 'hh' => __( '%d hours', 'liveblog' ),
479 'd' => __( 'a day', 'liveblog' ),
480 'dd' => __( '%d days', 'liveblog' ),
481 'M' => __( 'a month', 'liveblog' ),
482 'MM' => __( '%d months', 'liveblog' ),
483 'y' => __( 'a year', 'liveblog' ),
484 'yy' => __( '%d years', 'liveblog' ),
485 ),
486 ));
487
488 wp_enqueue_script( self::key, plugins_url( 'js/liveblog.js', __FILE__ ), array( 'jquery', 'jquery-color', 'backbone', 'jquery-throttle', 'moment' ), self::version, true );
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
489
5781e55 @nb Don't load the publishing interface if archived
nb authored
490 if ( self::is_liveblog_editable() ) {
e3fb7f2 @nb Switch the jQuery mess in publisher to Backbone
nb authored
491 wp_enqueue_script( 'liveblog-publisher', plugins_url( 'js/liveblog-publisher.js', __FILE__ ), array( self::key ), self::version, true );
212e64d @zbtirrell Hookable Uploader
zbtirrell authored
492 wp_enqueue_script( 'liveblog-plupload', plugins_url( 'js/plupload.js', __FILE__ ), array( self::key, 'wp-plupload', 'jquery' ) );
c65e58f @nb Make the function name a verb
nb authored
493 self::add_default_plupload_settings();
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
494 }
8ff4206 @mjangda v1
mjangda authored
495
c0c3085 @nb Add spinner for inserting an entry
nb authored
496 if ( wp_script_is( 'jquery.spin', 'registered' ) ) {
497 wp_enqueue_script( 'jquery.spin' );
498 } else {
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
499 wp_enqueue_script( 'spin', plugins_url( 'js/spin.js', __FILE__ ), false, '1.2.4' );
500 wp_enqueue_script( 'jquery.spin', plugins_url( 'js/jquery.spin.js', __FILE__ ), array( 'jquery', 'spin' ) );
c0c3085 @nb Add spinner for inserting an entry
nb authored
501 }
502
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
503 wp_localize_script( self::key, 'liveblog_settings',
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
504 apply_filters( 'liveblog_settings', array(
505 'permalink' => get_permalink(),
506 'post_id' => get_the_ID(),
ea5a8a6 @nb Introduce archiving
nb authored
507 'state' => self::get_liveblog_state(),
8ff4206 @mjangda v1
mjangda authored
508
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
509 'key' => self::key,
510 'nonce_key' => self::nonce_key,
e3fb7f2 @nb Switch the jQuery mess in publisher to Backbone
nb authored
511 'nonce' => wp_create_nonce( self::nonce_key ),
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
512 'latest_entry_timestamp' => self::$entry_query->get_latest_timestamp(),
8ff4206 @mjangda v1
mjangda authored
513
7af87b5 @nb Use shorter refresh interval when debugging
nb authored
514 'refresh_interval' => WP_DEBUG? self::debug_refresh_interval : self::refresh_interval,
ed1991c @nb Shut the auto-update only on consecutive failures
nb authored
515 'max_consecutive_retries'=> self::max_consecutive_retries,
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
516 'delay_threshold' => self::delay_threshold,
517 'delay_multiplier' => self::delay_multiplier,
fdef301 @nb Switch to adding new entries unobtrusively
nb authored
518 'fade_out_duration' => self::fade_out_duration,
8ff4206 @mjangda v1
mjangda authored
519
ea5a8a6 @nb Introduce archiving
nb authored
520 'endpoint_url' => self::get_entries_endpoint_url(),
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
521
522 // i18n
28802ff @nb Delete entry functionality
nb authored
523 'delete_confirmation' => __( 'Do you really want do delete this entry? There is no way back.', 'liveblog' ),
f4e54ce @nb Translate JS error messages
nb authored
524 'error_message_template' => __( 'Error {error-code}: {error-message}', 'liveblog' ),
9bc391a @nb Show error callback status for non-HTTP errors
nb authored
525 'short_error_message_template' => __( 'Error: {error-message}', 'liveblog' ),
ab7d20d @nb Publisher i18n
nb authored
526 'new_update' => __( 'Liveblog: {number} new update' , 'liveblog'),
527 'new_updates' => __( 'Liveblog: {number} new updates' , 'liveblog'),
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
528 ) )
529 );
ab7d20d @nb Publisher i18n
nb authored
530 wp_localize_script( 'liveblog-publisher', 'liveblog_publisher_settings', array(
531 'loading_preview' => __( 'Loading preview…', 'liveblog' ),
532 'new_entry_tab_label' => __( 'New Entry', 'liveblog' ),
533 'new_entry_submit_label' => __( 'Publish Update', 'liveblog' ),
534 'edit_entry_tab_label' => __( 'Edit Entry', 'liveblog' ),
535 'edit_entry_submit_label' => __( 'Update', 'liveblog' ),
536 ) );
8ff4206 @mjangda v1
mjangda authored
537 }
538
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
539 /**
8413aff @johnjamesjacoby Uploading:
johnjamesjacoby authored
540 * Sets up some default Plupload settings so we can upload meda theme-side
541 *
542 * @global type $wp_scripts
543 */
c65e58f @nb Make the function name a verb
nb authored
544 private static function add_default_plupload_settings() {
8413aff @johnjamesjacoby Uploading:
johnjamesjacoby authored
545 global $wp_scripts;
546
547 $defaults = array(
548 'runtimes' => 'html5,silverlight,flash,html4',
549 'file_data_name' => 'async-upload',
550 'multiple_queues' => true,
551 'max_file_size' => self::max_upload_size() . 'b',
552 'url' => admin_url( 'admin-ajax.php', 'relative' ),
553 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
554 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
70b347a @mjangda Add missing textdomain to translated strings
mjangda authored
555 'filters' => array( array( 'title' => __( 'Allowed Files', 'liveblog' ), 'extensions' => '*') ),
8413aff @johnjamesjacoby Uploading:
johnjamesjacoby authored
556 'multipart' => true,
557 'urlstream_upload' => true,
558 'multipart_params' => array(
559 'action' => 'upload-attachment',
560 '_wpnonce' => wp_create_nonce( 'media-form' )
561 )
562 );
563
564 $settings = array(
565 'defaults' => $defaults,
566 'browser' => array(
567 'mobile' => wp_is_mobile(),
568 'supported' => _device_can_upload(),
569 )
570 );
571
572 $script = 'var _wpPluploadSettings = ' . json_encode( $settings ) . ';';
573 $data = $wp_scripts->get_data( 'wp-plupload', 'data' );
574
575 if ( ! empty( $data ) )
576 $script = "$data\n$script";
577
578 $wp_scripts->add_data( 'wp-plupload', 'data', $script );
579 }
580
581 /**
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
582 * Get the URL of a specific liveblog entry.
583 *
584 * @return string
585 */
586 private static function get_entries_endpoint_url() {
0dccc81 @nb Add correct endpoing to draft URLs with query args
nb authored
587 $post_permalink = get_permalink( self::$post_id );
588 if ( false !== strpos( $post_permalink, '?p=' ) )
589 $url = add_query_arg( self::url_endpoint, '', $post_permalink ) . '='; // returns something like ?p=1&liveblog=
25be635 @mjangda Support for non-pretty permalinks
mjangda authored
590 else
0dccc81 @nb Add correct endpoing to draft URLs with query args
nb authored
591 $url = trailingslashit( trailingslashit( $post_permalink ) . self::url_endpoint ); // returns something like /2012/01/01/post/liveblog/
7330fcb @nb Allow the endpoint URL to be filtered
nb authored
592 $url = apply_filters( 'liveblog_endpoint_url', $url, self::$post_id );
25be635 @mjangda Support for non-pretty permalinks
mjangda authored
593 return $url;
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
594 }
cb778e4 @mjangda Load initial entries server-side rather than via AJAX for SEO benefit
mjangda authored
595
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
596 /** Display Methods *******************************************************/
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
597
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
598 /**
599 * Filter the_content and add the liveblog theme-side UI above the normal
600 * content area.
601 *
602 * @param string $content
603 * @return string
604 */
605 public static function add_liveblog_to_content( $content ) {
cb778e4 @mjangda Load initial entries server-side rather than via AJAX for SEO benefit
mjangda authored
606
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
607 $liveblog_output = '<div id="liveblog-container" class="'. self::$post_id .'">';
608 $liveblog_output .= self::get_editor_output();
609 $liveblog_output .= '<div id="liveblog-update-spinner"></div>';
610 $liveblog_output .= self::get_all_entry_output();
ba2c2ae @mjangda Switch around ids with classes just to be future-safe. Add a new wrap…
mjangda authored
611 $liveblog_output .= '</div>';
8ff4206 @mjangda v1
mjangda authored
612
09e766c @mjangda New filter: liveblog_add_to_content
mjangda authored
613 $liveblog_output = apply_filters( 'liveblog_add_to_content', $liveblog_output, $content, self::$post_id );
614
7205206 @nb Put the post contents before the liveblog
nb authored
615 return $content . $liveblog_output;
8ff4206 @mjangda v1
mjangda authored
616 }
617
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
618 /**
619 * Return the posting area for the end-user to liveblog from
620 *
621 * @return string
622 */
623 private static function get_editor_output() {
5781e55 @nb Don't load the publishing interface if archived
nb authored
624 if ( !self::is_liveblog_editable() )
8ff4206 @mjangda v1
mjangda authored
625 return;
626
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
627 return self::get_template_part( 'liveblog-form.php' );
8ff4206 @mjangda v1
mjangda authored
628 }
629
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
630 /**
631 * Get all the liveblog entries for this post
632 */
633 private static function get_all_entry_output() {
8413aff @johnjamesjacoby Uploading:
johnjamesjacoby authored
634
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
635 // Get liveblog entries
9c2b7c3 @nb Order entries reverse-chronologically on initial load
nb authored
636 $entries = (array) self::$entry_query->get_all();
00379a8 @nb Add a a message for editors on archived liveblogs
nb authored
637 $show_archived_message = 'archive' == self::get_liveblog_state() && self::current_user_can_edit_liveblog();
8ff4206 @mjangda v1
mjangda authored
638
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
639 // Get the template part
00379a8 @nb Add a a message for editors on archived liveblogs
nb authored
640 return self::get_template_part( 'liveblog-loop.php', compact( 'entries', 'show_archived_message' ) );
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
641 }
642
643 /**
644 * Get the template part in an output buffer and return it
645 *
646 * @param string $template_name
647 * @param array $template_variables
648 */
649 public static function get_template_part( $template_name, $template_variables = array() ) {
650 ob_start();
651 extract( $template_variables );
652 include( dirname( __FILE__ ) . '/templates/' . $template_name );
653 return ob_get_clean();
8ff4206 @mjangda v1
mjangda authored
654 }
8413aff @johnjamesjacoby Uploading:
johnjamesjacoby authored
655
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
656 /** Admin Methods *********************************************************/
657
658 /**
659 * Register the metabox with the supporting post-type
660 *
661 * @param string $post_type
662 */
663 public static function add_meta_box( $post_type ) {
664
665 // Bail if not supported
666 if ( ! post_type_supports( $post_type, self::key ) )
667 return;
8ff4206 @mjangda v1
mjangda authored
668
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
669 add_meta_box( self::key, __( 'Liveblog', 'liveblog' ), array( __CLASS__, 'display_meta_box' ) );
8ff4206 @mjangda v1
mjangda authored
670 }
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
671
186ea96 @nb Add an image URL handler
nb authored
672 public static function image_embed_handler( $matches, $attr, $url, $rawattr ) {
673 $embed = sprintf( '<img src="%s" alt="" />', esc_url( $url ) );
674 return apply_filters( 'embed_liveblog_image', $embed, $matches, $attr, $url, $rawattr );
675 }
676
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
677 /**
678 * Output the metabox
679 *
680 * @param WP_Post $post
681 */
682 public static function display_meta_box( $post ) {
ea5a8a6 @nb Introduce archiving
nb authored
683 $current_state = self::get_liveblog_state( $post->ID );
684 $buttons = array(
8c3cdd8 @nb Remove the Disable button
nb authored
685 'enable' => array( 'value' => 'enable', 'text' => __( 'Enable', 'liveblog' ),
686 'description' => __( 'Enables liveblog on this post. Posting tools are enabled for editors, visitors get the latest updates.' , 'liveblog'), 'active-text' => sprintf( __( 'There is an <strong>enabled</strong> liveblog on this post. <a href="%s">Visit the liveblog &rarr;</a>', 'liveblog' ), get_permalink( $post ) ), 'primary' => true, 'disabled' => false, ),
ea5a8a6 @nb Introduce archiving
nb authored
687 'archive' => array( 'value' => 'archive', 'text' => __( 'Archive', 'liveblog' ),
8c3cdd8 @nb Remove the Disable button
nb authored
688 'description' => __( 'Archives the liveblog on this post. Visitors still see the liveblog entries, but posting tools are hidden.' , 'liveblog'), 'active-text' => sprintf( __( 'There is an <strong>archived</strong> liveblog on this post. <a href="%s">Visit the liveblog archive &rarr;</a>', 'liveblog' ), get_permalink( $post ) ), 'primary' => false, 'disabled' => false ),
ea5a8a6 @nb Introduce archiving
nb authored
689 );
8c3cdd8 @nb Remove the Disable button
nb authored
690 if ( $current_state ) {
691 $active_text = $buttons[$current_state]['active-text'];
692 $buttons[$current_state]['disabled'] = true;
693 } else {
694 $active_text = __( 'This is a normal WordPress post, without a liveblog.', 'liveblog' );
695 $buttons['archive']['disabled'] = true;
ea5a8a6 @nb Introduce archiving
nb authored
696 }
71eb33a @nb Dashes are the new underscores
nb authored
697 echo self::get_template_part( 'meta-box.php', compact( 'active_text', 'buttons' ) );
8ff4206 @mjangda v1
mjangda authored
698 }
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
699
ea5a8a6 @nb Introduce archiving
nb authored
700 public function admin_ajax_set_liveblog_state_for_post() {
701 $post_id = isset( $_REQUEST['post_id'] )? $_REQUEST['post_id'] : 0;
702 $new_state = isset( $_REQUEST['state'] )? $_REQUEST['state'] : '';
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
703
e447a3c @nb Check for permissions and nonces
nb authored
704 self::ajax_current_user_can_edit_liveblog();
705 self::ajax_check_nonce();
8ff4206 @mjangda v1
mjangda authored
706
ea5a8a6 @nb Introduce archiving
nb authored
707 if ( !$REQUEST = get_post( $post_id ) ) {
feecd6b @nb Add text domains
nb authored
708 self::send_user_error( __( "Non-existing post ID: $post_id" , 'liveblog') );
ea5a8a6 @nb Introduce archiving
nb authored
709 }
710
711 if ( wp_is_post_revision( $post_id ) ) {
feecd6b @nb Add text domains
nb authored
712 self::send_user_error( __( "The post is a revision: $post_id" , 'liveblog') );
ea5a8a6 @nb Introduce archiving
nb authored
713 }
c9f98b5 @mjangda Only update/delete liveblog postmeta when it's changing.
mjangda authored
714
ea5a8a6 @nb Introduce archiving
nb authored
715 self::set_liveblog_state( $post_id, $_REQUEST['state'] );
716 self::display_meta_box( $REQUEST );
717 exit;
718 }
c9f98b5 @mjangda Only update/delete liveblog postmeta when it's changing.
mjangda authored
719
ea5a8a6 @nb Introduce archiving
nb authored
720 private function set_liveblog_state( $post_id, $state ) {
721 if ( in_array( $state, array( 'enable', 'archive' ) ) ) {
722 update_post_meta( $post_id, self::key, $state );
723 do_action( "liveblog_{$state}_post", $post_id );
724 } elseif ( 'disable' == $state ) {
8ff4206 @mjangda v1
mjangda authored
725 delete_post_meta( $post_id, self::key );
7e39692 @mjangda Introduce some new hooks.
mjangda authored
726 do_action( 'liveblog_disable_post', $post_id );
ea5a8a6 @nb Introduce archiving
nb authored
727 } else {
728 return false;
7e39692 @mjangda Introduce some new hooks.
mjangda authored
729 }
8ff4206 @mjangda v1
mjangda authored
730 }
2ba7f86 @nb Remove trailing whitespace
nb authored
731
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
732 /** Error Methods *********************************************************/
733
734 /**
735 * Can the current user edit liveblog data (non-ajax)
736 *
737 * @return bool
738 */
739 public static function current_user_can_edit_liveblog() {
740 return (bool) current_user_can( apply_filters( 'liveblog_edit_cap', self::edit_cap ) );
8ff4206 @mjangda v1
mjangda authored
741 }
742
5781e55 @nb Don't load the publishing interface if archived
nb authored
743 public static function is_liveblog_editable() {
744 return self::current_user_can_edit_liveblog() && 'enable' == self::get_liveblog_state();
745 }
746
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
747 /**
748 * Can the current user edit liveblog data (ajax)
749 *
750 * Sends an error if not
751 */
752 public static function ajax_current_user_can_edit_liveblog() {
b58c3a0 @nb Remove leading underscores from function names
nb authored
753 if ( ! self::current_user_can_edit_liveblog() ) {
69f9cbb @nb Add more specific HTTP error codes
nb authored
754 self::send_forbidden_error( __( "Cheatin', uh?", 'liveblog' ) );
8ff4206 @mjangda v1
mjangda authored
755 }
756 }
757
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
758 /**
759 * Check for valid intention, and send an error if there is none
760 *
761 * @param string $action
762 */
763 public static function ajax_check_nonce( $action = self::nonce_key ) {
8ff4206 @mjangda v1
mjangda authored
764 if ( ! isset( $_REQUEST[ self::nonce_key ] ) || ! wp_verify_nonce( $_REQUEST[ self::nonce_key ], $action ) ) {
69f9cbb @nb Add more specific HTTP error codes
nb authored
765 self::send_forbidden_error( __( 'Sorry, we could not authenticate you.', 'liveblog' ) );
8ff4206 @mjangda v1
mjangda authored
766 }
767 }
768
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
769 /** Feedback **************************************************************/
770
771 /**
772 * Send an error message
773 * @param type $message
774 */
69f9cbb @nb Add more specific HTTP error codes
nb authored
775 private static function send_server_error( $message ) {
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
776 self::status_header_with_message( 500, $message );
777 exit();
778 }
779
69f9cbb @nb Add more specific HTTP error codes
nb authored
780 private static function send_user_error( $message ) {
781 self::status_header_with_message( 406, $message );
782 exit();
783 }
784
785 private static function send_forbidden_error( $message ) {
786 self::status_header_with_message( 403, $message );
787 exit();
788 }
789
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
790 /**
791 * Encode some data and echo it (possibly without cached headers)
792 *
793 * @param array $data
794 */
795 private static function json_return( $data ) {
20c5b02 @nb Get rid of the intermediate layer completely
nb authored
796 $json_data = json_encode( $data );
8ff4206 @mjangda v1
mjangda authored
797
f2908df @nb Get rid if return functionality in json_return()
nb authored
798 header( 'Content-Type: application/json' );
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
799 if ( self::$do_not_cache_response )
6c66757 @nb Do not let the client cache future requests
nb authored
800 nocache_headers();
20c5b02 @nb Get rid of the intermediate layer completely
nb authored
801
802 echo $json_data;
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
803 exit();
d81e042 @nb Extract sending errors in its own method
nb authored
804 }
805
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
806 /**
807 * Modify the header and description in the global array
808 *
809 * @global array $wp_header_to_desc
810 * @param int $status
811 * @param string $message
812 */
813 private static function status_header_with_message( $status, $message ) {
2532397 @nb Send HTTP errors instead of the success flag
nb authored
814 global $wp_header_to_desc;
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
815
816 $status = absint( $status );
817 $official_message = isset( $wp_header_to_desc[$status] ) ? $wp_header_to_desc[$status] : '';
2532397 @nb Send HTTP errors instead of the success flag
nb authored
818 $wp_header_to_desc[$status] = $message;
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
819
2532397 @nb Send HTTP errors instead of the success flag
nb authored
820 status_header( $status );
cd6d574 @johnjamesjacoby * Code clean up.
johnjamesjacoby authored
821
2532397 @nb Send HTTP errors instead of the success flag
nb authored
822 $wp_header_to_desc[$status] = $official_message;
823 }
8413aff @johnjamesjacoby Uploading:
johnjamesjacoby authored
824
825 /** Plupload Helpers ******************************************************/
826
827 /**
828 * Convert hours to bytes
829 *
830 * @param unknown_type $size
831 * @return unknown
832 */
833 private static function convert_hr_to_bytes( $size ) {
834 $size = strtolower( $size );
835 $bytes = (int) $size;
836
837 if ( strpos( $size, 'k' ) !== false )
838 $bytes = intval( $size ) * 1024;
839 elseif ( strpos( $size, 'm' ) !== false )
840 $bytes = intval( $size ) * 1024 * 1024;
841 elseif ( strpos( $size, 'g' ) !== false )
842 $bytes = intval( $size ) * 1024 * 1024 * 1024;
843
844 return $bytes;
845 }
846
847 /**
848 * Convert bytes to hour
849 *
850 * @param string $bytes
851 * @return string
852 */
853 private static function convert_bytes_to_hr( $bytes ) {
854 $units = array( 0 => 'B', 1 => 'kB', 2 => 'MB', 3 => 'GB' );
855 $log = log( $bytes, 1024 );
856 $power = (int) $log;
857 $size = pow( 1024, $log - $power );
858
859 return $size . $units[$power];
860 }
861
862 /**
863 * Get the maximum upload file size
864 *
865 * @see wp_max_upload_size()
866 * @return string
867 */
868 private static function max_upload_size() {
869 $u_bytes = self::convert_hr_to_bytes( ini_get( 'upload_max_filesize' ) );
870 $p_bytes = self::convert_hr_to_bytes( ini_get( 'post_max_size' ) );
871 $bytes = apply_filters( 'upload_size_limit', min( $u_bytes, $p_bytes ), $u_bytes, $p_bytes );
872
873 return $bytes;
a6429c8 @nb Remove trailing whitespace
nb authored
874 }
a823f5d @nb Show an admin notice if WP is older than 3.5
nb authored
875
876 private static function is_wp_too_old() {
877 global $wp_version;
878 return version_compare( $wp_version, self::min_wp_version, '<' );
879 }
8ff4206 @mjangda v1
mjangda authored
880 }
881
0a0ca28 @johnjamesjacoby Weekend updates:
johnjamesjacoby authored
882 /**
883 * Load the one true WPCOM_Liveblog instance
884 *
885 * Loaded late on the 'plugins_loaded' hook to allow any other plugin to sneak
886 * in ahead of it, to add actions, filters, etc...
887 *
888 * @uses WPCOM_Liveblog::load()
889 */
890 function wpcom_liveblog_load() {
891 WPCOM_Liveblog::load();
892 }
893 add_action( 'plugins_loaded', 'wpcom_liveblog_load', 999 );
894
8ff4206 @mjangda v1
mjangda authored
895 endif;
Something went wrong with that request. Please try again.