Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 790 lines (649 sloc) 24.069 kb
8ff4206 Mohammad Jangda v1
mjangda authored
1 <?php
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
2
8ff4206 Mohammad Jangda v1
mjangda authored
3 /**
4 * Plugin Name: Liveblog
1fc681a Nikolay Bachiyski Add metadata URLs
nb authored
5 * Plugin URI: http://wordpress.org/extend/plugins/liveblog/
8ff4206 Mohammad Jangda v1
mjangda authored
6 * Description: Blogging: at the speed of live.
aa5c82c Nikolay Bachiyski Bump 1.2
nb authored
7 * Version: 1.2
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
8 * Author: WordPress.com VIP, Automattic
1fc681a Nikolay Bachiyski Add metadata URLs
nb authored
9 * Author URI: http://vip.wordpress.com/
10 * Text Domain: liveblog
8ff4206 Mohammad Jangda v1
mjangda authored
11 */
12
13 if ( ! class_exists( 'WPCOM_Liveblog' ) ) :
14
0a0ca28 John James Jacoby 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 John James Jacoby Uploading:
johnjamesjacoby authored
25 *
5ad84ba Nikolay Bachiyski Fix typo
nb authored
26 * Things yet to be implemented:
0a0ca28 John James Jacoby 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 Mohammad Jangda v1
mjangda authored
36
aa5c82c Nikolay Bachiyski Bump 1.2
nb authored
37 const version = '1.2';
1d5d7f9 Nikolay Bachiyski Flush the rewrite rules on rules update
nb authored
38 const rewrites_version = 1;
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
39 const key = 'liveblog';
40 const url_endpoint = 'liveblog';
41 const edit_cap = 'publish_posts';
42 const nonce_key = 'liveblog_nonce';
8ff4206 Mohammad Jangda v1
mjangda authored
43
1d7244f Mohammad Jangda Increase the default refresh interval
mjangda authored
44 const refresh_interval = 10; // how often should we refresh
ed1991c Nikolay Bachiyski Shut the auto-update only on consecutive failures
nb authored
45 const max_consecutive_retries = 100; // max number of failed tries before polling is disabled
46 const delay_threshold = 5; // how many failed tries after which we should increase the refresh interval
47 const delay_multiplier = 2; // by how much should we inscrease the refresh interval
8ff4206 Mohammad Jangda v1
mjangda authored
48
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
49 /** Variables *************************************************************/
50
51 private static $post_id = null;
52 private static $entry_query = null;
53 private static $do_not_cache_response = false;
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
54
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
55 /** Load Methods **********************************************************/
56
57 /**
58 * @uses add_action() to hook methods into WordPress actions
59 * @uses add_filter() to hook methods into WordPress filters
60 */
61 public static function load() {
e5351e5 Mohammad Jangda load_plugin_textdomain so the plugin can be translated.
mjangda authored
62 load_plugin_textdomain( 'liveblog', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
63
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
64 self::includes();
65 self::add_actions();
66 self::add_filters();
67 self::add_admin_actions();
68 }
69
70 /**
71 * Include the necessary files
72 */
73 private static function includes() {
74 require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry.php' );
75 require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry-query.php' );
e691fe3 John James Jacoby Include ms.php theme-side for its filesize and available space functions...
johnjamesjacoby authored
76
77 // Manually include ms.php theme-side in multisite environments because
78 // we need its filesize and available space functions.
79 if ( ! is_admin() && is_multisite() ) {
8f5fb3c John James Jacoby Remove preceding slash. ABSPATH is already slashed for us.
johnjamesjacoby authored
80 require_once( ABSPATH . 'wp-admin/includes/ms.php' );
e691fe3 John James Jacoby Include ms.php theme-side for its filesize and available space functions...
johnjamesjacoby authored
81 }
02b5fdb Nikolay Bachiyski Add convertor from extend read me to github readme
nb authored
82
83 if ( defined( 'WP_CLI' ) && WP_CLI ) {
84 require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-wp-cli.php' );
85 }
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
86 }
8ff4206 Mohammad Jangda v1
mjangda authored
87
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
88 /**
89 * Hook actions in that run on every page-load
90 *
91 * @uses add_action()
92 */
93 private static function add_actions() {
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
94 add_action( 'init', array( __CLASS__, 'init' ) );
7994c3e Nikolay Bachiyski Re-add the rewrite rules on permalink change
nb authored
95 add_action( 'init', array( __CLASS__, 'add_rewrite_rules' ) );
96 add_action( 'permalink_structure_changed', array( __CLASS__, 'add_rewrite_rules' ) );
4221823 Nikolay Bachiyski Flush the rewrite rules later
nb authored
97 // flush the rewrite rules a lot later so that we don't interfere with other plugins using rewrite rules
98 add_action( 'init', array( __CLASS__, 'flush_rewrite_rules' ), 1000 );
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
99 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
5aee585 Nikolay Bachiyski Add ajax endpoint for preview
nb authored
100 add_action( 'wp_ajax_liveblog_preview_entry', array( __CLASS__, 'ajax_preview_entry' ) );
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
101 }
8ff4206 Mohammad Jangda v1
mjangda authored
102
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
103 /**
104 * Hook filters in that run on every page-load
105 *
106 * @uses add_filter()
107 */
108 private static function add_filters() {
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
109 add_filter( 'template_redirect', array( __CLASS__, 'handle_request' ) );
c3dc8bd Mohammad Jangda Only apply liveblog-entry CSS class to liveblog comment types.
mjangda authored
110 add_filter( 'comment_class', array( __CLASS__, 'add_comment_class' ), 10, 3 );
8ff4206 Mohammad Jangda v1
mjangda authored
111 }
112
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
113 /**
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
114 * Hook actions in that run on every admin page-load
115 *
116 * @uses add_action()
117 * @uses is_admin()
118 */
119 private static function add_admin_actions() {
120
121 // Bail if not in admin area
122 if ( ! is_admin() )
123 return;
124
125 add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_box' ) );
126 add_action( 'save_post', array( __CLASS__, 'save_meta_box' ) );
127 }
128
129 /** Public Methods ********************************************************/
130
131 /**
132 * Liveblog initialization functions.
133 *
134 * This is where Liveblog sets up any additional things it needs to run
135 * inside of WordPress. Where some plugins would register post types or
136 * taxonomies, we modify endpoints and add post type support for Liveblog.
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
137 */
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
138 public static function init() {
139 /**
140 * Add liveblog support to the 'post' post type. This is done here so
141 * we can possibly introduce this to other post types later.
142 */
8ff4206 Mohammad Jangda v1
mjangda authored
143 add_post_type_support( 'post', self::key );
8314495 Nikolay Bachiyski Add an action after liveblog's init
nb authored
144 do_action( 'after_liveblog_init' );
8ff4206 Mohammad Jangda v1
mjangda authored
145 }
146
7994c3e Nikolay Bachiyski Re-add the rewrite rules on permalink change
nb authored
147 public function add_rewrite_rules() {
1d5d7f9 Nikolay Bachiyski Flush the rewrite rules on rules update
nb authored
148 add_rewrite_endpoint( self::url_endpoint, EP_PERMALINK );
7994c3e Nikolay Bachiyski Re-add the rewrite rules on permalink change
nb authored
149 }
1d5d7f9 Nikolay Bachiyski Flush the rewrite rules on rules update
nb authored
150
7994c3e Nikolay Bachiyski Re-add the rewrite rules on permalink change
nb authored
151 public static function flush_rewrite_rules() {
1d5d7f9 Nikolay Bachiyski Flush the rewrite rules on rules update
nb authored
152 if ( get_option( 'liveblog_rewrites_version' ) != self::rewrites_version ) {
153 flush_rewrite_rules();
154 update_option( 'liveblog_rewrites_version', self::rewrites_version );
155 }
156 }
157
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
158 /**
159 * This is where a majority of the magic happens.
160 *
161 * Hooked to template_redirect, this method tries to add anything it can to
162 * the current post output. If nothing needs to be added, we redirect back
163 * to the permalink.
164 *
165 * @return If request has been handled
166 */
167 public static function handle_request() {
168
8ff4206 Mohammad Jangda v1
mjangda authored
169 if ( ! self::is_viewing_liveblog_post() )
170 return;
171
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
172 self::$post_id = get_the_ID();
b28b38d Nikolay Bachiyski Rename the query class to match WP conventions
nb authored
173 self::$entry_query = new WPCOM_Liveblog_Entry_Query( self::$post_id, self::key );
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
174
4872b2a Nikolay Bachiyski Use front-end AJAX URLs for same-origin requests
nb authored
175 if ( self::is_initial_page_request() )
8ff4206 Mohammad Jangda v1
mjangda authored
176 add_filter( 'the_content', array( __CLASS__, 'add_liveblog_to_content' ) );
4872b2a Nikolay Bachiyski Use front-end AJAX URLs for same-origin requests
nb authored
177 else
178 self::handle_ajax_request();
179 }
180
181 private static function handle_ajax_request() {
182
183 $endpoint_suffix = get_query_var( self::url_endpoint );
184
185 if ( !$endpoint_suffix ) {
186 // we redirect, because if somebody accessed <permalink>/liveblog
187 // they probably did that in the URL bar, not via AJAX
188 wp_safe_redirect( get_permalink() );
189 exit();
8ff4206 Mohammad Jangda v1
mjangda authored
190 }
2b0244c Nikolay Bachiyski Remove trailing whitespace
nb authored
191 wp_cache_delete( self::key . '_entries_asc_' . self::$post_id, 'liveblog' );
8ff4206 Mohammad Jangda v1
mjangda authored
192
4872b2a Nikolay Bachiyski Use front-end AJAX URLs for same-origin requests
nb authored
193 $suffix_to_method = array(
194 '\d+/\d+' => 'ajax_entries_between',
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
195 'crud' => 'ajax_crud_entry',
4872b2a Nikolay Bachiyski Use front-end AJAX URLs for same-origin requests
nb authored
196 'preview' => 'ajax_preview_entry',
197 );
198
199 $response_method = 'ajax_unknown';
200
201 foreach( $suffix_to_method as $suffix_re => $method ) {
202 if ( preg_match( "%^$suffix_re/?%", $endpoint_suffix ) ) {
203 $response_method = $method;
204 break;
205 }
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
206 }
207
4872b2a Nikolay Bachiyski Use front-end AJAX URLs for same-origin requests
nb authored
208 self::$response_method();
209
8ff4206 Mohammad Jangda v1
mjangda authored
210 }
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
211
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
212 /**
213 * Look for any new Liveblog entries, and return them via JSON
214 */
215 public static function ajax_entries_between() {
216
217 // Set some defaults
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
218 $latest_timestamp = 0;
219 $entries_for_json = array();
558008c Nikolay Bachiyski Use the same current timestamp at all places
nb authored
220
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
221 // Look for entry boundaries
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
222 list( $start_timestamp, $end_timestamp ) = self::get_timestamps_from_query();
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
223
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
224 // Bail if there is no end timestamp
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
225 if ( empty( $end_timestamp ) ) {
70b347a Mohammad Jangda Add missing textdomain to translated strings
mjangda authored
226 self::send_user_error( __( 'A timestamp is missing. Correct URL: <permalink>/liveblog/<from>/</to>/', 'liveblog' ) );
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
227 }
228
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
229 // Do not cache if it's too soon
bd6c841 Nikolay Bachiyski Use the Date header to get server-side date
nb authored
230 if ( $end_timestamp > time() )
6c66757 Nikolay Bachiyski Do not let the client cache future requests
nb authored
231 self::$do_not_cache_response = true;
232
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
233 // Get liveblog entries within the start and end boundaries
b28b38d Nikolay Bachiyski Rename the query class to match WP conventions
nb authored
234 $entries = self::$entry_query->get_between_timestamps( $start_timestamp, $end_timestamp );
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
235 if ( empty( $entries ) ) {
7e39692 Mohammad Jangda Introduce some new hooks.
mjangda authored
236 do_action( 'liveblog_entry_request_empty' );
237
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
238 self::json_return( array(
239 'entries' => array(),
240 'latest_timestamp' => null
241 ) );
242 }
d79a82d Nikolay Bachiyski Gather common entry functionality in a new class
nb authored
243
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
244 /**
245 * Loop through each liveblog entry, set the most recent timestamp, and
246 * put the JSON data for each entry into a neat little array.
247 */
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
248 foreach( $entries as $entry ) {
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
249 $latest_timestamp = max( $latest_timestamp, $entry->get_timestamp() );
d79a82d Nikolay Bachiyski Gather common entry functionality in a new class
nb authored
250 $entries_for_json[] = $entry->for_json();
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
251 }
252
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
253 // Setup our data to return via JSON
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
254 $result_for_json = array(
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
255 'entries' => $entries_for_json,
256 'latest_timestamp' => $latest_timestamp,
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
257 );
258
7e39692 Mohammad Jangda Introduce some new hooks.
mjangda authored
259 do_action( 'liveblog_entry_request', $result_for_json );
260
e977561 Nikolay Bachiyski Get rid of extra json_return() arguments
nb authored
261 self::json_return( $result_for_json );
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
262 }
263
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
264 /** Private _is_ Methods **************************************************/
265
266 /**
267 * Are we viewing a liveblog post?
268 *
269 * @uses is_single()
270 * @uses is_liveblog_post()
271 * @return bool
272 */
273 private static function is_viewing_liveblog_post() {
274 return (bool) ( is_single() && self::is_liveblog_post() );
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
275 }
276
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
277 /**
278 * Is this the initial page request?
279 *
280 * Note that we do not use get_query_var() - it returns '' for all requests,
281 * which is valid for /post-name/liveblog/
282 *
283 * @global WP_Query $wp_query
284 * @return bool
285 */
286 private static function is_initial_page_request() {
8ff4206 Mohammad Jangda v1
mjangda authored
287 global $wp_query;
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
288
289 return (bool) ! isset( $wp_query->query_vars[self::key] );
8ff4206 Mohammad Jangda v1
mjangda authored
290 }
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
291
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
292 /**
293 * Is this an ajax request for the entries?
294 *
295 * @uses get_query_var() to check for the url_endpoint
296 * @return bool
297 */
298 private static function is_entries_ajax_request() {
299 return (bool) get_query_var( self::url_endpoint );
300 }
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
301
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
302 /**
303 * Is a given post_id a liveblog enabled post?
304 *
305 * @global WP_Post $post
306 * @param int $post_id
307 * @return bool
308 */
309 private static function is_liveblog_post( $post_id = null ) {
310 if ( empty( $post_id ) ) {
311 global $post;
312 $post_id = $post->ID;
313 }
314
315 return (bool) get_post_meta( $post_id, self::key, true );
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
316 }
317
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
318 /**
319 * Get timestamps from the current WP_Query
320 *
321 * Ensures that two timestamps exist, and returns a properly formatted empty
322 * array if not.
323 *
324 * @return array
325 */
326 private static function get_timestamps_from_query() {
327
328 // Look for timestamps and bail if none
25be635 Mohammad Jangda Support for non-pretty permalinks
mjangda authored
329 $stamps = rtrim( get_query_var( self::url_endpoint ), '/' );
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
330 if ( empty( $stamps ) )
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
331 return array( false, false );
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
332
333 // Get timestamps from the query variable
334 $timestamps = explode( '/', $stamps );
335
336 // Bail if there are not 2 timestamps
337 if ( 2 !== count( $timestamps ) )
338 return array( false, false );
339
340 // Return integer timestamps in an array
341 return array_map( 'intval', $timestamps );
1b8e8d5 Nikolay Bachiyski Streamline logic for getting recent entries
nb authored
342 }
343
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
344 public static function ajax_crud_entry() {
b58c3a0 Nikolay Bachiyski Remove leading underscores from function names
nb authored
345 self::ajax_current_user_can_edit_liveblog();
346 self::ajax_check_nonce();
8ff4206 Mohammad Jangda v1
mjangda authored
347
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
348 $args = array();
8ff4206 Mohammad Jangda v1
mjangda authored
349
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
350 $crud_action = isset( $_POST['crud_action'] ) ? $_POST['crud_action'] : 0;
8ff4206 Mohammad Jangda v1
mjangda authored
351
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
352 if ( !in_array( $crud_action, array( 'insert', 'update', 'delete' ) ) ) {
353 self::send_user_error( sprintf( __( 'Invalid entry crud_action: %s', 'liveblog' ), $crud_action ) );
a2723d4 Nikolay Bachiyski Commit entry modifications
nb authored
354 }
355
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
356 $args['post_id'] = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
357 $args['content'] = isset( $_POST['content'] ) ? $_POST['content'] : '';
358 $args['entry_id'] = isset( $_POST['entry_id'] ) ? intval( $_POST['entry_id'] ) : 0;
e92599e Nikolay Bachiyski Switch the delete endpoint to use the new method
nb authored
359
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
360 $args['user'] = wp_get_current_user();
361 $args['ip'] = preg_replace( '/[^0-9a-fA-F:., ]/', '',$_SERVER['REMOTE_ADDR'] );
362 $args['user_agent'] = substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 );
e92599e Nikolay Bachiyski Switch the delete endpoint to use the new method
nb authored
363
4c7e77b Nikolay Bachiyski Consolidate all CRUD AJAX actions
nb authored
364 $entry = call_user_func( array( 'WPCOM_Liveblog_Entry', $crud_action ), $args );
e92599e Nikolay Bachiyski Switch the delete endpoint to use the new method
nb authored
365
366 if ( is_wp_error( $entry ) ) {
367 self::send_server_error( $entry->get_error_message() );
368 }
369
370 // Do not send latest_timestamp. If we send it the client won't get
371 // older entries. Since we send only the new one, we don't know if there
372 // weren't any entries in between.
373 self::json_return( array(
374 'entries' => array( $entry->for_json() ),
375 'latest_timestamp' => null
376 ) );
377 }
378
5aee585 Nikolay Bachiyski Add ajax endpoint for preview
nb authored
379 function ajax_preview_entry() {
380 $entry_content = isset( $_REQUEST['entry_content'] ) ? $_REQUEST['entry_content'] : '';
5460519 Mohammad Jangda Fix preview which was returning slashed data.
mjangda authored
381 $entry_content = stripslashes( wp_filter_post_kses( $entry_content ) );
5aee585 Nikolay Bachiyski Add ajax endpoint for preview
nb authored
382 $entry_content = WPCOM_Liveblog_Entry::render_content( $entry_content );
7e39692 Mohammad Jangda Introduce some new hooks.
mjangda authored
383
384 do_action( 'liveblog_preview_entry', $entry_content );
385
5aee585 Nikolay Bachiyski Add ajax endpoint for preview
nb authored
386 self::json_return( array( 'html' => $entry_content ) );
387 }
388
4872b2a Nikolay Bachiyski Use front-end AJAX URLs for same-origin requests
nb authored
389 public function ajax_unknown() {
390 self::send_user_error( __( 'Unknown liveblog action', 'liveblog' ) );
391 }
392
393
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
394 /** Comment Methods *******************************************************/
8ff4206 Mohammad Jangda v1
mjangda authored
395
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
396 /**
397 * Add a liveblog class to each comment, so they can be styled
398 *
399 * @param array $classes
400 * @return string
401 */
c3dc8bd Mohammad Jangda Only apply liveblog-entry CSS class to liveblog comment types.
mjangda authored
402 public static function add_comment_class( $classes, $class, $comment_id ) {
403 if ( self::key == get_comment_type( $comment_id ) )
404 $classes[] = 'liveblog-entry';
8ff4206 Mohammad Jangda v1
mjangda authored
405 return $classes;
406 }
407
f157181 John James Jacoby Comment Status:
johnjamesjacoby authored
408
409 /**
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
410 * Enqueue the necessary CSS and JS that liveblog needs to function.
411 *
412 * @return If not a liveblog post
413 */
414 public static function enqueue_scripts() {
415
8ff4206 Mohammad Jangda v1
mjangda authored
416 if ( ! self::is_viewing_liveblog_post() )
417 return;
418
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
419 wp_enqueue_style( self::key, plugins_url( 'css/liveblog.css', __FILE__ ) );
db742c8 Nikolay Bachiyski Highlight new posts
nb authored
420 wp_enqueue_script( self::key, plugins_url( 'js/liveblog.js', __FILE__ ), array( 'jquery', 'jquery-color' ), self::version, true );
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
421
8413aff John James Jacoby Uploading:
johnjamesjacoby authored
422 if ( self::current_user_can_edit_liveblog() ) {
a456b55 Nikolay Bachiyski Add Preview interface
nb authored
423 wp_enqueue_script( 'liveblog-publisher', plugins_url( 'js/liveblog-publisher.js', __FILE__ ), array( self::key, 'jquery-ui-tabs' ), self::version, true );
212e64d Zach Hookable Uploader
zbtirrell authored
424 wp_enqueue_script( 'liveblog-plupload', plugins_url( 'js/plupload.js', __FILE__ ), array( self::key, 'wp-plupload', 'jquery' ) );
c65e58f Nikolay Bachiyski Make the function name a verb
nb authored
425 self::add_default_plupload_settings();
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
426 }
8ff4206 Mohammad Jangda v1
mjangda authored
427
c0c3085 Nikolay Bachiyski Add spinner for inserting an entry
nb authored
428 if ( wp_script_is( 'jquery.spin', 'registered' ) ) {
429 wp_enqueue_script( 'jquery.spin' );
430 } else {
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
431 wp_enqueue_script( 'spin', plugins_url( 'js/spin.js', __FILE__ ), false, '1.2.4' );
432 wp_enqueue_script( 'jquery.spin', plugins_url( 'js/jquery.spin.js', __FILE__ ), array( 'jquery', 'spin' ) );
c0c3085 Nikolay Bachiyski Add spinner for inserting an entry
nb authored
433 }
434
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
435 wp_localize_script( self::key, 'liveblog_settings',
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
436 apply_filters( 'liveblog_settings', array(
437 'permalink' => get_permalink(),
438 'post_id' => get_the_ID(),
8ff4206 Mohammad Jangda v1
mjangda authored
439
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
440 'key' => self::key,
441 'nonce_key' => self::nonce_key,
442 'latest_entry_timestamp' => self::$entry_query->get_latest_timestamp(),
8ff4206 Mohammad Jangda v1
mjangda authored
443
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
444 'refresh_interval' => self::refresh_interval,
ed1991c Nikolay Bachiyski Shut the auto-update only on consecutive failures
nb authored
445 'max_consecutive_retries'=> self::max_consecutive_retries,
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
446 'delay_threshold' => self::delay_threshold,
447 'delay_multiplier' => self::delay_multiplier,
8ff4206 Mohammad Jangda v1
mjangda authored
448
358dc85 Nikolay Bachiyski Rename entriesurl to endpoint_url
nb authored
449 'endpoint_url' => self::get_entries_endpoint_url(),
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
450
451 // i18n
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
452 'update_nag_singular' => __( '%d new update', 'liveblog' ),
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
453 'update_nag_plural' => __( '%d new updates', 'liveblog' ),
28802ff Nikolay Bachiyski Delete entry functionality
nb authored
454 'delete_confirmation' => __( 'Do you really want do delete this entry? There is no way back.', 'liveblog' ),
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
455 ) )
456 );
8ff4206 Mohammad Jangda v1
mjangda authored
457 }
458
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
459 /**
8413aff John James Jacoby Uploading:
johnjamesjacoby authored
460 * Sets up some default Plupload settings so we can upload meda theme-side
461 *
462 * @global type $wp_scripts
463 */
c65e58f Nikolay Bachiyski Make the function name a verb
nb authored
464 private static function add_default_plupload_settings() {
8413aff John James Jacoby Uploading:
johnjamesjacoby authored
465 global $wp_scripts;
466
467 $defaults = array(
468 'runtimes' => 'html5,silverlight,flash,html4',
469 'file_data_name' => 'async-upload',
470 'multiple_queues' => true,
471 'max_file_size' => self::max_upload_size() . 'b',
472 'url' => admin_url( 'admin-ajax.php', 'relative' ),
473 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
474 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
70b347a Mohammad Jangda Add missing textdomain to translated strings
mjangda authored
475 'filters' => array( array( 'title' => __( 'Allowed Files', 'liveblog' ), 'extensions' => '*') ),
8413aff John James Jacoby Uploading:
johnjamesjacoby authored
476 'multipart' => true,
477 'urlstream_upload' => true,
478 'multipart_params' => array(
479 'action' => 'upload-attachment',
480 '_wpnonce' => wp_create_nonce( 'media-form' )
481 )
482 );
483
484 $settings = array(
485 'defaults' => $defaults,
486 'browser' => array(
487 'mobile' => wp_is_mobile(),
488 'supported' => _device_can_upload(),
489 )
490 );
491
492 $script = 'var _wpPluploadSettings = ' . json_encode( $settings ) . ';';
493 $data = $wp_scripts->get_data( 'wp-plupload', 'data' );
494
495 if ( ! empty( $data ) )
496 $script = "$data\n$script";
497
498 $wp_scripts->add_data( 'wp-plupload', 'data', $script );
499 }
500
501 /**
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
502 * Get the URL of a specific liveblog entry.
503 *
504 * @return string
505 */
506 private static function get_entries_endpoint_url() {
0dccc81 Nikolay Bachiyski Add correct endpoing to draft URLs with query args
nb authored
507 $post_permalink = get_permalink( self::$post_id );
508 if ( false !== strpos( $post_permalink, '?p=' ) )
509 $url = add_query_arg( self::url_endpoint, '', $post_permalink ) . '='; // returns something like ?p=1&liveblog=
25be635 Mohammad Jangda Support for non-pretty permalinks
mjangda authored
510 else
0dccc81 Nikolay Bachiyski Add correct endpoing to draft URLs with query args
nb authored
511 $url = trailingslashit( trailingslashit( $post_permalink ) . self::url_endpoint ); // returns something like /2012/01/01/post/liveblog/
7330fcb Nikolay Bachiyski Allow the endpoint URL to be filtered
nb authored
512 $url = apply_filters( 'liveblog_endpoint_url', $url, self::$post_id );
25be635 Mohammad Jangda Support for non-pretty permalinks
mjangda authored
513 return $url;
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
514 }
cb778e4 Mohammad Jangda Load initial entries server-side rather than via AJAX for SEO benefit
mjangda authored
515
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
516 /** Display Methods *******************************************************/
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
517
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
518 /**
519 * Filter the_content and add the liveblog theme-side UI above the normal
520 * content area.
521 *
522 * @param string $content
523 * @return string
524 */
525 public static function add_liveblog_to_content( $content ) {
cb778e4 Mohammad Jangda Load initial entries server-side rather than via AJAX for SEO benefit
mjangda authored
526
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
527 $liveblog_output = '<div id="liveblog-container" class="'. self::$post_id .'">';
528 $liveblog_output .= self::get_editor_output();
529 $liveblog_output .= '<div id="liveblog-update-spinner"></div>';
530 $liveblog_output .= self::get_all_entry_output();
ba2c2ae Mohammad Jangda Switch around ids with classes just to be future-safe. Add a new wrapper...
mjangda authored
531 $liveblog_output .= '</div>';
8ff4206 Mohammad Jangda v1
mjangda authored
532
09e766c Mohammad Jangda New filter: liveblog_add_to_content
mjangda authored
533 $liveblog_output = apply_filters( 'liveblog_add_to_content', $liveblog_output, $content, self::$post_id );
534
7205206 Nikolay Bachiyski Put the post contents before the liveblog
nb authored
535 return $content . $liveblog_output;
8ff4206 Mohammad Jangda v1
mjangda authored
536 }
537
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
538 /**
539 * Return the posting area for the end-user to liveblog from
540 *
541 * @return string
542 */
543 private static function get_editor_output() {
b58c3a0 Nikolay Bachiyski Remove leading underscores from function names
nb authored
544 if ( ! self::current_user_can_edit_liveblog() )
8ff4206 Mohammad Jangda v1
mjangda authored
545 return;
546
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
547 // Get the template part
548 return self::get_template_part( 'liveblog-form.php' );
8ff4206 Mohammad Jangda v1
mjangda authored
549 }
550
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
551 /**
552 * Get all the liveblog entries for this post
553 */
554 private static function get_all_entry_output() {
8413aff John James Jacoby Uploading:
johnjamesjacoby authored
555
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
556 // Get liveblog entries
9c2b7c3 Nikolay Bachiyski Order entries reverse-chronologically on initial load
nb authored
557 $entries = (array) self::$entry_query->get_all();
8ff4206 Mohammad Jangda v1
mjangda authored
558
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
559 // Get the template part
560 return self::get_template_part( 'liveblog-loop.php', compact( 'entries' ) );
561 }
562
563 /**
564 * Get the template part in an output buffer and return it
565 *
566 * @param string $template_name
567 * @param array $template_variables
568 */
569 public static function get_template_part( $template_name, $template_variables = array() ) {
570 ob_start();
571 extract( $template_variables );
572 include( dirname( __FILE__ ) . '/templates/' . $template_name );
573 return ob_get_clean();
8ff4206 Mohammad Jangda v1
mjangda authored
574 }
8413aff John James Jacoby Uploading:
johnjamesjacoby authored
575
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
576 /** Admin Methods *********************************************************/
577
578 /**
579 * Register the metabox with the supporting post-type
580 *
581 * @param string $post_type
582 */
583 public static function add_meta_box( $post_type ) {
584
585 // Bail if not supported
586 if ( ! post_type_supports( $post_type, self::key ) )
587 return;
8ff4206 Mohammad Jangda v1
mjangda authored
588
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
589 add_meta_box( self::key, __( 'Liveblog', 'liveblog' ), array( __CLASS__, 'display_meta_box' ) );
8ff4206 Mohammad Jangda v1
mjangda authored
590 }
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
591
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
592 /**
593 * Output the metabox
594 *
595 * @param WP_Post $post
596 */
597 public static function display_meta_box( $post ) {
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
598 ?>
599
8ff4206 Mohammad Jangda v1
mjangda authored
600 <label>
601 <input type="checkbox" name="is-liveblog" id="is-liveblog" value="1" <?php checked( self::is_liveblog_post( $post->ID ) ); ?> />
602 <?php esc_html_e( 'This is a liveblog', 'liveblog' ); ?>
603 </label>
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
604
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
605 <?php
606 wp_nonce_field( self::nonce_key, self::nonce_key, false );
8ff4206 Mohammad Jangda v1
mjangda authored
607 }
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
608
609 /**
610 * Save the metabox when the post is saved
611 *
612 * @param type $post_id
613 * @return type
614 */
615 public function save_meta_box( $post_id ) {
616
617 // Bail if no liveblog nonce
618 if ( empty( $_POST[self::nonce_key] ) || ! wp_verify_nonce( $_POST[self::nonce_key], self::nonce_key ) )
8ff4206 Mohammad Jangda v1
mjangda authored
619 return;
620
c9f98b5 Mohammad Jangda Only update/delete liveblog postmeta when it's changing.
mjangda authored
621 if ( wp_is_post_revision( $post_id ) )
622 return;
623
624 $is_liveblog = self::is_liveblog_post( $post_id );
625
626 if ( ! empty( $_POST['is-liveblog'] ) && ! $is_liveblog ) {
8ff4206 Mohammad Jangda v1
mjangda authored
627 update_post_meta( $post_id, self::key, 1 );
7e39692 Mohammad Jangda Introduce some new hooks.
mjangda authored
628 do_action( 'liveblog_enable_post', $post_id );
c9f98b5 Mohammad Jangda Only update/delete liveblog postmeta when it's changing.
mjangda authored
629 } elseif ( empty( $_POST['is-liveblog'] ) && $is_liveblog ) {
8ff4206 Mohammad Jangda v1
mjangda authored
630 delete_post_meta( $post_id, self::key );
7e39692 Mohammad Jangda Introduce some new hooks.
mjangda authored
631 do_action( 'liveblog_disable_post', $post_id );
632 }
8ff4206 Mohammad Jangda v1
mjangda authored
633 }
2ba7f86 Nikolay Bachiyski Remove trailing whitespace
nb authored
634
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
635 /** Error Methods *********************************************************/
636
637 /**
638 * Can the current user edit liveblog data (non-ajax)
639 *
640 * @return bool
641 */
642 public static function current_user_can_edit_liveblog() {
643 return (bool) current_user_can( apply_filters( 'liveblog_edit_cap', self::edit_cap ) );
8ff4206 Mohammad Jangda v1
mjangda authored
644 }
645
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
646 /**
647 * Can the current user edit liveblog data (ajax)
648 *
649 * Sends an error if not
650 */
651 public static function ajax_current_user_can_edit_liveblog() {
b58c3a0 Nikolay Bachiyski Remove leading underscores from function names
nb authored
652 if ( ! self::current_user_can_edit_liveblog() ) {
69f9cbb Nikolay Bachiyski Add more specific HTTP error codes
nb authored
653 self::send_forbidden_error( __( "Cheatin', uh?", 'liveblog' ) );
8ff4206 Mohammad Jangda v1
mjangda authored
654 }
655 }
656
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
657 /**
658 * Check for valid intention, and send an error if there is none
659 *
660 * @param string $action
661 */
662 public static function ajax_check_nonce( $action = self::nonce_key ) {
8ff4206 Mohammad Jangda v1
mjangda authored
663 if ( ! isset( $_REQUEST[ self::nonce_key ] ) || ! wp_verify_nonce( $_REQUEST[ self::nonce_key ], $action ) ) {
69f9cbb Nikolay Bachiyski Add more specific HTTP error codes
nb authored
664 self::send_forbidden_error( __( 'Sorry, we could not authenticate you.', 'liveblog' ) );
8ff4206 Mohammad Jangda v1
mjangda authored
665 }
666 }
667
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
668 /** Feedback **************************************************************/
669
670 /**
671 * Send an error message
672 * @param type $message
673 */
69f9cbb Nikolay Bachiyski Add more specific HTTP error codes
nb authored
674 private static function send_server_error( $message ) {
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
675 self::status_header_with_message( 500, $message );
676 exit();
677 }
678
69f9cbb Nikolay Bachiyski Add more specific HTTP error codes
nb authored
679 private static function send_user_error( $message ) {
680 self::status_header_with_message( 406, $message );
681 exit();
682 }
683
684 private static function send_forbidden_error( $message ) {
685 self::status_header_with_message( 403, $message );
686 exit();
687 }
688
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
689 /**
690 * Encode some data and echo it (possibly without cached headers)
691 *
692 * @param array $data
693 */
694 private static function json_return( $data ) {
20c5b02 Nikolay Bachiyski Get rid of the intermediate layer completely
nb authored
695 $json_data = json_encode( $data );
8ff4206 Mohammad Jangda v1
mjangda authored
696
f2908df Nikolay Bachiyski Get rid if return functionality in json_return()
nb authored
697 header( 'Content-Type: application/json' );
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
698 if ( self::$do_not_cache_response )
6c66757 Nikolay Bachiyski Do not let the client cache future requests
nb authored
699 nocache_headers();
20c5b02 Nikolay Bachiyski Get rid of the intermediate layer completely
nb authored
700
701 echo $json_data;
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
702 exit();
d81e042 Nikolay Bachiyski Extract sending errors in its own method
nb authored
703 }
704
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
705 /**
706 * Modify the header and description in the global array
707 *
708 * @global array $wp_header_to_desc
709 * @param int $status
710 * @param string $message
711 */
712 private static function status_header_with_message( $status, $message ) {
2532397 Nikolay Bachiyski Send HTTP errors instead of the success flag
nb authored
713 global $wp_header_to_desc;
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
714
715 $status = absint( $status );
716 $official_message = isset( $wp_header_to_desc[$status] ) ? $wp_header_to_desc[$status] : '';
2532397 Nikolay Bachiyski Send HTTP errors instead of the success flag
nb authored
717 $wp_header_to_desc[$status] = $message;
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
718
2532397 Nikolay Bachiyski Send HTTP errors instead of the success flag
nb authored
719 status_header( $status );
cd6d574 John James Jacoby * Code clean up.
johnjamesjacoby authored
720
2532397 Nikolay Bachiyski Send HTTP errors instead of the success flag
nb authored
721 $wp_header_to_desc[$status] = $official_message;
722 }
8413aff John James Jacoby Uploading:
johnjamesjacoby authored
723
724 /** Plupload Helpers ******************************************************/
725
726 /**
727 * Convert hours to bytes
728 *
729 * @param unknown_type $size
730 * @return unknown
731 */
732 private static function convert_hr_to_bytes( $size ) {
733 $size = strtolower( $size );
734 $bytes = (int) $size;
735
736 if ( strpos( $size, 'k' ) !== false )
737 $bytes = intval( $size ) * 1024;
738 elseif ( strpos( $size, 'm' ) !== false )
739 $bytes = intval( $size ) * 1024 * 1024;
740 elseif ( strpos( $size, 'g' ) !== false )
741 $bytes = intval( $size ) * 1024 * 1024 * 1024;
742
743 return $bytes;
744 }
745
746 /**
747 * Convert bytes to hour
748 *
749 * @param string $bytes
750 * @return string
751 */
752 private static function convert_bytes_to_hr( $bytes ) {
753 $units = array( 0 => 'B', 1 => 'kB', 2 => 'MB', 3 => 'GB' );
754 $log = log( $bytes, 1024 );
755 $power = (int) $log;
756 $size = pow( 1024, $log - $power );
757
758 return $size . $units[$power];
759 }
760
761 /**
762 * Get the maximum upload file size
763 *
764 * @see wp_max_upload_size()
765 * @return string
766 */
767 private static function max_upload_size() {
768 $u_bytes = self::convert_hr_to_bytes( ini_get( 'upload_max_filesize' ) );
769 $p_bytes = self::convert_hr_to_bytes( ini_get( 'post_max_size' ) );
770 $bytes = apply_filters( 'upload_size_limit', min( $u_bytes, $p_bytes ), $u_bytes, $p_bytes );
771
772 return $bytes;
a6429c8 Nikolay Bachiyski Remove trailing whitespace
nb authored
773 }
8ff4206 Mohammad Jangda v1
mjangda authored
774 }
775
0a0ca28 John James Jacoby Weekend updates:
johnjamesjacoby authored
776 /**
777 * Load the one true WPCOM_Liveblog instance
778 *
779 * Loaded late on the 'plugins_loaded' hook to allow any other plugin to sneak
780 * in ahead of it, to add actions, filters, etc...
781 *
782 * @uses WPCOM_Liveblog::load()
783 */
784 function wpcom_liveblog_load() {
785 WPCOM_Liveblog::load();
786 }
787 add_action( 'plugins_loaded', 'wpcom_liveblog_load', 999 );
788
8ff4206 Mohammad Jangda v1
mjangda authored
789 endif;
Something went wrong with that request. Please try again.