Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Weekend updates:

* Group WPCOM_Liveblog methods into logical groupings
* Add phpdoc and inline doc to liveblog.php
* Add templates for: form, loop, single entries
* Move classes into /classes folder
* Move templates into /templates folder
* Tweak liveblog styling, js, and mark-up
* Tweak UI animations
* Fix 'liveblog' comment_status, causing comments not to appear
  • Loading branch information...
commit 0a0ca28b36ed6c7167fab6e344f8c002278f183d 1 parent cd6d574
@johnjamesjacoby johnjamesjacoby authored
View
64 class-wpcom-liveblog-entry.php
@@ -1,64 +0,0 @@
-<?php
-
-class WPCOM_Liveblog_Entry {
- const default_avatar_size = 30;
- const replaces_meta_key = 'liveblog_replaces';
- private $comment;
-
- static function from_comment( $comment ) {
- $entry = new WPCOM_Liveblog_Entry( $comment );
- return $entry;
- }
-
- function __construct( $comment ) {
- $this->comment = $comment;
- $this->replaces = get_comment_meta( $comment->comment_ID, self::replaces_meta_key, true );
- }
-
- function get_id() {
- return $this->comment->comment_ID;
- }
-
- function get_timestamp() {
- return mysql2date( 'G', $this->comment->comment_date_gmt );
- }
-
- function for_json() {
- return (object)array(
- 'id' => $this->replaces? $this->replaces : $this->get_id(),
- 'html' => $this->render(),
- );
- }
-
- function render() {
- $output = '';
-
- // Allow plugins to override the output
- $output = apply_filters( 'liveblog_pre_entry_output', $output, $this );
- if ( $output )
- return $output;
-
- if ( !$this->comment->comment_content )
- return $output;
-
- $entry_id = $this->comment->comment_ID;
- $post_id = $this->comment->comment_post_ID;
- $css_classes = comment_class( '', $entry_id, $post_id, false );
- $comment_text = apply_filters( 'comment_text', get_comment_text( $entry_id ), $this->comment );
- $avatar_size = apply_filters( 'liveblog_entry_avatar_size', self::default_avatar_size );
- $avatar_img = get_avatar( $this->comment->comment_author_email, $avatar_size );
- $author_link = get_comment_author_link( $entry_id );
- $entry_time = sprintf( __( '%1$s at %2$s' ), get_comment_date( get_option( 'date_format' ), $entry_id ), get_comment_date( get_option( 'time_format' ), $entry_id ) );
-
- $can_edit_liveblog = WPCOM_Liveblog::current_user_can_edit_liveblog();
-
- ob_start();
- include dirname( __FILE__ ) . '/entry.tmpl.php';
- $output = ob_get_clean();
-
- $output = apply_filters( 'liveblog_entry_output', $output, $this );
-
- return $output;
- }
-
-}
View
48 class-wpcom-liveblog-entry-query.php → classes/class-wpcom-liveblog-entry-query.php
@@ -1,20 +1,22 @@
<?php
+
+
class WPCOM_Liveblog_Entry_Query {
function __construct( $post_id, $key ) {
$this->post_id = $post_id;
- $this->key = $key;
+ $this->key = $key;
}
private function get( $args = array() ) {
$defaults = array(
'post_id' => $this->post_id,
'orderby' => 'comment_date_gmt',
- 'order' => 'DESC',
- 'type' => $this->key,
- 'comment_approved' => $this->key,
+ 'order' => 'DESC',
+ 'type' => $this->key,
+ 'status' => 'approve',
);
- $args = array_merge( $defaults, $args );
+ $args = wp_parse_args( $defaults, $args );
$comments = get_comments( $args );
return self::entries_from_comments( $comments );
}
@@ -27,24 +29,26 @@ function get_latest() {
$entries = $this->get( array( 'number' => 1 ) );
if ( empty( $entries ) )
return null;
- reset( $entries );
- $first = current( $entries );
- return $first;
+
+ return current( reset( $entries ) );
}
function get_latest_timestamp() {
$latest = $this->get_latest();
- if ( is_null( $latest ) ) {
+ if ( is_null( $latest ) )
return null;
- }
- return $latest->get_timestamp();
+
+ if ( is_a( $latest, 'WPCOM_Liveblog_Entry' ) )
+ return $latest->get_timestamp();
+
+ return '0';
}
function get_between_timestamps( $start_timestamp, $end_timestamp ) {
- $all_entries = $this->get();
+ $all_entries = $this->get();
$entries_between = array();
- foreach( $all_entries as $entry ) {
+ foreach ( (array) $all_entries as $entry ) {
if ( $entry->get_timestamp() >= $start_timestamp && $entry->get_timestamp() <= $end_timestamp ) {
$entries_between[] = $entry;
}
@@ -54,31 +58,33 @@ function get_between_timestamps( $start_timestamp, $end_timestamp ) {
}
static function entries_from_comments( $comments ) {
- if ( !$comments ) {
+ if ( empty( $comments ) )
return null;
- }
- $entries = array_map( array( 'WPCOM_Liveblog_Entry', 'from_comment' ), $comments );
- return $entries;
+
+ return array_map( array( 'WPCOM_Liveblog_Entry', 'from_comment' ), $comments );
}
static function filter_event_entries( $entries ) {
- if ( !$entries ) {
+ if ( empty( $entries ) )
return $entries;
- }
+
$entries_by_id = self::key_by_get_id( $entries );
- foreach( $entries_by_id as $id => $entry ) {
+ foreach( (array) $entries_by_id as $id => $entry ) {
if ( $entry->replaces && isset( $entries_by_id[$entry->replaces] ) ) {
unset( $entries_by_id[$id] );
}
}
+
return $entries_by_id;
}
static function key_by_get_id( $entries ) {
$result = array();
- foreach( $entries as $entry ) {
+
+ foreach( (array) $entries as $entry ) {
$result[$entry->get_id()] = $entry;
}
+
return $result;
}
}
View
66 classes/class-wpcom-liveblog-entry.php
@@ -0,0 +1,66 @@
+<?php
+
+class WPCOM_Liveblog_Entry {
+ const default_avatar_size = 30;
+ const replaces_meta_key = 'liveblog_replaces';
+ private $comment;
+
+ public function __construct( $comment ) {
+ $this->comment = $comment;
+ $this->replaces = get_comment_meta( $comment->comment_ID, self::replaces_meta_key, true );
+ }
+
+ public static function from_comment( $comment ) {
+ $entry = new WPCOM_Liveblog_Entry( $comment );
+ return $entry;
+ }
+
+ public function get_id() {
+ return $this->comment->comment_ID;
+ }
+
+ public function get_timestamp() {
+ return mysql2date( 'G', $this->comment->comment_date_gmt );
+ }
+
+ public function for_json() {
+ return (object) array(
+ 'id' => $this->replaces ? $this->replaces : $this->get_id(),
+ 'html' => $this->render(),
+ );
+ }
+
+ public function render() {
+
+ // Allow plugins to override the output
+ $output = apply_filters( 'liveblog_pre_entry_output', '', $this );
+ if ( ! empty( $output ) )
+ return $output;
+
+ // Bail if content is empty
+ if ( empty( $this->comment->comment_content ) )
+ return $output;
+
+ // These variables are used in the liveblog-single-entry.php template
+ $entry_id = $this->comment->comment_ID;
+ $post_id = $this->comment->comment_post_ID;
+ $css_classes = comment_class( '', $entry_id, $post_id, false );
+ $comment_text = apply_filters( 'comment_text', get_comment_text( $entry_id ), $this->comment );
+ $avatar_size = apply_filters( 'liveblog_entry_avatar_size', self::default_avatar_size );
+ $avatar_img = get_avatar( $this->comment->comment_author_email, $avatar_size );
+ $author_link = get_comment_author_link( $entry_id );
+ $entry_time = get_comment_date( 'M j, Y - g:i:s A', $entry_id );
+ $can_edit_liveblog = WPCOM_Liveblog::current_user_can_edit_liveblog();
+
+ return WPCOM_Liveblog::get_template_part( 'liveblog-single-entry.php', compact(
+ 'post_id',
+ 'entry_id',
+ 'css_classes',
+ 'comment_text',
+ 'avatar_img',
+ 'author_link',
+ 'entry_time',
+ 'can_edit_liveblog'
+ ) );
+ }
+}
View
128 css/liveblog.css
@@ -1,17 +1,86 @@
-.liveblog-hidden {
- display: none;
+/* =Container
+-------------------------------------------------------------- */
+
+#liveblog-container {
+ margin: 10px 0;
+ width: 100%;
+ display: block;
+ position: relative;
+}
+
+/* =Form Actions
+-------------------------------------------------------------- */
+
+fieldset#liveblog-actions {
+ display: block;
+ padding: 5px 20px 20px 20px;
+ border-radius: 3px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border: 1px solid #ccc;
+ background: rgb(255,255,255); /* Old browsers */
+ background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(243,243,243,1) 33%, rgba(237,237,237,1) 34%, rgba(255,255,255,1) 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(33%,rgba(243,243,243,1)), color-stop(34%,rgba(237,237,237,1)), color-stop(100%,rgba(255,255,255,1))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(243,243,243,1) 33%,rgba(237,237,237,1) 34%,rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(243,243,243,1) 33%,rgba(237,237,237,1) 34%,rgba(255,255,255,1) 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(243,243,243,1) 33%,rgba(237,237,237,1) 34%,rgba(255,255,255,1) 100%); /* IE10+ */
+ background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(243,243,243,1) 33%,rgba(237,237,237,1) 34%,rgba(255,255,255,1) 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */
}
+fieldset#liveblog-actions legend {
+ padding: 5px;
+ background: transparent;
+}
+
+textarea#liveblog-form-entry {
+ display: inline-block;
+ background: #fff;
+ width: 98%;
+ height: 50px;
+ margin-bottom: 10px;
+ padding: 5px;
+ border-radius: 0;
+ -moz-border-radius: 0;
+ -webkit-border-radius: 0;
+ border: 1px solid #ddd;
+ -webkit-box-shadow: inset 1px 1px 1px 0px #f4f4f4;
+ -moz-box-shadow: inset 1px 1px 1px 0px #f4f4f4;
+ box-shadow: inset 1px 1px 1px 0px #f4f4f4;
+ outline-color: #acc;
+}
+
+#liveblog-actions div.liveblog-submit-wrapper {
+ text-align: right;
+ position: relative;
+}
+
+input#liveblog-form-entry-submit {
+ margin: 0;
+}
+
+span#liveblog-submit-spinner {
+ padding: 0;
+ position: absolute;
+ top: 50%;
+ right: 50%;
+}
+
+/* =Feedback and Nags
+-------------------------------------------------------------- */
+
.liveblog-message {
font: 13px "Helvetica Neue", sans-serif;
font-weight: 400;
- padding: 6px 10px;
+ padding: 7px 10px;
text-shadow: 1px 1px 0 #0074A2;
text-align: center;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
+ margin-bottom: 5px;
}
+
.liveblog-nag {
display: block;
cursor: pointer;
@@ -19,47 +88,58 @@
color: white;
}
+.liveblog-hidden {
+ display: none;
+}
+
+/* =Entry Container
+-------------------------------------------------------------- */
+
+#liveblog-entries {
+ display: block;
+ padding: 10px 0 0 0;
+}
+
.liveblog-loading {
color: #AAA;
background: #F9F9F9;
- border: 1px solid #EEE;
+ border: 1px solid #ddd;
}
-.liveblog-container {
- margin-top: 20px;
-}
+/* =Single Entry
+-------------------------------------------------------------- */
.liveblog-entry {
overflow: hidden;
- margin: 5px 0;
- padding: 5px 0;
- border-bottom: 1px dotted #ccc;
+ margin: 0;
+ padding: 10px 0 0 0;
+ border-top: 1px solid #eee;
}
.liveblog-entry-text {
font-size: 18px;
line-height: 22px;
- padding-bottom: 10px;
- }
-.liveblog-meta-time {
- display: block;
- font-size: 10px;
- line-height: 12px;
-}
- .liveblog-meta-time a {
- color: #888;
- text-decoration: none;
- text-transform: uppercase;
+ padding: 10px 0 0;
+ margin-left: 40px;
}
+
.liveblog-author-name {
- display: block;
font-size: 15px;
line-height: 18px;
}
+
.liveblog-author-avatar {
float: left;
margin: 0 10px 0 0;
}
-#liveblog-submit-spinner {
- margin-left: 16px;
+.liveblog-meta-time {
+ float: right;
+ margin-left: 10px;
+ font-size: 10px;
+ line-height: 12px;
}
+ .liveblog-meta-time a {
+ color: #888;
+ text-decoration: none;
+ text-transform: uppercase;
+ }
View
10 entry.tmpl.php
@@ -1,10 +0,0 @@
-<div id="liveblog-entry-<?php echo $entry_id ?>" <?php echo $css_classes ?>>
- <div class="liveblog-entry-text">
- <?php echo $comment_text ?>
- </div>
- <header class="liveblog-meta">
- <span class="liveblog-author-avatar"><?php echo $avatar_img ?></span>
- <span class="liveblog-author-name"><?php $author_link ?></span>
- <span class="liveblog-meta-time"><a href="#liveblog-entry-<?php echo $entry_id ?>"><?php echo $entry_time ?></a></span>
- </header>
-</div>
View
7 js/liveblog-publisher.js
@@ -8,10 +8,11 @@
liveblog.publisher.init = function() {
liveblog.disable_nag();
- liveblog.publisher.$entry_text = $( '#liveblog-form-entry' );
+ liveblog.publisher.$entry_text = $( '#liveblog-form-entry' );
liveblog.publisher.$entry_button = $( '#liveblog-form-entry-submit' );
- liveblog.publisher.$nonce = $( '#liveblog_nonce' );
- liveblog.publisher.$spinner = $( '#liveblog-submit-spinner' );
+ liveblog.publisher.$nonce = $( '#liveblog_nonce' );
+ liveblog.publisher.$spinner = $( '#liveblog-submit-spinner' );
+
liveblog.publisher.$entry_button.bind( 'click', liveblog.publisher.submit_click );
}
View
29 js/liveblog.js
@@ -3,8 +3,8 @@ var liveblog = {};
( function( $ ) {
liveblog.init = function() {
- liveblog.$entry_container = $( '.liveblog-entries' );
- liveblog.$spinner = $( '#liveblog-update-spinner' );
+ liveblog.$entry_container = $( '#liveblog-entries' );
+ liveblog.$spinner = $( '#liveblog-update-spinner' );
liveblog.cast_settings_numbers();
liveblog.reset_timer();
liveblog.set_initial_timestamps();
@@ -12,8 +12,8 @@ var liveblog = {};
liveblog.set_initial_timestamps = function() {
var now = liveblog.current_timestamp();
- liveblog.latest_entry_timestamp = liveblog_settings.latest_entry_timestamp;
- liveblog.latest_response_local_timestamp = now;
+ liveblog.latest_entry_timestamp = liveblog_settings.latest_entry_timestamp;
+ liveblog.latest_response_local_timestamp = now;
liveblog.latest_response_server_timestamp = now;
}
@@ -21,10 +21,10 @@ var liveblog = {};
// we need them to be real integers, so that we can use them in
// arithmetic operations
liveblog.cast_settings_numbers = function() {
- liveblog_settings.refresh_interval = parseInt( liveblog_settings.refresh_interval );
- liveblog_settings.max_retries = parseInt( liveblog_settings.max_retries );
- liveblog_settings.delay_threshold = parseInt( liveblog_settings.delay_threshold );
- liveblog_settings.delay_multiplier = parseFloat( liveblog_settings.delay_multiplier );
+ liveblog_settings.refresh_interval = parseInt( liveblog_settings.refresh_interval );
+ liveblog_settings.max_retries = parseInt( liveblog_settings.max_retries );
+ liveblog_settings.delay_threshold = parseInt( liveblog_settings.delay_threshold );
+ liveblog_settings.delay_multiplier = parseFloat( liveblog_settings.delay_multiplier );
liveblog_settings.latest_entry_timestamp = parseInt( liveblog_settings.latest_entry_timestamp );
}
@@ -124,6 +124,10 @@ var liveblog = {};
if ( !entries || !entries.length ) {
return;
}
+
+ if ( ! hidden_entries_count ) {
+ return;
+ }
if ( liveblog.is_nag_disabled() ) {
liveblog.unhide_entries();
@@ -140,7 +144,7 @@ var liveblog = {};
liveblog.$update_nag = $( '<div/>' );
liveblog.$update_nag
.addClass( 'liveblog-nag liveblog-message' )
- .hide();
+ .slideUp();
}
var nag_text = 1 < hidden_entries_count ? liveblog_settings.update_nag_plural : liveblog_settings.update_nag_singular;
@@ -151,7 +155,7 @@ var liveblog = {};
.prependTo( liveblog.$entry_container )
.one( 'click', function() {
liveblog.unhide_entries();
- $( this ).hide();
+ $( this ).slideUp();
document.title = liveblog.original_title;
} )
.slideDown();
@@ -182,12 +186,13 @@ var liveblog = {};
liveblog.add_entry = function( new_entry ) {
var $new_entry = $( new_entry.html );
- $new_entry.addClass( 'liveblog-hidden' ).prependTo( liveblog.$entry_container );
+ $new_entry.addClass( 'liveblog-hidden' ).prependTo( liveblog.$entry_container ).slideDown();
}
liveblog.update_entry = function( $entry, updated_entry ) {
var $updated_entry = $( updated_entry.html );
- var updated_text = $( '.liveblog-entry-text', $updated_entry ).html();
+ var updated_text = $( '.liveblog-entry-text', $updated_entry ).html();
+
if ( updated_text ) {
$( '.liveblog-entry-text', $entry ).html( updated_text );
} else {
View
525 liveblog.php
@@ -1,31 +1,39 @@
<?php
+
/**
* Plugin Name: Liveblog
* Description: Blogging: at the speed of live.
- * Version: 0.1
- * Author: WordPress.com VIP, Automattic
+ * Version: 0.1
+ * Author: WordPress.com VIP, Automattic
*/
-/*
-TODO (0.1):
--- Fix Batcache issues
-
-TODO (future):
--- PHP and JS Actions/Filters/Triggers
--- Change "Read More" to "View Liveblog"
--- Manual refresh button
--- Allow marking of liveblog as ended
--- Allow comment modifications; need to store modified date as comment_meta
--- Drag-and-drop image uploading support
-
-*/
-
-require( dirname( __FILE__ ) . '/class-wpcom-liveblog-entry.php' );
-require( dirname( __FILE__ ) . '/class-wpcom-liveblog-entry-query.php' );
-
if ( ! class_exists( 'WPCOM_Liveblog' ) ) :
-class WPCOM_Liveblog {
+/**
+ * The main Liveblog class used to setup everything this plugin needs.
+ *
+ * Liveblog currently uses a custom comment-type to circumvent post cache
+ * issues frequently experienced by other live-blog implimentations. It comes
+ * with a simple and effective templating mechanism, complete with all of the
+ * CSS, JS, and AJAX needed to make this a turn-key installation.
+ *
+ * This class is a big container for a bunch of static methods, similar to a
+ * factory but without object inheritance or instantiation.
+ *
+ * Things yet to be implimented:
+ *
+ * -- PHP and JS Actions/Filters/Triggers
+ * -- Change "Read More" to "View Liveblog"
+ * -- Manual refresh button
+ * -- Allow marking of liveblog as ended
+ * -- Allow comment modifications; need to store modified date as comment_meta
+ * -- Drag-and-drop image uploading support
+ *
+ * @todo more batcache testing
+ */
+final class WPCOM_Liveblog {
+
+ /** Constants *************************************************************/
const version = 0.1;
const key = 'liveblog';
@@ -38,78 +46,189 @@ class WPCOM_Liveblog {
const delay_threshold = 10; // how many failed tries after which we should increase the refresh interval
const delay_multiplier = 1.5; // by how much should we inscrease the refresh interval
- static $post_id = null;
- static $entry_query = null;
- static $do_not_cache_response = false;
+ /** Variables *************************************************************/
+
+ private static $post_id = null;
+ private static $entry_query = null;
+ private static $do_not_cache_response = false;
- function load() {
+ /** Load Methods **********************************************************/
+
+ /**
+ * @uses add_action() to hook methods into WordPress actions
+ * @uses add_filter() to hook methods into WordPress filters
+ */
+ public static function load() {
+ self::includes();
+ self::add_actions();
+ self::add_filters();
+ self::add_admin_actions();
+ }
+
+ /**
+ * Include the necessary files
+ */
+ private static function includes() {
+ require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry.php' );
+ require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry-query.php' );
+ }
- // Actions
+ /**
+ * Hook actions in that run on every page-load
+ *
+ * @uses add_action()
+ */
+ private static function add_actions() {
add_action( 'init', array( __CLASS__, 'init' ) );
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
add_action( 'wp_ajax_liveblog_insert_entry', array( __CLASS__, 'ajax_insert_entry' ) );
- add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_box' ) );
- add_action( 'save_post', array( __CLASS__, 'save_meta_box' ) );
+ }
- // Filters
+ /**
+ * Hook filters in that run on every page-load
+ *
+ * @uses add_filter()
+ */
+ private static function add_filters() {
add_filter( 'template_redirect', array( __CLASS__, 'handle_request' ) );
add_filter( 'comment_class', array( __CLASS__, 'add_comment_class' ) );
}
/**
+ * Hook actions in that run on every admin page-load
+ *
+ * @uses add_action()
+ * @uses is_admin()
+ */
+ private static function add_admin_actions() {
+
+ // Bail if not in admin area
+ if ( ! is_admin() )
+ return;
+
+ add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_box' ) );
+ add_action( 'save_post', array( __CLASS__, 'save_meta_box' ) );
+ }
+
+ /** Public Methods ********************************************************/
+
+ /**
+ * Liveblog initialization functions.
+ *
+ * This is where Liveblog sets up any additional things it needs to run
+ * inside of WordPress. Where some plugins would register post types or
+ * taxonomies, we modify endpoints and add post type support for Liveblog.
+ *
* @todo filters for time and interval overrides
*/
- function init() {
- // /2012/01/01/post-name/liveblog/123456/ where 123456 is a timestamp
+ public static function init() {
+
+ /**
+ * Add a WordPress rewrite-rule enpoint.
+ *
+ * Looks like: /2012/01/01/post-name/liveblog/123456/
+ *
+ * where 123456 is a timestamp
+ */
add_rewrite_endpoint( self::url_endpoint, EP_PERMALINK );
+
+ /**
+ * Add liveblog support to the 'post' post type. This is done here so
+ * we can possibly introduce this to other post types later.
+ */
add_post_type_support( 'post', self::key );
}
- function handle_request( $query ) {
+ /**
+ * This is where a majority of the magic happens.
+ *
+ * Hooked to template_redirect, this method tries to add anything it can to
+ * the current post output. If nothing needs to be added, we redirect back
+ * to the permalink.
+ *
+ * @return If request has been handled
+ */
+ public static function handle_request() {
+
+ // Bail if not a liveblog post
if ( ! self::is_viewing_liveblog_post() )
return;
+ // Set the some useful bits based on the request
self::$post_id = get_the_ID();
self::$entry_query = new WPCOM_Liveblog_Entry_Query( self::$post_id, self::key );
+ /**
+ * If this is the first time this page is being requested, we know we
+ * need to add all of the liveblog updates to the top of the post.
+ *
+ * Once we've added them, bail.
+ */
if ( self::is_initial_page_request() ) {
add_filter( 'the_content', array( __CLASS__, 'add_liveblog_to_content' ) );
return;
}
+ /**
+ * If this is an ajax request to update the entries, call the method
+ * responsible for updating entries between now and the last time they
+ * were successfully returned.
+ *
+ * Once we've added them, bail.
+ */
if ( self::is_entries_ajax_request() ) {
self::ajax_entries_between();
return;
}
+ // We haven't needed to do anything, so redirect back to the permalink
wp_safe_redirect( get_permalink() );
- exit;
+ exit();
}
- function ajax_entries_between() {
+ /**
+ * Look for any new Liveblog entries, and return them via JSON
+ */
+ public static function ajax_entries_between() {
+
+ // Set some defaults
$current_timestamp = time();
$latest_timestamp = 0;
$entries_for_json = array();
+ // Look for entry boundaries
list( $start_timestamp, $end_timestamp ) = self::get_timestamps_from_query();
+ // Bail if there is no end timestamp
if ( empty( $end_timestamp ) ) {
wp_safe_redirect( get_permalink() );
- die;
+ die();
}
+ // Do not cache if it's too soon
if ( $end_timestamp > $current_timestamp )
self::$do_not_cache_response = true;
+ // Get liveblog entries within the start and end boundaries
$entries = self::$entry_query->get_between_timestamps( $start_timestamp, $end_timestamp );
- if ( empty( $entries ) )
- self::json_return( array( 'entries' => array(), 'current_timestamp' => $current_timestamp, 'latest_timestamp' => null ) );
+ if ( empty( $entries ) ) {
+ self::json_return( array(
+ 'entries' => array(),
+ 'current_timestamp' => $current_timestamp,
+ 'latest_timestamp' => null
+ ) );
+ }
+ /**
+ * Loop through each liveblog entry, set the most recent timestamp, and
+ * put the JSON data for each entry into a neat little array.
+ */
foreach( $entries as $entry ) {
$latest_timestamp = max( $latest_timestamp, $entry->get_timestamp() );
$entries_for_json[] = $entry->for_json();
}
+ // Setup our data to return via JSON
$result_for_json = array(
'entries' => $entries_for_json,
'current_timestamp' => $current_timestamp,
@@ -119,31 +238,92 @@ function ajax_entries_between() {
self::json_return( $result_for_json );
}
- function is_viewing_liveblog_post() {
- return is_single() && self::is_liveblog_post();
+ /** Private _is_ Methods **************************************************/
+
+ /**
+ * Are we viewing a liveblog post?
+ *
+ * @uses is_single()
+ * @uses is_liveblog_post()
+ * @return bool
+ */
+ private static function is_viewing_liveblog_post() {
+ return (bool) ( is_single() && self::is_liveblog_post() );
}
- function is_initial_page_request() {
+ /**
+ * Is this the initial page request?
+ *
+ * Note that we do not use get_query_var() - it returns '' for all requests,
+ * which is valid for /post-name/liveblog/
+ *
+ * @global WP_Query $wp_query
+ * @return bool
+ */
+ private static function is_initial_page_request() {
global $wp_query;
- // Not using get_query_var since it returns '' for all requests, which is a valid for /post-name/liveblog/
- return ! isset( $wp_query->query_vars['liveblog'] );
+
+ return (bool) ! isset( $wp_query->query_vars[self::key] );
}
+ /**
+ * Is this an ajax request for the entries?
+ *
+ * @uses get_query_var() to check for the url_endpoint
+ * @return bool
+ */
+ private static function is_entries_ajax_request() {
+ return (bool) get_query_var( self::url_endpoint );
+ }
- function is_entries_ajax_request() {
- return (bool)get_query_var( self::url_endpoint );
+ /**
+ * Is a given post_id a liveblog enabled post?
+ *
+ * @global WP_Post $post
+ * @param int $post_id
+ * @return bool
+ */
+ private static function is_liveblog_post( $post_id = null ) {
+ if ( empty( $post_id ) ) {
+ global $post;
+ $post_id = $post->ID;
+ }
+
+ return (bool) get_post_meta( $post_id, self::key, true );
}
- function get_timestamps_from_query() {
- $timestamps = explode( '/', get_query_var( self::url_endpoint) );
- if ( 2 != count( $timestamps ) ) {
+ /**
+ * Get timestamps from the current WP_Query
+ *
+ * Ensures that two timestamps exist, and returns a properly formatted empty
+ * array if not.
+ *
+ * @return array
+ */
+ private static function get_timestamps_from_query() {
+
+ // Look for timestamps and bail if none
+ $stamps = get_query_var( self::url_endpoint );
+ if ( empty( $stamps ) )
return array( false, false );
- }
- $timestamps = array_map( 'intval', $timestamps );
- return $timestamps;
+
+ // Get timestamps from the query variable
+ $timestamps = explode( '/', $stamps );
+
+ // Bail if there are not 2 timestamps
+ if ( 2 !== count( $timestamps ) )
+ return array( false, false );
+
+ // Return integer timestamps in an array
+ return array_map( 'intval', $timestamps );
}
- function ajax_insert_entry() {
+ /**
+ * Inserts, updates, or deletes a liveblog entry
+ *
+ * @todo break update/delete off into separate methods
+ */
+ public static function ajax_insert_entry() {
// Capability and Intention Checks
self::ajax_current_user_can_edit_liveblog();
@@ -164,7 +344,7 @@ function ajax_insert_entry() {
$new_comment_id = wp_insert_comment( array(
'comment_post_ID' => $post_id,
'comment_content' => $entry_content,
- 'comment_approved' => self::key,
+ 'comment_approved' => 1,
'comment_type' => self::key,
'user_id' => $user->ID,
@@ -213,36 +393,53 @@ function ajax_insert_entry() {
) );
}
- function entry_output( $entry ) {
- }
+ /** Comment Methods *******************************************************/
- function add_comment_class( $classes ) {
+ /**
+ * Add a liveblog class to each comment, so they can be styled
+ *
+ * @param array $classes
+ * @return string
+ */
+ public static function add_comment_class( $classes ) {
$classes[] = 'liveblog-entry';
return $classes;
}
- function enqueue_scripts() {
+ /**
+ * Enqueue the necessary CSS and JS that liveblog needs to function.
+ *
+ * @return If not a liveblog post
+ */
+ public static function enqueue_scripts() {
+
+ // Bail if not a liveblog post
if ( ! self::is_viewing_liveblog_post() )
return;
// Styling
- wp_enqueue_style( 'liveblog', plugins_url( 'css/liveblog.css', __FILE__ ) );
+ wp_enqueue_style( self::key, plugins_url( 'css/liveblog.css', __FILE__ ) );
// Scripts
- wp_enqueue_script( 'liveblog', plugins_url( 'js/liveblog.js', __FILE__ ), array( 'jquery' ), self::version, true );
+ wp_enqueue_script( self::key, plugins_url( 'js/liveblog.js', __FILE__ ), array( 'jquery' ), self::version, true );
+ // Only for users that can publish liveblog content
if ( self::current_user_can_edit_liveblog() ) {
- wp_enqueue_script( 'liveblog-publisher', plugins_url( 'js/liveblog-publisher.js', __FILE__ ), array( 'liveblog' ), self::version, true );
+ wp_enqueue_script( 'liveblog-publisher', plugins_url( 'js/liveblog-publisher.js', __FILE__ ), array( self::key ), self::version, true );
}
+ // Use the WordPress core jQuery spinner plugin
if ( wp_script_is( 'jquery.spin', 'registered' ) ) {
wp_enqueue_script( 'jquery.spin' );
+
+ // Use the bundled jQuery spinner plugin
} else {
- wp_enqueue_script( 'spin', plugins_url( 'js/spin.js', __FILE__ ), false, '1.2.4' );
- wp_enqueue_script( 'jquery.spin', plugins_url( 'js/jquery.spin.js', __FILE__ ), array( 'jquery', 'spin' ) );
+ wp_enqueue_script( 'spin', plugins_url( 'js/spin.js', __FILE__ ), false, '1.2.4' );
+ wp_enqueue_script( 'jquery.spin', plugins_url( 'js/jquery.spin.js', __FILE__ ), array( 'jquery', 'spin' ) );
}
- wp_localize_script( 'liveblog', 'liveblog_settings',
+ // Localize some script variables
+ wp_localize_script( self::key, 'liveblog_settings',
apply_filters( 'liveblog_settings', array(
'permalink' => get_permalink(),
'post_id' => get_the_ID(),
@@ -260,61 +457,103 @@ function enqueue_scripts() {
'entriesurl' => self::get_entries_endpoint_url(),
// i18n
- 'update_nag_singular' => __( '%d new update', 'liveblog' ),
+ 'update_nag_singular' => __( '%d new update', 'liveblog' ),
'update_nag_plural' => __( '%d new updates', 'liveblog' ),
) )
);
}
- function add_liveblog_to_content( $content ) {
- $entries = self::$entry_query->get_all( array( 'order' => 'ASC' ) );
- $entries = array_reverse( $entries );
+ /**
+ * Get the URL of a specific liveblog entry.
+ *
+ * @return string
+ */
+ private static function get_entries_endpoint_url() {
+ return trailingslashit( get_permalink( self::$post_id ) . self::url_endpoint );
+ }
- $liveblog_output = '';
- $liveblog_output .= '<div id="liveblog-'. self::$post_id .'" class="liveblog-container">';
- $liveblog_output .= '<div id="liveblog-update-spinner"></div>';
- $liveblog_output .= '<div class="liveblog-actions">';
- $liveblog_output .= self::get_entry_editor_output();
- $liveblog_output .= '</div>';
- $liveblog_output .= '<div class="liveblog-entries">';
+ /** Display Methods *******************************************************/
- foreach ( (array) $entries as $entry )
- $liveblog_output .= $entry->render();
+ /**
+ * Filter the_content and add the liveblog theme-side UI above the normal
+ * content area.
+ *
+ * @param string $content
+ * @return string
+ */
+ public static function add_liveblog_to_content( $content ) {
- $liveblog_output .= '</div>';
+ $liveblog_output = '<div id="liveblog-container" class="'. self::$post_id .'">';
+ $liveblog_output .= self::get_editor_output();
+ $liveblog_output .= '<div id="liveblog-update-spinner"></div>';
+ $liveblog_output .= self::get_all_entry_output();
$liveblog_output .= '</div>';
- return $content . $liveblog_output;
+ return $liveblog_output . $content;
}
- function get_entry_editor_output() {
+ /**
+ * Return the posting area for the end-user to liveblog from
+ *
+ * @return string
+ */
+ private static function get_editor_output() {
if ( ! self::current_user_can_edit_liveblog() )
return;
- $editor_output = '';
- $editor_output .= '<textarea id="liveblog-form-entry" name="liveblog-form-entry"></textarea>';
- $editor_output .= '<input type="button" id="liveblog-form-entry-submit" class="button" value="'. esc_attr__( 'Post Update' ) . '" />';
- $editor_output .= '<span id="liveblog-submit-spinner"></span>';
- $editor_output .= wp_nonce_field( self::nonce_key, self::nonce_key, false, false );
-
- return $editor_output;
+ // Get the template part
+ return self::get_template_part( 'liveblog-form.php' );
}
+ /**
+ * Get all the liveblog entries for this post
+ */
+ private static function get_all_entry_output() {
+
+ // Get liveblog entries
+ $entries = (array) self::$entry_query->get_all( array( 'order' => 'ASC' ) );
- function is_liveblog_post( $post_id = null ) {
- if ( empty( $post_id ) ) {
- global $post;
- $post_id = $post->ID;
- }
- return get_post_meta( $post_id, self::key, true );
+ // Get the template part
+ return self::get_template_part( 'liveblog-loop.php', compact( 'entries' ) );
+ }
+
+ /**
+ * Get the template part in an output buffer and return it
+ *
+ * @param string $template_name
+ * @param array $template_variables
+ *
+ * @todo Rudementary part/child theme file_exists() checks
+ */
+ public static function get_template_part( $template_name, $template_variables = array() ) {
+ ob_start();
+ extract( $template_variables );
+ include( dirname( __FILE__ ) . '/templates/' . $template_name );
+ return ob_get_clean();
}
+
+ /** Admin Methods *********************************************************/
+
+ /**
+ * Register the metabox with the supporting post-type
+ *
+ * @param string $post_type
+ */
+ public static function add_meta_box( $post_type ) {
+
+ // Bail if not supported
+ if ( ! post_type_supports( $post_type, self::key ) )
+ return;
- function add_meta_box( $post_type ) {
- if ( post_type_supports( $post_type, self::key ) )
- add_meta_box( self::key, __( 'Liveblog', 'liveblog' ), array( __CLASS__, 'display_meta_box' ) );
+ add_meta_box( self::key, __( 'Liveblog', 'liveblog' ), array( __CLASS__, 'display_meta_box' ) );
}
- function display_meta_box( $post ) {
+ /**
+ * Output the metabox
+ *
+ * @param WP_Post $post
+ */
+ public static function display_meta_box( $post ) {
?>
<label>
@@ -322,39 +561,81 @@ function display_meta_box( $post ) {
<?php esc_html_e( 'This is a liveblog', 'liveblog' ); ?>
</label>
- <?php
- wp_nonce_field( 'liveblog_nonce', 'liveblog_nonce', false );
+ <?php
+ wp_nonce_field( self::nonce_key, self::nonce_key, false );
}
- function save_meta_box( $post_id ) {
- if ( ! isset( $_POST['liveblog_nonce'] ) || ! wp_verify_nonce( $_POST['liveblog_nonce'], 'liveblog_nonce' ) )
+
+ /**
+ * Save the metabox when the post is saved
+ *
+ * @param type $post_id
+ * @return type
+ */
+ public function save_meta_box( $post_id ) {
+
+ // Bail if no liveblog nonce
+ if ( empty( $_POST[self::nonce_key] ) || ! wp_verify_nonce( $_POST[self::nonce_key], self::nonce_key ) )
return;
- if ( isset( $_POST['is-liveblog'] ) )
+ // Update liveblog beta
+ if ( ! empty( $_POST['is-liveblog'] ) )
update_post_meta( $post_id, self::key, 1 );
+
+ // Delete liveblog meta
else
delete_post_meta( $post_id, self::key );
}
- function get_entries_endpoint_url() {
- return trailingslashit( get_permalink( self::$post_id ) . self::url_endpoint );
+ /** Error Methods *********************************************************/
+
+ /**
+ * Can the current user edit liveblog data (non-ajax)
+ *
+ * @return bool
+ */
+ public static function current_user_can_edit_liveblog() {
+ return (bool) current_user_can( apply_filters( 'liveblog_edit_cap', self::edit_cap ) );
}
- function ajax_current_user_can_edit_liveblog() {
+ /**
+ * Can the current user edit liveblog data (ajax)
+ *
+ * Sends an error if not
+ */
+ public static function ajax_current_user_can_edit_liveblog() {
if ( ! self::current_user_can_edit_liveblog() ) {
self::send_error( __( "Cheatin', uh?", 'liveblog' ) );
}
}
- function current_user_can_edit_liveblog() {
- return current_user_can( apply_filters( 'liveblog_edit_cap', self::edit_cap ) );
- }
- function ajax_check_nonce( $action = 'liveblog_nonce' ) {
+ /**
+ * Check for valid intention, and send an error if there is none
+ *
+ * @param string $action
+ */
+ public static function ajax_check_nonce( $action = self::nonce_key ) {
if ( ! isset( $_REQUEST[ self::nonce_key ] ) || ! wp_verify_nonce( $_REQUEST[ self::nonce_key ], $action ) ) {
self::send_error( __( 'Sorry, we could not authenticate you.', 'liveblog' ) );
}
}
- function json_return( $data ) {
+ /** Feedback **************************************************************/
+
+ /**
+ * Send an error message
+ * @param type $message
+ */
+ private static function send_error( $message ) {
+ self::status_header_with_message( 500, $message );
+ exit();
+ }
+
+ /**
+ * Encode some data and echo it (possibly without cached headers)
+ *
+ * @param array $data
+ */
+ private static function json_return( $data ) {
$json_data = json_encode( $data );
header( 'Content-Type: application/json' );
@@ -362,15 +643,17 @@ function json_return( $data ) {
nocache_headers();
echo $json_data;
- exit;
- }
-
- function send_error( $message ) {
- self::status_header_with_message( 500, $message );
- exit;
+ exit();
}
- function status_header_with_message( $status, $message ) {
+ /**
+ * Modify the header and description in the global array
+ *
+ * @global array $wp_header_to_desc
+ * @param int $status
+ * @param string $message
+ */
+ private static function status_header_with_message( $status, $message ) {
global $wp_header_to_desc;
$status = absint( $status );
@@ -383,5 +666,17 @@ function status_header_with_message( $status, $message ) {
}
}
-WPCOM_Liveblog::load();
+/**
+ * Load the one true WPCOM_Liveblog instance
+ *
+ * Loaded late on the 'plugins_loaded' hook to allow any other plugin to sneak
+ * in ahead of it, to add actions, filters, etc...
+ *
+ * @uses WPCOM_Liveblog::load()
+ */
+function wpcom_liveblog_load() {
+ WPCOM_Liveblog::load();
+}
+add_action( 'plugins_loaded', 'wpcom_liveblog_load', 999 );
+
endif;
View
6 t/test-entry-query.php
@@ -84,9 +84,9 @@ function test_filter_event_entries_should_not_remove_entries_replacing_non_exist
private function create_comment( $args = array() ) {
$defaults = array(
- 'comment_post_ID' => $this->entry_query->post_id,
- 'comment_approved' => $this->entry_query->key,
- 'comment_type' => $this->entry_query->key,
+ 'comment_post_ID' => $this->entry_query->post_id,
+ 'comment_approved' => 'approve',
+ 'comment_type' => $this->entry_query->key,
);
$args = array_merge( $defaults, $args );
// TODO: addslashes deep
View
9 templates/liveblog-form.php
@@ -0,0 +1,9 @@
+<fieldset id="liveblog-actions">
+ <legend><?php _e( "You're Live!", 'liveblog' ); ?></legend>
+ <textarea placeholder="<?php _e( 'Remember: keep it short!', 'liveblog' ); ?>" id="liveblog-form-entry" name="liveblog-form-entry" cols="50" rows="5"></textarea>
+ <div class="liveblog-submit-wrapper">
+ <span id="liveblog-submit-spinner"></span>
+ <input type="button" id="liveblog-form-entry-submit" class="button" value="<?php echo esc_attr__( 'Publish Update', 'liveblog' ); ?>" />
+ <?php echo wp_nonce_field( self::nonce_key, self::nonce_key, false, false ); ?>
+ </div>
+</fieldset>
View
9 templates/liveblog-loop.php
@@ -0,0 +1,9 @@
+<div id="liveblog-entries">
+
+ <?php foreach ( (array) array_reverse( $entries ) as $entry ) : ?>
+
+ <?php echo $entry->render(); ?>
+
+ <?php endforeach; ?>
+
+</div>
View
10 templates/liveblog-single-entry.php
@@ -0,0 +1,10 @@
+<div id="liveblog-entry-<?php echo $entry_id; ?>" <?php echo $css_classes; ?>>
+ <header class="liveblog-meta">
+ <span class="liveblog-author-avatar"><?php echo $avatar_img; ?></span>
+ <span class="liveblog-author-name"><?php echo $author_link; ?></span>
+ <span class="liveblog-meta-time"><a href="#liveblog-entry-<?php echo $entry_id; ?>"><?php echo $entry_time; ?></a></span>
+ </header>
+ <div class="liveblog-entry-text">
+ <?php echo $comment_text; ?>
+ </div>
+</div>
Please sign in to comment.
Something went wrong with that request. Please try again.