diff --git a/classes/connector.php b/classes/connector.php index 2ae48b4aa..85dbf71cc 100644 --- a/classes/connector.php +++ b/classes/connector.php @@ -42,7 +42,7 @@ public static function register() { /** * Callback for all registered hooks throughout Stream * Looks for a class method with the convention: "callback_{action name}" - * + * * @return void */ public static function callback() { @@ -52,6 +52,11 @@ public static function callback() { //For the sake of testing, trigger an action with the name of the callback if ( defined( 'STREAM_TESTS' ) ) { + /** + * Action fires during testing to test the current callback + * + * @param array $callback Callback name + */ do_action( 'stream_test_' . $callback[1] ); } @@ -96,6 +101,14 @@ public static function is_logging_enabled_for_user( $user = null ) { $bool = ! ( count( array_intersect( $user_roles, $roles_logged ) ) === 0 ); } + /** + * Filter sets boolean result value for this method + * + * @param bool + * @param obj $user Current user object + * @param string Current class name + * @return bool + */ return apply_filters( 'wp_stream_record_log', $bool, $user, get_called_class() ); } diff --git a/connectors/posts.php b/connectors/posts.php index 786bcadf7..488786948 100644 --- a/connectors/posts.php +++ b/connectors/posts.php @@ -63,8 +63,8 @@ public static function get_context_labels() { public static function action_links( $links, $record ) { if ( get_post( $record->object_id ) ) { if ( $link = get_edit_post_link( $record->object_id ) ) { - $post_type = get_post_type_object( get_post_type( $record->object_id ) ); - $links[ sprintf( __( 'Edit %s', 'stream' ), $post_type->labels->singular_name ) ] = $link; + $post_type_name = self::get_post_type_name( get_post_type( $record->object_id ) ); + $links[ sprintf( __( 'Edit %s', 'stream' ), $post_type_name ) ] = $link; } if ( post_type_exists( get_post_type( $record->object_id ) ) && $link = get_permalink( $record->object_id ) ) { $links[ __( 'View', 'stream' ) ] = $link; @@ -135,13 +135,13 @@ public static function callback_transition_post_status( $new, $old, $post ) { } } - $post_type = get_post_type_object( $post->post_type ); + $post_type_name = strtolower( self::get_post_type_name( $post->post_type ) ); self::log( $message, array( 'post_title' => $post->post_title, - 'singular_name' => strtolower( $post_type->labels->singular_name ), + 'singular_name' => $post_type_name, 'new_status' => $new, 'old_status' => $old, 'revision_id' => $revision_id, @@ -166,13 +166,13 @@ public static function callback_deleted_post( $post_id ) { return; } - $post_type = get_post_type_object( $post->post_type ); + $post_type_name = strtolower( self::get_post_type_name( $post->post_type ) ); self::log( __( '"%s" %s deleted from trash', 'stream' ), array( 'post_title' => $post->post_title, - 'singular_name' => strtolower( $post_type->labels->singular_name ), + 'singular_name' => $post_type_name, ), $post->ID, array( @@ -181,6 +181,11 @@ public static function callback_deleted_post( $post_id ) { ); } + /** + * Constructs list of ignored post types for the post connector + * + * @return array List of ignored post types + */ public static function get_ignored_post_types() { return apply_filters( 'wp_stream_post_exclude_post_types', @@ -192,4 +197,14 @@ public static function get_ignored_post_types() { ); } + private static function get_post_type_name( $post_type_slug ) { + if ( post_type_exists( $post_type_slug ) ) { + $post_type = get_post_type_object( $post_type_slug ); + $name = $post_type->labels->singular_name; + } else { + $name = __( 'Post', 'stream' ); + } + return $name; + } + } diff --git a/connectors/settings.php b/connectors/settings.php index 06e875d86..ded44c716 100644 --- a/connectors/settings.php +++ b/connectors/settings.php @@ -183,6 +183,12 @@ public static function get_serialized_field_label( $option_name, $field_key ) { // to be updated ); + /** + * Filter allows for insertion of serialized labels + * + * @param array $lables Serialized labels + * @return array Updated array of serialzed labels + */ $labels = apply_filters( 'wp_stream_serialized_labels', $labels ); if ( isset( $labels[$option_name] ) && isset( $labels[$option_name][$field_key] ) ) { @@ -276,6 +282,11 @@ public static function callback_update_option_tag_base( $old_value, $value ) { */ public static function callback_updated_option( $option, $old_value, $value ) { global $new_whitelist_options, $whitelist_options; + + if ( 0 === strpos( $option, '_transient_' ) ) { + return; + } + $options = array_merge( (array) $whitelist_options, $new_whitelist_options, @@ -311,18 +322,15 @@ public static function callback_updated_option( $option, $old_value, $value ) { } } - $changed_options = array_map( - function( $field_key ) use ( $current_key, $value, $old_value ) { - return array( - 'label' => self::get_serialized_field_label( $current_key, $field_key ), - 'option' => $current_key, - // Prevent fatal error when saving option as array - 'old_value' => isset( $old_value[$field_key] ) ? maybe_serialize( $old_value[$field_key] ) : null, - 'value' => isset( $value[$field_key] ) ? maybe_serialize( $value[$field_key] ) : null, - ); - }, - $changed_keys - ); + foreach ( $changed_keys as $field_key ) { + $changed_options[] = array( + 'label' => self::get_serialized_field_label( $current_key, $field_key ), + 'option' => $current_key, + // Prevent fatal error when saving option as array + 'old_value' => isset( $old_value[$field_key] ) ? maybe_serialize( $old_value[$field_key] ) : null, + 'value' => isset( $value[$field_key] ) ? maybe_serialize( $value[$field_key] ) : null, + ); + } } else { $changed_options[] = array( 'label' => self::get_field_label( $option ), diff --git a/connectors/taxonomies.php b/connectors/taxonomies.php index 0267d60ab..9958f4f0c 100644 --- a/connectors/taxonomies.php +++ b/connectors/taxonomies.php @@ -90,8 +90,10 @@ public static function get_context_labels() { */ public static function action_links( $links, $record ) { if ( $record->object_id && $record->action != 'deleted' && ( $term = get_term( $record->object_id, $record->context ) ) ) { - $links[ __( 'Edit', 'stream' ) ] = get_edit_term_link( $record->object_id, $record->context ); - $links[ __( 'View', 'stream' ) ] = get_term_link( get_term( $record->object_id, $record->context ) ); + if ( ! is_wp_error( $term ) ) { + $links[ __( 'Edit', 'stream' ) ] = get_edit_term_link( $record->object_id, $record->context ); + $links[ __( 'View', 'stream' ) ] = get_term_link( get_term( $record->object_id, $record->context ) ); + } } return $links; } diff --git a/connectors/widgets.php b/connectors/widgets.php index 9d00b81fd..b580c7f4e 100644 --- a/connectors/widgets.php +++ b/connectors/widgets.php @@ -307,6 +307,13 @@ public static function get_widget_settings( $id ) { * @return array */ public static function get_sidebar_widgets() { + /** + * Filter allows for insertion of sidebar widgets + * + * @param array Sidebar Widgets in Options table + * @param array Inserted Sidebar Widgets + * @return array Array of updated Sidebar Widgets + */ return apply_filters( 'sidebars_widgets', get_option( 'sidebars_widgets', array() ) ); } diff --git a/includes/admin.php b/includes/admin.php index 4fcf27824..8feae3d03 100644 --- a/includes/admin.php +++ b/includes/admin.php @@ -15,12 +15,13 @@ class WP_Stream_Admin { */ public static $list_table = null; - const ADMIN_BODY_CLASS = 'wp_stream_screen'; - const RECORDS_PAGE_SLUG = 'wp_stream'; - const SETTINGS_PAGE_SLUG = 'wp_stream_settings'; - const ADMIN_PARENT_PAGE = 'admin.php'; - const VIEW_CAP = 'view_stream'; - const SETTINGS_CAP = 'manage_options'; + const ADMIN_BODY_CLASS = 'wp_stream_screen'; + const RECORDS_PAGE_SLUG = 'wp_stream'; + const SETTINGS_PAGE_SLUG = 'wp_stream_settings'; + const ADMIN_PARENT_PAGE = 'admin.php'; + const VIEW_CAP = 'view_stream'; + const SETTINGS_CAP = 'manage_options'; + const PRELOAD_AUTHORS_MAX = 50; public static function load() { // User and role caps @@ -62,6 +63,12 @@ public static function load() { // Enable/Disable live update per user add_action( 'wp_ajax_stream_enable_live_update', array( __CLASS__, 'enable_live_update' ) ); + // Ajax authors list + add_action( 'wp_ajax_wp_stream_filters', array( __CLASS__, 'ajax_filters' ) ); + + // Ajax author's name by ID + add_action( 'wp_ajax_wp_stream_get_author_name_by_id', array( __CLASS__, 'get_author_name_by_id' ) ); + } /** @@ -328,7 +335,7 @@ public static function wp_ajax_reset() { ); exit; } else { - wp_die( "You don't have sufficient priviledges to do this action." ); + wp_die( "You don't have sufficient privileges to do this action." ); } } @@ -693,4 +700,54 @@ public static function enable_live_update() { } } + /** + * @action wp_ajax_wp_stream_filters + */ + public static function ajax_filters() { + switch ( $_REQUEST['filter'] ) { + case 'author': + $results = array_map( + function( $user ) { + return array( + 'id' => $user->id, + 'text' => $user->display_name, + ); + }, + get_users() + ); + break; + } + + // `search` arg for get_users() is not enough + $results = array_filter( + $results, + function( $result ) { + return mb_strpos( mb_strtolower( $result['text'] ), mb_strtolower( $_REQUEST['q'] ) ) !== false; + } + ); + + $results_count = count( $results ); + + if ( $results_count > self::PRELOAD_AUTHORS_MAX ) { + $results = array_slice( $results, 0, self::PRELOAD_AUTHORS_MAX ); + $results[] = array( + 'id' => 0, + 'disabled' => true, + 'text' => sprintf( _n( 'One more result...', '%d more results...', $results_count - self::PRELOAD_AUTHORS_MAX, 'stream' ), $results_count - self::PRELOAD_AUTHORS_MAX ), + ); + } + + echo json_encode( array_values( $results ) ); + die(); + } + + /** + * @action wp_ajax_wp_stream_get_author_name_by_id + */ + public static function get_author_name_by_id() { + $user = get_userdata( $_REQUEST['id'] ); + echo json_encode( $user->display_name ); + die(); + } + } diff --git a/includes/connectors.php b/includes/connectors.php index cdc9f7f6a..924267cf3 100644 --- a/includes/connectors.php +++ b/includes/connectors.php @@ -33,6 +33,14 @@ public static function load() { $classes[] = "WP_Stream_Connector_$class"; } } + + /** + * Filter allows for adding additional connectors via classes that extend + * WP_Stream_Connector + * + * @param array Connector Class names + * @return array Updated Array of Connector Class names + */ self::$connectors = apply_filters( 'wp_stream_connectors', $classes ); foreach ( self::$connectors as $connector ) { diff --git a/includes/context-query.php b/includes/context-query.php index e6127d68e..51af5bd87 100644 --- a/includes/context-query.php +++ b/includes/context-query.php @@ -82,9 +82,9 @@ function get_sql() { $where = array(); $queries = $this->queries; - + $meta_query = new WP_Meta_Query; - + // Context table is always joined // $join[] = " INNER JOIN $context_table ON $main_table.ID = $context_table.record_id"; @@ -148,6 +148,12 @@ function get_sql() { $join = implode( "\n", $join ); + /** + * Filter allows modification of context sql statement + * + * @param array Array of context sql statement components + * @return string Updated context sql statement + */ return apply_filters_ref_array( 'get_context_sql', array( compact( 'join', 'where' ), $this->queries ) ); } diff --git a/includes/db-actions.php b/includes/db-actions.php index 3d08e6dbd..7323febce 100644 --- a/includes/db-actions.php +++ b/includes/db-actions.php @@ -12,7 +12,12 @@ class WP_Stream_DB { public function __construct() { global $wpdb; - // Allow devs to alter the tables prefix, default to base_prefix + /** + * Allows devs to alter the tables prefix, default to base_prefix + * + * @param string database prefix + * @return string udpated database prefix + */ $prefix = apply_filters( 'wp_stream_db_tables_prefix', $wpdb->prefix ); self::$table = $prefix . 'stream'; self::$table_meta = $prefix . 'stream_meta'; @@ -50,6 +55,12 @@ public function get_table_names() { public function insert( $recordarr ) { global $wpdb; + /** + * Filter allows modification of record information + * + * @param array array of record information + * @return array udpated array of record information + */ $recordarr = apply_filters( 'wp_stream_record_array', $recordarr ); // Allow extensions to handle the saving process @@ -62,7 +73,7 @@ public function insert( $recordarr ) { $data = array_filter( $data ); - // TODO Check/Validate *required* fields + // TODO Check/Validate *required* fields $result = $wpdb->insert( self::$table, @@ -73,6 +84,11 @@ public function insert( $recordarr ) { $record_id = $wpdb->insert_id; } else { + /** + * Action Hook that fires on an error during post insertion + * + * @param int $record_id Record being inserted + */ do_action( 'wp_stream_post_insert_error', $record_id ); return $record_id; } @@ -91,7 +107,12 @@ public function insert( $recordarr ) { $this->insert_meta( $record_id, $key, $val ); } } - + /** + * Fires when A Post is inserted + * + * @param int $record_id Inserted record ID + * @param array $recordarr Array of information on this record + */ do_action( 'wp_stream_post_inserted', $record_id, $recordarr ); return $record_id; diff --git a/includes/feeds.php b/includes/feeds.php index 8e893494e..8077afe5e 100644 --- a/includes/feeds.php +++ b/includes/feeds.php @@ -154,6 +154,11 @@ public static function feed_template() { xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" + > @@ -165,6 +170,11 @@ public static function feed_template() { + ip ) ?> + diff --git a/includes/install.php b/includes/install.php index 520864491..c9d7528c9 100644 --- a/includes/install.php +++ b/includes/install.php @@ -16,6 +16,12 @@ public static function check() { $db_version = get_option( plugin_basename( WP_STREAM_DIR ) . '_db' ); + /** + * Allows devs to alter the tables prefix, default to base_prefix + * + * @param string database prefix + * @return string udpated database prefix + */ self::$table_prefix = apply_filters( 'wp_stream_db_tables_prefix', $wpdb->prefix ); if ( empty( $db_version ) ) { @@ -45,7 +51,7 @@ public static function install() { parent bigint(20) unsigned NOT NULL DEFAULT '0', type varchar(20) NOT NULL DEFAULT 'stream', created datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - ip varchar(20) NULL, + ip varchar(39) NULL, PRIMARY KEY (ID), KEY site_id (site_id), KEY parent (parent), @@ -105,11 +111,6 @@ public static function update( $db_version, $current ) { global $wpdb; $prefix = self::$table_prefix; - // If version is lower than 1.1.3, do the update routine - if ( version_compare( $db_version, '1.1.3' ) == -1 ) { - $wpdb->query( "ALTER TABLE {$prefix}stream MODIFY ip varchar(20) NULL AFTER created" ); - } - // If version is lower than 1.1.4, do the update routine if ( version_compare( $db_version, '1.1.4' ) == -1 ) { $tables = array( 'stream', 'stream_context', 'stream_meta' ); @@ -118,6 +119,11 @@ public static function update( $db_version, $current ) { $wpdb->query( "ALTER TABLE {$prefix}{$table} CONVERT TO CHARACTER SET {$wpdb->charset}{$collate};" ); } } + + // If version is lower than 1.1.7, do the update routine + if ( version_compare( $db_version, '1.1.7' ) == -1 ) { + $wpdb->query( "ALTER TABLE {$prefix}stream MODIFY ip varchar(39) NULL AFTER created" ); + } } } diff --git a/includes/list-table.php b/includes/list-table.php index 1f2590e11..1c8d95b07 100644 --- a/includes/list-table.php +++ b/includes/list-table.php @@ -22,9 +22,25 @@ function __construct( $args = array() ) { add_filter( 'set-screen-option', array( __CLASS__, 'set_screen_option' ), 10, 3 ); add_filter( 'screen_settings', array( __CLASS__, 'live_update_checkbox' ), 10, 2 ); + add_action( 'wp_ajax_wp_stream_filters', array( __CLASS__, 'ajax_filters' ) ); set_screen_options(); } + static function ajax_filters() { + $results = array( + array( + 'id' => 1, + 'text' => 'Garfield', + ), + array( + 'id' => 2, + 'text' => 'Odie', + ), + ); + echo json_encode( $results ); + die(); + } + function extra_tablenav( $which ) { if ( $which == 'top' ){ $this->filters_form(); @@ -32,6 +48,12 @@ function extra_tablenav( $which ) { } function get_columns(){ + /** + * Allows devs to add new columns to table + * + * @param array default columns + * @return array updated list of columns + */ return apply_filters( 'wp_stream_list_table_columns', array( @@ -49,8 +71,8 @@ function get_columns(){ function get_sortable_columns() { return array( - 'id' => 'id', - 'date' => 'date', + 'id' => array( 'ID', false ), + 'date' => array( 'date', false ), ); } @@ -201,7 +223,12 @@ function column_default( $item, $column_name ) { break; default: - // Register inserted column defaults. Must match a column header from get_columns. + /** + * Registers new Columns to be inserted into the table. The cell contents of this column is set + * below with 'wp_stream_inster_column_default-' + * + * @param array $new_columns Array of new column titles to add + */ $inserted_columns = apply_filters( 'wp_stream_register_column_defaults', $new_columns = array() ); if ( ! empty( $inserted_columns ) && is_array( $inserted_columns ) ) { @@ -215,6 +242,12 @@ function column_default( $item, $column_name ) { * with wp_stream_register_column_defaults */ if ( $column_title == $column_name && has_action( 'wp_stream_insert_column_default-' . $column_title ) ) { + /** + * This action allows for the addition of content under the specified column ($column_title) + * + * @param string $column_title Title of the column (set in wp_stream_register_column_defaults) + * @param obj $item Contents of the row + */ $out = do_action( 'wp_stream_insert_column_default-' . $column_title, $item ); } else { $out = $column_name; @@ -231,8 +264,26 @@ function column_default( $item, $column_name ) { public static function get_action_links( $record ){ - $out = ''; + $out = ''; + + /** + * Filter allows modification of action links for a specific connector + * + * @param string connector + * @param array array of action links for this connector + * @param obj record + * @return arrray action links for this connector + */ $action_links = apply_filters( 'wp_stream_action_links_' . $record->connector, array(), $record ); + + /** + * Filter allows addition of custom links for a specific connector + * + * @param string connector + * @param array array of custom links for this connector + * @param obj record + * @return arrray custom links for this connector + */ $custom_links = apply_filters( 'wp_stream_custom_action_links_' . $record->connector, array(), $record ); if ( $action_links || $custom_links ) { @@ -342,10 +393,15 @@ function filters_form() { $filters_string = sprintf( '', 'wp_stream' ); - $filters['author'] = array( - 'title' => __( 'authors', 'stream' ), - 'items' => $this->assemble_records( 'author', 'stream' ), - ); + $authors_records = $this->assemble_records( 'author', 'stream' ); + $filters['author'] = array(); + $filters['author']['title'] = __( 'authors', 'stream' ); + + if ( count( $authors_records ) <= WP_Stream_Admin::PRELOAD_AUTHORS_MAX ) { + $filters['author']['items'] = $authors_records; + } else { + $filters['author']['ajax'] = true; + } $filters['connector'] = array( 'title' => __( 'connectors', 'stream' ), @@ -362,12 +418,20 @@ function filters_form() { 'items' => $this->assemble_records( 'action' ), ); + /** + * Filter allows additional filters in the list table dropdowns + * Note the format of the filters above, with they key and array + * containing a title and array of items. + * + * @param array Array of filters + * @return array Updated array of filters + */ $filters = apply_filters( 'wp_stream_list_table_filters', $filters ); $filters_string .= $this->filter_date(); foreach ( $filters as $name => $data ) { - $filters_string .= $this->filter_select( $name, $data['title'], $data['items'] ); + $filters_string .= $this->filter_select( $name, $data['title'], isset( $data['items'] ) ? $data['items'] : array(), isset( $data['ajax'] ) && $data['ajax'] ); } $filters_string .= sprintf( '', __( 'Filter', 'stream' ) ); @@ -376,24 +440,34 @@ function filters_form() { echo sprintf( '
%s
', $filters_string ); // xss okay } - function filter_select( $name, $title, $items ) { - $options = array( sprintf( __( '', 'stream' ), $title ) ); - $selected = filter_input( INPUT_GET, $name ); - foreach ( $items as $v => $label ) { - $options[$v] = sprintf( - '', - $v, - selected( $v, $selected, false ), - $label['disabled'], - $label['label'] + function filter_select( $name, $title, $items, $ajax ) { + if ( $ajax ) { + $out = sprintf( + '', + $name, + filter_input( INPUT_GET, $name ), + $title + ); + } else { + $options = array( sprintf( __( '', 'stream' ), $title ) ); + $selected = filter_input( INPUT_GET, $name ); + foreach ( $items as $v => $label ) { + $options[$v] = sprintf( + '', + $v, + selected( $v, $selected, false ), + $label['disabled'], + $label['label'] + ); + } + $out = sprintf( + '', + $name, + $title, + implode( '', $options ) ); } - $out = sprintf( - '', - $name, - $title, - implode( '', $options ) - ); + return $out; } @@ -452,6 +526,9 @@ function display_tablenav( $which ) {
extra_tablenav( $which ); $this->pagination( $which ); diff --git a/includes/log.php b/includes/log.php index f4a1182e5..2007816fb 100644 --- a/includes/log.php +++ b/includes/log.php @@ -20,6 +20,12 @@ class WP_Stream_Log { * @return void */ public static function load() { + /** + * Filter allows developers to change log handler class + * + * @param array Current Class + * @return string New Class for log handling + */ $log_handler = apply_filters( 'wp_stream_log_handler', __CLASS__ ); self::$instance = new $log_handler; } diff --git a/includes/query.php b/includes/query.php index 9fb0e0b19..3f396b2bf 100644 --- a/includes/query.php +++ b/includes/query.php @@ -59,6 +59,12 @@ public function query( $args ) { $args = wp_parse_args( $args, $defaults ); + /** + * Filter allows additional arguments to query $args + * + * @param array Array of query arguments + * @return array Updated array of query arguments + */ $args = apply_filters( 'stream_query_args', $args ); $join = ''; diff --git a/includes/settings.php b/includes/settings.php index 115f285be..5d9334a7b 100644 --- a/includes/settings.php +++ b/includes/settings.php @@ -36,7 +36,12 @@ public static function load() { // Parse field information gathering default values $defaults = self::get_defaults(); - // Get options + /** + * Filter allows for modification of options + * + * @param array array of options + * @return array updated array of options + */ self::$options = apply_filters( 'wp_stream_options', wp_parse_args( @@ -139,6 +144,12 @@ public static function get_fields() { ), ), ); + /** + * Filter allows for modification of options fields + * + * @param array array of fields + * @return array updated array of fields + */ self::$fields = apply_filters( 'wp_stream_options_fields', $fields ); } return self::$fields; @@ -419,6 +430,9 @@ public function updated_option_ttl_remove_records( $old_value, $new_value ) { $ttl_after = isset( $new_value['general_records_ttl'] ) ? (int) $new_value['general_records_ttl'] : -1; if ( $ttl_after < $ttl_before ) { + /** + * Action assists in purging when TTL is shortened + */ do_action( 'wp_stream_auto_purge' ); } } diff --git a/readme.md b/readme.md index 6894e5262..86dd36d87 100755 --- a/readme.md +++ b/readme.md @@ -53,6 +53,8 @@ Stream is built to extend, allowing developers to easily build their own connect * Private JSON feeds of user activity records * Set how long records should live before being purged automatically * Option to manually purge all user activity records from the database + * Disable connectors where you don't want user activity tracked + * Support for IPv6 addresses **Extension plugins:** @@ -69,7 +71,6 @@ Stream is built to extend, allowing developers to easily build their own connect **Coming soon:** * Multisite view of all activity records on a network - * Support for IPv6 addresses * Language support for Arabic (RTL), Czech, Slovak and Indonesian **See room for improvement?** @@ -104,6 +105,18 @@ Thank you for wanting to make Stream better for everyone! We salute you. ## Changelog ## +### 1.1.8 ### +**2014/02/09** - Bug fixes. Props [shadyvb](http://profiles.wordpress.org/shadyvb/) + +### 1.1.7 ### +**2014/02/06** - Upgrade routine for IPv6 support. Persist tab selection after saving Stream Settings. Props [shadyvb](http://profiles.wordpress.org/shadyvb/), [dero](https://github.com/dero) + +### 1.1.6 ### +**2014/02/06** - Sortable columns bug fix on the records screen. Props [powelski](http://profiles.wordpress.org/powelski/), [fjarrett](http://profiles.wordpress.org/fjarrett/) + +### 1.1.5 ### +**2014/02/05** - Fixed a class scope bug [reported in the support forum](http://wordpress.org/support/topic/temporary-fatal-error-after-upgrade-113) that was causing a fatal error on some installs. Props [shadyvb](http://profiles.wordpress.org/shadyvb/) + ### 1.1.4 ### **2014/02/05** - Highlight changed settings field feature. DB upgrade routine for proper utf-8 charset. Various bug fixes. Props [powelski](http://profiles.wordpress.org/powelski/), [johnregan3](http://profiles.wordpress.org/johnregan3/), [shadyvb](http://profiles.wordpress.org/shadyvb/), [fjarrett](http://profiles.wordpress.org/fjarrett/) diff --git a/readme.txt b/readme.txt index 4c0c31580..1de7a4b31 100644 --- a/readme.txt +++ b/readme.txt @@ -51,6 +51,8 @@ Stream is built to extend, allowing developers to easily build their own connect * Private JSON feeds of user activity records * Set how long records should live before being purged automatically * Option to manually purge all user activity records from the database + * Disable connectors where you don't want user activity tracked + * Support for IPv6 addresses **Extension plugins:** @@ -67,7 +69,6 @@ Stream is built to extend, allowing developers to easily build their own connect **Coming soon:** * Multisite view of all activity records on a network - * Support for IPv6 addresses * Language support for Arabic (RTL), Czech, Slovak and Indonesian **See room for improvement?** @@ -89,6 +90,18 @@ Thank you for wanting to make Stream better for everyone! We salute you. == Changelog == += 1.1.8 = +**2014/02/09** - Bug fixes. Props [shadyvb](http://profiles.wordpress.org/shadyvb/) + += 1.1.7 = +**2014/02/06** - Upgrade routine for IPv6 support. Persist tab selection after saving Stream Settings. Props [shadyvb](http://profiles.wordpress.org/shadyvb/), [dero](https://github.com/dero) + += 1.1.6 = +**2014/02/06** - Sortable columns bug fix on the records screen. Props [powelski](http://profiles.wordpress.org/powelski/), [fjarrett](http://profiles.wordpress.org/fjarrett/) + += 1.1.5 = +**2014/02/05** - Fixed a class scope bug [reported in the support forum](http://wordpress.org/support/topic/temporary-fatal-error-after-upgrade-113) that was causing a fatal error on some installs. Props [shadyvb](http://profiles.wordpress.org/shadyvb/) + = 1.1.4 = **2014/02/05** - Highlight changed settings field feature. DB upgrade routine for proper utf-8 charset. Various bug fixes. Props [powelski](http://profiles.wordpress.org/powelski/), [johnregan3](http://profiles.wordpress.org/johnregan3/), [shadyvb](http://profiles.wordpress.org/shadyvb/), [fjarrett](http://profiles.wordpress.org/fjarrett/) diff --git a/stream.php b/stream.php index 832241dca..1c8fdddda 100644 --- a/stream.php +++ b/stream.php @@ -3,7 +3,7 @@ * Plugin Name: Stream * Plugin URI: http://wordpress.org/plugins/stream/ * Description: Stream tracks logged-in user activity so you can monitor every change made on your WordPress site in beautifully organized detail. All activity is organized by context, action and IP address for easy filtering. Developers can extend Stream with custom connectors to log any kind of action. - * Version: 1.1.4 + * Version: 1.1.8 * Author: X-Team * Author URI: http://x-team.com/wordpress/ * License: GPLv2+ @@ -37,7 +37,7 @@ class WP_Stream { * * @const string */ - const VERSION = '1.1.4'; + const VERSION = '1.1.8'; /** * Hold Stream instance @@ -138,6 +138,12 @@ public static function install() { return; } + /** + * Filter will halt install() if set to true + * + * @param bool + * @return bool + */ if ( apply_filters( 'wp_stream_no_tables', false ) ) { return; } @@ -153,6 +159,12 @@ public static function install() { * @return void */ private function verify_database_present() { + /** + * Filter will halt verify_database_present() if set to true + * + * @param bool + * @return bool + */ if ( apply_filters( 'wp_stream_no_tables', false ) ) { return; } diff --git a/tests/tests/test-admin.php b/tests/tests/test-admin.php index f71f3b080..ff7d04c2d 100644 --- a/tests/tests/test-admin.php +++ b/tests/tests/test-admin.php @@ -101,6 +101,13 @@ public function test_admin_enqueue_script() { * Check the output of the plugin action links function */ public function test_plugin_action_links() { + /** + * Filter allows for addition of action links during testing + * + * @param array array of action links + * @param string URL of stream main PHP file + * @return array updated array of action links + */ $filter_output = apply_filters( 'plugin_action_links', array(), plugin_basename( WP_STREAM_DIR . 'stream.php' ) ); $this->assertTrue( strrpos( $filter_output[0], '/wp-admin/admin.php?page=wp_stream_settings' ) >= 0 ); } diff --git a/ui/admin.js b/ui/admin.js index df6b40c8d..1ac12befd 100644 --- a/ui/admin.js +++ b/ui/admin.js @@ -8,11 +8,51 @@ jQuery(function($){ }); } - $( '.toplevel_page_wp_stream .chosen-select' ).select2({ - minimumResultsForSearch: 10, - allowClear: true, - width: '165px' - }); + $( '.toplevel_page_wp_stream select.chosen-select' ).select2({ + minimumResultsForSearch: 10, + allowClear: true, + width: '165px' + }); + + $( '.toplevel_page_wp_stream input[type=hidden].chosen-select' ).select2({ + minimumInputLength: 1, + allowClear: true, + width: '165px', + ajax: { + url: ajaxurl, + datatype: 'json', + data: function (term) { + return { + action: 'wp_stream_filters', + filter: $(this).attr('name'), + q: term + }; + }, + results: function (data) { + return {results: data}; + } + }, + initSelection: function (element, callback) { + var id = $(element).val(); + + if(id !== '') { + $.post( + ajaxurl, + { + action: 'wp_stream_get_author_name_by_id', + id: id + }, + function (response) { + callback({ + id: id, + text: response + }); + }, + 'json' + ); + } + } + }); $(window).load(function() { $( '.toplevel_page_wp_stream [type=search]' ).off( 'mousedown' ); @@ -32,15 +72,25 @@ jQuery(function($){ }); // Admin page tabs - var $tabs = $('.nav-tab-wrapper'), - $panels = $('table.form-table'), - currentHash = window.location.hash ? window.location.hash.match(/\d+/)[0] : 0; + var $tabs = $('.nav-tab-wrapper'), + $panels = $('table.form-table'), + $activeTab = $tabs.find('.nav-tab-active'), + defaultIndex = $activeTab.length > 0 ? $tabs.find('a').index( $activeTab ) : 0, + currentHash = window.location.hash ? window.location.hash.match(/\d+/)[0] : defaultIndex, + syncFormAction = function( index ) { + var $optionsForm = $('input[name="option_page"][value="wp_stream"]').parent('form'); + var currentAction = $optionsForm.attr('action'); + + $optionsForm.prop('action', currentAction.replace( /(^[^#]*).*$/, '$1#' + index )); + }; $tabs.on('click', 'a', function(e){ e.preventDefault(); var index = $tabs.find('a').index( $(this) ); $panels.hide().eq(index).show(); $tabs.find('a').removeClass('nav-tab-active').filter($(this)).addClass('nav-tab-active'); + window.location.hash = index; + syncFormAction(index); }); $tabs.children().eq( currentHash ).trigger('click');