├── languages ├── live-stream-widget-default.mo ├── live-stream-widget-default.po └── live-stream-widget.pot ├── css ├── live-stream-admin-style.css └── live-stream-style.css ├── js ├── live-stream.js └── live-stream-admin.js ├── lib └── dash-notices │ └── wpmudev-dash-notification.php ├── changelog.txt ├── README.md └── live-stream.php /languages/live-stream-widget-default.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/live-stream-widget/master/languages/live-stream-widget-default.mo -------------------------------------------------------------------------------- /css/live-stream-admin-style.css: -------------------------------------------------------------------------------- 1 | #wpcontent select.widget-live-stream-content-types { 2 | width: 100%; 3 | } 4 | 5 | #wpcontent select.widget-live-stream-content-terms[multiple] { 6 | max-height: 75px; 7 | width: 100%; 8 | } 9 | 10 | 11 | #wpcontent select.widget-live-stream-content-types optgroup option, 12 | #wpcontent select.widget-live-stream-content-terms optgroup option { 13 | padding-left: 10px; 14 | } 15 | 16 | ul.live-stream-admin-checklist { 17 | height: 150px; 18 | overflow-y: scroll; 19 | background: #FFFFFF; 20 | padding: 5px; 21 | } 22 | 23 | ul.live-stream-admin-checklist ul { 24 | margin-left: 18px; 25 | } -------------------------------------------------------------------------------- /css/live-stream-style.css: -------------------------------------------------------------------------------- 1 | .live-stream-items-wrapper { 2 | overflow-y: hidden; 3 | overflow-x: hidden; 4 | width: 100%; 5 | margin: 0 0 10px 0; 6 | position: relative; 7 | } 8 | 9 | ul.live-stream-controls { 10 | list-style: none; 11 | height: 30px; 12 | padding: 0; 13 | width: 100%; 14 | } 15 | 16 | ul.live-stream-controls li { 17 | list-style: none; 18 | margin: 0; 19 | padding: 0; 20 | float: left; 21 | width: 25%; 22 | position: relative; 23 | } 24 | 25 | ul.live-stream-controls li button { 26 | height: 25px; 27 | width: 25px; 28 | } 29 | .live-stream-items-wrapper .live-stream-item { 30 | float: left; 31 | width: 90%; 32 | margin-bottom: 10px; 33 | background-color: #FFF; 34 | } 35 | 36 | .live-stream-items-wrapper .live-stream-current-item { 37 | background-color: #CCC; 38 | } 39 | 40 | .live-stream-items-wrapper .live-stream-item .live-stream-avatar { 41 | width: 35px; 42 | float: left; 43 | margin-right: -35px; 44 | } 45 | 46 | .live-stream-items-wrapper .live-stream-item img { 47 | margin-top: 5px; 48 | } 49 | 50 | .live-stream-items-wrapper .live-stream-text-has-avatar .live-stream-text { 51 | margin-left: 35px; 52 | } 53 | 54 | .live-stream-items-wrapper .live-stream-text-has-avatar .live-stream-text .live-stream-text-footer { 55 | font-size: 11px; 56 | } 57 | 58 | .live-stream-items-wrapper .live-stream-item-content { font-style: italic; } -------------------------------------------------------------------------------- /js/live-stream.js: -------------------------------------------------------------------------------- 1 | (function($){ 2 | "use strict"; 3 | 4 | var update_selector = null; 5 | var controls_selector = null; 6 | var containerHeight = null; 7 | var widget_id = null; 8 | 9 | var visible_top_item_id = ''; 10 | var visible_bottom_item_id = ''; 11 | 12 | $.LiveStreamUpdates = function(selector, settings) { 13 | // settings 14 | var config = { 15 | 'delay': 2000, 16 | 'widget_id': 0, 17 | 'max_items': 0 18 | }; 19 | 20 | if ( settings ){$.extend(config, settings);} 21 | 22 | if (selector != '') { 23 | update_selector = selector+' .live-stream-items-wrapper'; 24 | 25 | setInterval(function() { 26 | // We need to find the ID of the first/latest item displayed. Then pass this to AJAX so we can pull more recent items 27 | var latest_id = jQuery(update_selector+' .live-stream-item').first().attr('id'); 28 | 29 | if (latest_id) { 30 | var latest_id_parts = latest_id.split('-'); 31 | if (latest_id_parts[3] != "") { 32 | getUpdates(config.widget_id, latest_id_parts[3], update_selector, config.max_items); 33 | } 34 | } 35 | 36 | }, config.delay); 37 | } 38 | 39 | return this; 40 | } 41 | 42 | function getUpdates(widget_id, timekey, update_selector, max_items) { 43 | 44 | var data = { 45 | action: 'live_stream_update_ajax', 46 | widget_id: widget_id, 47 | timekey: timekey 48 | }; 49 | 50 | jQuery.ajax({ 51 | type: 'POST', 52 | url: live_stream_data.ajaxurl, 53 | data: data, 54 | cache: false, 55 | dataType: 'html', 56 | success: function( reply_data ) { 57 | if (reply_data != "") { 58 | 59 | jQuery(reply_data).hide().prependTo(update_selector).slideDown("slow"); 60 | jQuery(update_selector+' li:gt('+max_items+')').hide(); 61 | } 62 | } 63 | }); 64 | } 65 | 66 | })(jQuery); 67 | -------------------------------------------------------------------------------- /js/live-stream-admin.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready( function($) { 2 | 3 | // From http://www.johngadbois.com/adding-your-own-callbacks-to-wordpress-ajax-requests/ 4 | jQuery('body').ajaxSuccess(function(evt, request, settings) { 5 | jQuery('a.live-stream-terms-show').click(live_stream_terms_show); 6 | jQuery('ul.live-stream-admin-checklist input').click(live_stream_checklist_click); 7 | jQuery('input.live-stream-terms-select-all').click(live_Stream_terms_select_all_click); 8 | 9 | }); 10 | 11 | jQuery('a.live-stream-terms-show').click(live_stream_terms_show); 12 | jQuery('ul.live-stream-admin-checklist input').click(live_stream_checklist_click); 13 | jQuery('input.live-stream-terms-select-all').click(live_Stream_terms_select_all_click); 14 | 15 | function live_stream_terms_show(event) { 16 | 17 | var parent = jQuery(this).parent(); 18 | var select_all = jQuery('input.live-stream-terms-select-all', parent); 19 | if (jQuery(select_all).is(':checked')) { 20 | //console.log('select all is CHECKED'); 21 | jQuery(select_all).removeAttr('checked'); 22 | } 23 | var wrapper = jQuery(this).parent().next('div.terms-wrapper'); 24 | if (!jQuery(wrapper).is(":visible")) 25 | jQuery(wrapper).show(); 26 | 27 | var wrapper_ul = jQuery('ul', wrapper); 28 | if (jQuery(wrapper_ul).is(":visible")) 29 | { 30 | jQuery(wrapper_ul).slideUp(); 31 | } else { 32 | jQuery(wrapper_ul).slideDown(); 33 | } 34 | 35 | event.stopImmediatePropagation(); 36 | return false; 37 | } 38 | 39 | function live_stream_checklist_click(event) { 40 | 41 | var parent_div = jQuery(this).parents('div.terms-wrapper'); 42 | var parent_ul = $(this).parents('ul'); 43 | 44 | selected_terms_array = []; 45 | 46 | jQuery(parent_ul).find('input:checked').each( function() { 47 | var parent_item = $(this).parent(); 48 | var label_text = $(parent_item).find('span.label-text').html(); 49 | selected_terms_array[selected_terms_array.length] = label_text; 50 | }); 51 | 52 | if (selected_terms_array.length) { 53 | selected_terms_array.sort(); 54 | selected_terms_html = selected_terms_array.join(', '); 55 | jQuery(parent_div).find('p span.selected-terms').html(selected_terms_html); 56 | } else { 57 | jQuery(parent_div).find('p span.selected-terms').html('No terms selected'); 58 | } 59 | event.stopImmediatePropagation(); 60 | return; 61 | } 62 | 63 | function live_Stream_terms_select_all_click(event) { 64 | var wrapper = jQuery(this).parent().next('div.terms-wrapper'); 65 | if (jQuery(this).is(':checked')) { 66 | jQuery(wrapper).hide(); 67 | } else { 68 | jQuery(wrapper).slideDown('slow'); 69 | } 70 | event.stopImmediatePropagation(); 71 | return; 72 | } 73 | }); 74 | -------------------------------------------------------------------------------- /lib/dash-notices/wpmudev-dash-notification.php: -------------------------------------------------------------------------------- 1 | slug, 'install_wpmudev_dash') !== false ) { 31 | $res = new stdClass; 32 | $res->name = 'WPMU DEV Dashboard'; 33 | $res->slug = 'wpmu-dev-dashboard'; 34 | $res->version = ''; 35 | $res->rating = 100; 36 | $res->homepage = 'http://premium.wpmudev.org/project/wpmu-dev-dashboard/'; 37 | $res->download_link = "http://premium.wpmudev.org/wdp-un.php?action=install_wpmudev_dash"; 38 | $res->tested = $cur_wp_version; 39 | 40 | return $res; 41 | } 42 | 43 | return false; 44 | } 45 | 46 | function auto_install_url() { 47 | $function = is_multisite() ? 'network_admin_url' : 'admin_url'; 48 | return wp_nonce_url($function("update.php?action=install-plugin&plugin=install_wpmudev_dash"), "install-plugin_install_wpmudev_dash"); 49 | } 50 | 51 | function activate_url() { 52 | $function = is_multisite() ? 'network_admin_url' : 'admin_url'; 53 | return wp_nonce_url($function('plugins.php?action=activate&plugin=wpmudev-updates%2Fupdate-notifications.php'), 'activate-plugin_wpmudev-updates/update-notifications.php'); 54 | } 55 | 56 | function install_notice() { 57 | echo '

' . sprintf(__('Easily get updates, support, and one-click WPMU DEV plugin/theme installations right from in your dashboard - install the free WPMU DEV Dashboard plugin.    (find out more)', 'wpmudev'), $this->auto_install_url()) . '

'; 58 | } 59 | 60 | function activate_notice() { 61 | echo '

' . sprintf(__('Updates, Support, Premium Plugins, Community - activate the WPMU DEV Dashboard plugin now.', 'wpmudev'), $this->activate_url()) . '

'; 62 | } 63 | 64 | } 65 | new WPMUDEV_Dashboard_Notice(); 66 | } 67 | ?> -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------- 2 | Live Stream Widget 3 | Author: Paul Menard (incsub) 4 | ---------------------------------------------------------------------- 5 | 6 | Change Log: 7 | ---------------------------------------------------------------------- 8 | ---------------------------------------------------------------------- 9 | 10 | 1.0.5 - 2017-09-04 11 | ---------------------------------------------------------------------- 12 | - Fix: errors with PHP strict standards 13 | 14 | 1.0.4.3 - 2013/09/02 15 | ---------------------------------------------------------------------- 16 | - Correct issue with warning on regular WordPress sites. 17 | - Modified taxonomy terms selection UI to allow unselect for taxonomy terms instead of defaulting to selected all. 18 | - Added new option to allow setting link target to _blank to force open in new window. 19 | 20 | 1.0.4.2 - 2013/02/05 21 | ---------------------------------------------------------------------- 22 | - Corrected issue with double comment content on widget output 23 | 24 | 1.0.4.1 - 2013/01/07 25 | ---------------------------------------------------------------------- 26 | - Corrected sorting issue when merging multiple posts types 27 | - Added some CSS wrappers to better designate post type content list items and item elements 28 | 29 | 1.0.4 - 2012/12/13 30 | ---------------------------------------------------------------------- 31 | - Corrected bug where comments were not filtered by blog-id http://premium.wpmudev.org/forums/topic/wrong-post-titles-shown-in-live-stream-widget 32 | - Added new option to show X number characters of the post/comment content 33 | 34 | 1.0.3.1 - 2012/11/13 35 | ---------------------------------------------------------------------- 36 | - More change for Post Indexer 3 Network Query logic 37 | - Other tweaks to widget output for linking to comments listing 38 | 39 | 1.0.3 - 2012/11/07 40 | ---------------------------------------------------------------------- 41 | - Added logic to support Post Indexer 3 Network_Query object instead of direct database calls. 42 | - Changed display logic when showing local content and posts only http://premium.wpmudev.org/forums/topic/going-to-last-comment-posted 43 | 44 | 1.0.2 - 2012/09/19 45 | ---------------------------------------------------------------------- 46 | - Added in logic to support AJAX refresh calls for live data updates instead of just on page load. 47 | - Added support for non-Multisite which will pull from local Post, Comments and Taxonomies 48 | 49 | 50 | 1.0.1 - 2012/08/07 51 | ---------------------------------------------------------------------- 52 | - Added dropdown to allow Local - Local users and local content, Network - local user and network content, All users and all content 53 | - Added logic to support local Post/Comments when Post Indexer and Comment Indexer plugins are not enabled. When selecting local 54 | - Updated taxonomy terms selection logic to allow selecting multiple terms from various taxonomies. Still only support Categories and Post Tags 55 | - Corrected logic for comments to only pull approved comments 56 | 57 | 1.0 - 2012/7/18 58 | ---------------------------------------------------------------------- 59 | - Initial Release 60 | -------------------------------------------------------------------------------- /languages/live-stream-widget-default.po: -------------------------------------------------------------------------------- 1 | # Translation of the WordPress plugin by . 2 | # Copyright (C) 2013 3 | # This file is distributed under the same license as the package. 4 | # FIRST AUTHOR , 2013. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: Live Stream Widget 1.0.4.3\n" 9 | "Report-Msgid-Bugs-To: http://wordpress.org/tag/live-stream-widget\n" 10 | "POT-Creation-Date: 2013-09-02 09:07-0500\n" 11 | "PO-Revision-Date: 2013-09-02 10:09-0500\n" 12 | "Last-Translator: Paul Menard \n" 13 | "Language-Team: \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "X-Poedit-Language: English\n" 18 | 19 | #: lib/dash-notices/wpmudev-dash-notification.php:57 20 | #, php-format 21 | msgid "Easily get updates, support, and one-click WPMU DEV plugin/theme installations right from in your dashboard - install the free WPMU DEV Dashboard plugin.    (find out more)" 22 | msgstr "" 23 | 24 | #: lib/dash-notices/wpmudev-dash-notification.php:61 25 | #, php-format 26 | msgid "Updates, Support, Premium Plugins, Community - activate the WPMU DEV Dashboard plugin now." 27 | msgstr "" 28 | 29 | #: live-stream.php:118 30 | msgid "Show Posts and Comments in a Twitter-like updating widget" 31 | msgstr "" 32 | 33 | #: live-stream.php:125 34 | msgid "Live Stream" 35 | msgstr "" 36 | 37 | #: live-stream.php:370 38 | msgid "Widget Title:" 39 | msgstr "" 40 | 41 | #: live-stream.php:381 42 | msgid "Show Author Avatar?" 43 | msgstr "" 44 | 45 | #: live-stream.php:390 46 | msgid "Open Links in new Window?" 47 | msgstr "" 48 | 49 | #: live-stream.php:398 50 | msgid "Maximum items to show." 51 | msgstr "" 52 | 53 | #: live-stream.php:409 54 | msgid "Show chars from item content. 0 for none. Will append ... after" 55 | msgstr "" 56 | 57 | #: live-stream.php:424 58 | msgid "Content Loading" 59 | msgstr "" 60 | 61 | #: live-stream.php:429 62 | msgid "Looping - Continuous Scroll. No new content." 63 | msgstr "" 64 | 65 | #: live-stream.php:431 66 | msgid "Live - Load new content via AJAX. No scrolling." 67 | msgstr "" 68 | 69 | #: live-stream.php:442 70 | msgid "Show Vertical Scrollbar?" 71 | msgstr "" 72 | 73 | #: live-stream.php:450 74 | msgid "Number of second delay for scrolling/polling" 75 | msgstr "" 76 | 77 | #: live-stream.php:461 78 | msgid "Widget Height" 79 | msgstr "" 80 | 81 | #: live-stream.php:466 82 | msgid "200px - approx. 2-3 items" 83 | msgstr "" 84 | 85 | #: live-stream.php:468 86 | msgid "350px - approx. 4-5 items" 87 | msgstr "" 88 | 89 | #: live-stream.php:470 90 | msgid "500px - approx. 6-8 items" 91 | msgstr "" 92 | 93 | #: live-stream.php:472 94 | msgid "other - provide your own height" 95 | msgstr "" 96 | 97 | #: live-stream.php:477 98 | msgid "Specify Widget Height: include px, em, etc. qualifies i.e. 300px" 99 | msgstr "" 100 | 101 | #: live-stream.php:501 102 | msgid "Local - Content from only this site." 103 | msgstr "" 104 | 105 | #: live-stream.php:502 106 | msgid "Site - Content from all sites created by users from this site." 107 | msgstr "" 108 | 109 | #: live-stream.php:503 110 | msgid "All - Content by all users from all sites" 111 | msgstr "" 112 | 113 | #: live-stream.php:511 114 | msgid "What content to show" 115 | msgstr "" 116 | 117 | #: live-stream.php:534 118 | msgid "Content Types:" 119 | msgstr "" 120 | 121 | #: live-stream.php:539 122 | msgid "All Types" 123 | msgstr "" 124 | 125 | #: live-stream.php:597 126 | msgid "Select all" 127 | msgstr "" 128 | 129 | #: live-stream.php:597 130 | msgid "Click to show/hide taxonomy terms" 131 | msgstr "" 132 | 133 | #: live-stream.php:608 134 | msgid "No terms selected" 135 | msgstr "" 136 | 137 | #: live-stream.php:1407 138 | msgid "commented on" 139 | msgstr "" 140 | 141 | #: live-stream.php:1427 142 | msgid "published" 143 | msgstr "" 144 | 145 | #: live-stream.php:1442 146 | msgid "via" 147 | msgstr "" 148 | 149 | #: live-stream.php:1449 150 | #, php-format 151 | msgid "%s ago " 152 | msgstr "" 153 | 154 | #: live-stream.php:1456 155 | #: live-stream.php:1468 156 | msgid "comment" 157 | msgstr "" 158 | 159 | #: live-stream.php:1461 160 | msgid "comments" 161 | msgstr "" 162 | 163 | #: live-stream.php:1472 164 | msgid "visit" 165 | msgstr "" 166 | 167 | -------------------------------------------------------------------------------- /languages/live-stream-widget.pot: -------------------------------------------------------------------------------- 1 | # Translation of the WordPress plugin by . 2 | # Copyright (C) 2013 3 | # This file is distributed under the same license as the package. 4 | # FIRST AUTHOR , 2013. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: \n" 10 | "Report-Msgid-Bugs-To: http://wordpress.org/tag/live-stream-widget\n" 11 | "POT-Creation-Date: 2013-09-02 09:07-0500\n" 12 | "PO-Revision-Date: 2013-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=utf-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: lib/dash-notices/wpmudev-dash-notification.php:57 20 | #, php-format 21 | msgid "" 22 | "Easily get updates, support, and one-click WPMU DEV plugin/theme " 23 | "installations right from in your dashboard - install the free WPMU DEV Dashboard plugin.    (find out more)" 27 | msgstr "" 28 | 29 | #: lib/dash-notices/wpmudev-dash-notification.php:61 30 | #, php-format 31 | msgid "" 32 | "Updates, Support, Premium Plugins, Community - activate the WPMU DEV Dashboard plugin now." 35 | msgstr "" 36 | 37 | #: live-stream.php:118 38 | msgid "Show Posts and Comments in a Twitter-like updating widget" 39 | msgstr "" 40 | 41 | #: live-stream.php:125 42 | msgid "Live Stream" 43 | msgstr "" 44 | 45 | #: live-stream.php:370 46 | msgid "Widget Title:" 47 | msgstr "" 48 | 49 | #: live-stream.php:381 50 | msgid "Show Author Avatar?" 51 | msgstr "" 52 | 53 | #: live-stream.php:390 54 | msgid "Open Links in new Window?" 55 | msgstr "" 56 | 57 | #: live-stream.php:398 58 | msgid "Maximum items to show." 59 | msgstr "" 60 | 61 | #: live-stream.php:409 62 | msgid "Show chars from item content. 0 for none. Will append ... after" 63 | msgstr "" 64 | 65 | #: live-stream.php:424 66 | msgid "Content Loading" 67 | msgstr "" 68 | 69 | #: live-stream.php:429 70 | msgid "Looping - Continuous Scroll. No new content." 71 | msgstr "" 72 | 73 | #: live-stream.php:431 74 | msgid "Live - Load new content via AJAX. No scrolling." 75 | msgstr "" 76 | 77 | #: live-stream.php:442 78 | msgid "Show Vertical Scrollbar?" 79 | msgstr "" 80 | 81 | #: live-stream.php:450 82 | msgid "Number of second delay for scrolling/polling" 83 | msgstr "" 84 | 85 | #: live-stream.php:461 86 | msgid "Widget Height" 87 | msgstr "" 88 | 89 | #: live-stream.php:466 90 | msgid "200px - approx. 2-3 items" 91 | msgstr "" 92 | 93 | #: live-stream.php:468 94 | msgid "350px - approx. 4-5 items" 95 | msgstr "" 96 | 97 | #: live-stream.php:470 98 | msgid "500px - approx. 6-8 items" 99 | msgstr "" 100 | 101 | #: live-stream.php:472 102 | msgid "other - provide your own height" 103 | msgstr "" 104 | 105 | #: live-stream.php:477 106 | msgid "" 107 | "Specify Widget Height: include px, em, etc. qualifies i.e. 300px" 108 | msgstr "" 109 | 110 | #: live-stream.php:501 111 | msgid "Local - Content from only this site." 112 | msgstr "" 113 | 114 | #: live-stream.php:502 115 | msgid "Site - Content from all sites created by users from this site." 116 | msgstr "" 117 | 118 | #: live-stream.php:503 119 | msgid "All - Content by all users from all sites" 120 | msgstr "" 121 | 122 | #: live-stream.php:511 123 | msgid "What content to show" 124 | msgstr "" 125 | 126 | #: live-stream.php:534 127 | msgid "Content Types:" 128 | msgstr "" 129 | 130 | #: live-stream.php:539 131 | msgid "All Types" 132 | msgstr "" 133 | 134 | #: live-stream.php:597 135 | msgid "Select all" 136 | msgstr "" 137 | 138 | #: live-stream.php:597 139 | msgid "Click to show/hide taxonomy terms" 140 | msgstr "" 141 | 142 | #: live-stream.php:608 143 | msgid "No terms selected" 144 | msgstr "" 145 | 146 | #: live-stream.php:1407 147 | msgid "commented on" 148 | msgstr "" 149 | 150 | #: live-stream.php:1427 151 | msgid "published" 152 | msgstr "" 153 | 154 | #: live-stream.php:1442 155 | msgid "via" 156 | msgstr "" 157 | 158 | #: live-stream.php:1449 159 | #, php-format 160 | msgid "%s ago " 161 | msgstr "" 162 | 163 | #: live-stream.php:1456 live-stream.php:1468 164 | msgid "comment" 165 | msgstr "" 166 | 167 | #: live-stream.php:1461 168 | msgid "comments" 169 | msgstr "" 170 | 171 | #: live-stream.php:1472 172 | msgid "visit" 173 | msgstr "" 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Live Stream Widget 2 | 3 | **INACTIVE NOTICE: This plugin is unsupported by WPMUDEV, we've published it here for those technical types who might want to fork and maintain it for their needs.** 4 | 5 | ## Translations 6 | 7 | Translation files can be found at https://github.com/wpmudev/translations 8 | 9 | ## About 10 | 11 | Live Stream Widget displays an animated live stream of all the latest content from across your network. 12 | 13 | Gather the latest activity from your site in one place – just like the fancy animated recent activity feed on Facebook and Twitter. 14 | 15 | ![Stream recent activity in any widget area on your site.](https://premium.wpmudev.org/wp-content/uploads/2012/07/live-stream-widget-735x470.jpg) 16 | 17 | Stream recent activity in any widget area on your site. 18 | 19 | ### Fancy Animation 20 | 21 | Show a slick looping feed that slides new content in as its created, giving users and visitors an easy way to discover new content. Add another level of engagement. Promote the latest activity on your site without any extra effort. 22 | 23 | ### More Ways to Customize 24 | 25 | Add Live Stream Widget to any widget area on your site and create a custom configuration for each use. Set width, height, avatars display, feed permissions and how much content to show. 26 | 27 | ![Create a global activity feed on your Multisite network.](https://premium.wpmudev.org/wp-content/uploads/2012/07/Global-735x470.jpg) 28 | 29 | Create a global activity feed on your Multisite network. 30 | 31 | ### Multisite Magic 32 | 33 | Give every site on your network the power to stream their newest content. Plus, with the power of Post Indexer and Comment Indexer you can create a global live feed and stream activity from across your network. 34 | 35 | ## Usage 36 | 37 | For help and information on installing plugins you can view our [Installing WordPress Plugins Manual](https://premium.wpmudev.org/manuals/wpmu-manual-2/installing-regular-plugins-on-wpmu/). 38 | 39 | ##### Live Stream works with both single installations of WordPress and Multisite. 40 | 41 | ##### NOTE: If using multisite, you must** install** and **activate** the [Post Indexer Plugin](https://premium.wpmudev.org/project/post-indexer/) and the [Comment Indexer Plugin](https://premium.wpmudev.org/project/comment-indexer/) before activating Live Stream Widget Plugin. 42 | 43 | ### Using Live Stream Widget on Multisite Installations 44 | 45 | Once you have the plugin installed and Network Activated, you can navigate to any site on your network and check out the _Appearance>Widgets_ Menu to see that you have a new Widget called **Live Stream** available. Then it's as simple as dragging and dropping the widget in to the sidebar (or any other available wigetized area) that you want to display it in! Once you have it settled where you want it, you can check out the widget menu and set your options: 46 | 47 | ![Live Stream Widget](https://premium.wpmudev.org/wp-content/uploads/2012/07/live-stream2.png) 48 | 49 | 1\. Enter the title. 50 | 51 | 2\. Select the content types to display. 52 | 53 | 3\. Select the categories and tags. 54 | 55 | 4\. Choose how the content should scroll. 56 | 57 | 5\. Set the widget height. 58 | 59 | 6\. Enter the number of items to loop through. 60 | 61 | 7\. Set the number of characters that should display in each entry. 62 | 63 | 8\. Set the scrolling time delay. 64 | 65 | 9\. Want avatars and a scrollbar too? 66 | 67 | Don't forget to click Save! **Show Author Avatar:** Works with our [Avatar Plugin](https://premium.wpmudev.org/project/avatars/) to display the avatar of the post author! _Please note, at current this plugin does not support custom post types, but we plan to add this in a future release._ Then you'll have a shiny new widget with all the animated feed trimmings!  Just like this one: Note that this widget does some filtering on the feed items. The logic is that it only shows Posts/Comments for users from the current site. The checkbox allows you to include Posts/Comment for the same list of users across all sites.  So, if you install the widget on site3.mysite.com it will only show posts for users on site3.  If you set the checkbox will still only show posts/comments for users on site3 but will also show the the posts/comments that site3 users made on other sites in the network. 68 | 69 | #### Using Live Stream Widget on Single Installations of WordPress 70 | 71 | Live Stream Widget requires no special preparation for single installations of WordPress. Simply activate the plugin and visit the widgets panel in the Appearance section of the WordPress admin menus (_Appearance>Widgets)._ Once there, all settings for the Live Stream Widget mirror those explained above for the multisite WordPress installation. If you run a site with multiple authors, Live Stream Widget will automatically pull the author's [gravatar](http://gravatar.com) (if he/she has set one up) to use as a thumbnail image next to the post/comment widget content. 72 | -------------------------------------------------------------------------------- /live-stream.php: -------------------------------------------------------------------------------- 1 | site_url() ."/wp-admin/admin-ajax.php" 76 | ); 77 | 78 | wp_localize_script( 'live-stream-js', 'live_stream_data', $live_stream_data ); 79 | } 80 | } 81 | 82 | /** 83 | * Setup the needed admin CSS files used by the widget 84 | * 85 | * @since 1.0.0 86 | * @see 87 | * 88 | * @param none 89 | * @return none 90 | */ 91 | function live_stream_admin_init() { 92 | wp_register_style( 'live-stream-admin-style', plugins_url('/css/live-stream-admin-style.css', __FILE__), array(), LIVE_STREAM_VERSION ); 93 | wp_enqueue_style( 'live-stream-admin-style' ); 94 | 95 | wp_enqueue_script( 'jquery' ); 96 | wp_enqueue_script('live-stream-admin-js', plugins_url('/js/live-stream-admin.js', __FILE__), array('jquery'), LIVE_STREAM_VERSION ); 97 | } 98 | 99 | /** 100 | * Wrapper class for our widget per the WordPress coding standards. 101 | * 102 | * @since 1.0.0 103 | * @see 104 | * 105 | * @param none 106 | * @return none 107 | */ 108 | 109 | class LiveStreamWidget extends WP_Widget { 110 | 111 | /** 112 | * Widget setup. 113 | */ 114 | function __construct() { 115 | /* Widget settings. */ 116 | $widget_ops = array( 117 | 'classname' => 'live-stream-widget', 118 | 'description' => __('Show Posts and Comments in a Twitter-like updating widget', 'live-stream-widget'), 119 | 'classname' => 'live-stream-widget-admin' ); 120 | 121 | /* Widget control settings. */ 122 | $control_ops = array( 'width' => 350, 'height' => 350, 'id_base' => 'live-stream-widget' ); 123 | 124 | /* Create the widget. */ 125 | parent::__construct( 'live-stream-widget', __('Live Stream', 'live-stream-widget'), $widget_ops, $control_ops ); 126 | } 127 | 128 | /** 129 | * How to display the widget on the screen. 130 | */ 131 | function widget( $args, $instance ) { 132 | 133 | //echo "args
"; print_r($args); echo "
"; 134 | //echo "instance
"; print_r($instance); echo "
"; 135 | 136 | $items = live_stream_get_post_items($instance, $this->number); 137 | if ( ($items) && (count($items)) ) { 138 | 139 | extract( $args ); 140 | 141 | /* Our variables from the widget settings. */ 142 | $title = apply_filters('widget_title', $instance['title'] ); 143 | 144 | /* Before widget (defined by themes). */ 145 | echo $before_widget; 146 | 147 | /* Display the widget title if one was input (before and after defined by themes). */ 148 | if ( $title ) { 149 | echo $before_title . $title . $after_title; 150 | } 151 | 152 | krsort($items); 153 | //$items = array_slice($items, 1, count($items), true); 154 | 155 | if (isset($instance['height'])) { 156 | if ( ($instance['height'] == "other") && (isset($instance['height_other'])) ) { 157 | $style_height = " height:". $instance['height_other'] ."; "; 158 | } else { 159 | $style_height = " height: ". $instance['height'] ."; "; 160 | } 161 | } 162 | else 163 | $style_height = " height: 200px; "; 164 | 165 | if ((isset($instance['show_y_scroll'])) && ($instance['show_y_scroll'] == "on")) 166 | $style_scroll = " overflow-y:scroll;"; 167 | else 168 | $style_scroll = ""; 169 | 170 | $container_style = ' style="'. $style_height . $style_scroll .' "'; 171 | ?> 172 |
    > 173 | 174 |
175 | 191 | 218 | "; print_r($new_instance); echo ""; 231 | //echo "old_instance
"; print_r($old_instance); echo "
"; 232 | //die(); 233 | 234 | $instance = $old_instance; 235 | 236 | // First thing we want to do is delete the existing transients 237 | delete_transient( 'live_stream_widget_content_item_'. $this->number ); 238 | 239 | if (isset($instance['content_terms'])) { 240 | foreach($instance['content_terms'] as $tax_slug => $tax_terms) { 241 | // Ignore the _select_all_ tax_slug 242 | if ($tax_slug == "_select_all_") continue; 243 | 244 | delete_transient( 'live_stream_widget_terms_'. $instance['show_users_content'] .'_'. $tax_slug ); 245 | } 246 | } 247 | 248 | if (isset($new_instance['title'])) 249 | $instance['title'] = strip_tags($new_instance['title']); 250 | 251 | if ( (isset($new_instance['height'])) && (strlen($new_instance['height'])) ) 252 | $instance['height'] = strip_tags($new_instance['height']); 253 | 254 | if ($instance['height'] == "other") { 255 | if ( (isset($new_instance['height_other'])) && (strlen($new_instance['height_other'])) ) { 256 | $instance['height_other'] = strip_tags($new_instance['height_other']); 257 | } else { 258 | unset($instance['height']); 259 | } 260 | } else { 261 | unset($instance['height_other']); 262 | } 263 | 264 | if (isset($new_instance['content_types'])) { 265 | $instance['content_types'] = array(); 266 | 267 | if (count($new_instance['content_types'])) { 268 | foreach($new_instance['content_types'] as $content_type) { 269 | if (strlen($content_type)) 270 | $instance['content_types'][] = $content_type; 271 | } 272 | } 273 | } else { 274 | $instance['content_types'] = array(); 275 | } 276 | 277 | if (isset($new_instance['show_live'])) 278 | $instance['show_live'] = esc_attr($new_instance['show_live']); 279 | else 280 | $instance['show_live'] = 'loop'; 281 | 282 | 283 | if (isset($new_instance['content_terms'])) 284 | $instance['content_terms'] = $new_instance['content_terms']; 285 | else 286 | $instance['content_terms'] = array(); 287 | 288 | if ((isset($new_instance['show_avatar'])) && ($new_instance['show_avatar'] == "on")) 289 | $instance['show_avatar'] = $new_instance['show_avatar']; 290 | else 291 | $instance['show_avatar'] = ''; 292 | 293 | if ((isset($new_instance['link_target'])) && ($new_instance['link_target'] == "on")) 294 | $instance['link_target'] = $new_instance['link_target']; 295 | else 296 | $instance['link_target'] = ''; 297 | 298 | if (isset($new_instance['show_users_content'])) { 299 | $instance['show_users_content'] = esc_attr($new_instance['show_users_content']); 300 | if (($instance['show_users_content'] != 'local') && ($instance['show_users_content'] != 'site') && ($instance['show_users_content'] != "all")) 301 | $instance['show_users_content'] = 'local'; 302 | } 303 | else 304 | $instance['show_users_content'] = 'local'; 305 | 306 | if (isset($new_instance['items_number'])) 307 | $instance['items_number'] = $new_instance['items_number']; 308 | 309 | if (isset($new_instance['content_chars'])) 310 | $instance['content_chars'] = $new_instance['content_chars']; 311 | 312 | if ((isset($new_instance['show_y_scroll'])) && ($new_instance['show_y_scroll'] == "on")) 313 | $instance['show_y_scroll'] = $new_instance['show_y_scroll']; 314 | else 315 | $instance['show_y_scroll'] = ''; 316 | 317 | if (isset($new_instance['interval_seconds'])) { 318 | $instance['interval_seconds'] = intval($new_instance['interval_seconds']); 319 | if (!$instance['interval_seconds']) 320 | $instance['interval_seconds'] = 3; 321 | } 322 | 323 | //echo "instance
"; print_r($instance); echo "
"; 324 | //die(); 325 | return $instance; 326 | } 327 | 328 | 329 | /** 330 | * Displays the widget settings controls on the widget panel. 331 | * Make use of the get_field_id() and get_field_name() function 332 | * when creating your form elements. This handles the confusing stuff. 333 | */ 334 | function form( $instance ) { 335 | 336 | /* Default widget settings. */ 337 | $defaults = array( 338 | 'title' => '', 339 | 'show_avatar' => 'on', 340 | 'link_target' => '', 341 | 'show_users_content' => 'local', 342 | 'height' => '200px', 343 | 'height_other' => '', 344 | 'items_number' => '25', 345 | 'content_chars' => '0', 346 | 'show_y_scroll' => '', 347 | 'show_live' => 'loop', 348 | 'interval_seconds' => 3, 349 | 'content_types' => array('post', 'comment'), 350 | 'content_terms' => array() 351 | ); 352 | 353 | $instance = wp_parse_args( (array) $instance, $defaults ); 354 | 355 | $this->show_widget_admin_title($instance); 356 | $this->show_widget_admin_content_source($instance); 357 | $this->show_widget_admin_content_types($instance); 358 | $this->show_widget_admin_content_terms($instance); 359 | $this->show_widget_admin_live_scroll($instance); 360 | $this->show_widget_admin_height_option($instance); 361 | $this->show_widget_admin_content_item_count($instance); 362 | $this->show_widget_admin_content_char_count($instance); 363 | $this->show_widget_admin_interval_seconds($instance); 364 | $this->show_widget_admin_avatars($instance); 365 | $this->show_widget_admin_link_target($instance); 366 | $this->show_widget_admin_scrollbars($instance); 367 | 368 | } 369 | 370 | function show_widget_admin_title($instance) { 371 | ?> 372 |

373 | 375 |

376 | 381 |

382 | id="get_field_id( 'show_avatar' ); ?>" name="get_field_name( 'show_avatar' ); ?>" /> 383 | 384 |

385 | 390 |

391 | id="get_field_id( 'link_target' ); ?>" name="get_field_name( 'link_target' ); ?>" /> 392 | 393 |

394 | 399 |

401 | 404 |

405 | 410 |

412 | 415 |

416 | 425 |

427 | 428 | 435 |

436 | 442 |

443 | id="get_field_id( 'show_y_scroll' ); ?>" name="get_field_name( 'show_y_scroll' ); ?>" /> 444 | 445 |

446 | 451 |

453 | 456 |

457 | 462 |

464 | 465 | 476 |

483 | 492 |

493 | __('Local - Content from only this site.', 'live-stream-widget'), 504 | 'site' => __('Site - Content from all sites created by users from this site.', 'live-stream-widget'), 505 | 'all' => __('All - Content by all users from all sites', 'live-stream-widget') 506 | ); 507 | 508 | if ( (function_exists('is_edublogs')) && (is_edublogs()) ) { 509 | unset($source_content_array['all']); 510 | } 511 | 512 | ?> 513 |

535 | 537 | 550 |

551 | 'names', 'include' => $selected_term_ids, 'hide_empty' => false)); 581 | } else { 582 | foreach($tax_terms as $idx => $term) { 583 | if (array_search($term->term_id, $selected_term_ids) !== false) { 584 | $selected_term_names[] = $term->name; 585 | } 586 | } 587 | } 588 | } 589 | 590 | // Set our default taxonomy if nothing is yet set for this taxonomy. Will set the 'Select all' checkbox on initial load. 591 | // if ((!isset($instance['content_terms']['_select_all_'][$tax_slug])) 592 | // && ((!isset($instance['content_terms'][$tax_slug])) || (!count($instance['content_terms'][$tax_slug])))) { 593 | // $instance['content_terms']['_select_all_'][$tax_slug] = "on"; 594 | // } 595 | ?> 596 |

598 | name="get_field_name( 'content_terms' ); ?>[_select_all_][]" type="checkbox"> - labels->name; ?> 601 | 602 | 603 |

631 | 'parent', 'id' => 'term_id'); //TODO: decouple this 641 | var $field_name_prefix; 642 | var $field_id_prefix; 643 | 644 | function start_lvl(&$output, $depth = 0, $args = array()) { 645 | $indent = str_repeat("\t", $depth); 646 | $output .= "$indent
    \n"; 647 | } 648 | 649 | function end_lvl(&$output, $depth = 0, $args = array()) { 650 | $indent = str_repeat("\t", $depth); 651 | $output .= "$indent
\n"; 652 | } 653 | 654 | function start_el(&$output, $category, $depth = 0, $args = array(), $id = 0) { 655 | extract($args); 656 | if ( empty($taxonomy) ) 657 | $taxonomy = 'category'; 658 | 659 | $name = $this->field_name_prefix; 660 | 661 | $class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : ''; 662 | $output .= '
  • 663 | '; 672 | } 673 | 674 | function end_el(&$output, $category, $depth = 0, $args = array(), $id = 0) { 675 | $output .= "
  • \n"; 676 | } 677 | } 678 | 679 | function get_source_tax_terms($tax_slug, $show_users_content='local') { 680 | global $wpdb; 681 | 682 | $content_source = ''; 683 | 684 | if (($show_users_content == "local")) 685 | $content_source = "local"; 686 | else 687 | $content_source = "site"; 688 | 689 | $post_indexer_plugin = has_post_indexer_plugin(); 690 | $comment_indexer_plugin = has_comment_indexer_plugin(); 691 | 692 | $trans_key = 'live_stream_widget_terms_'. $content_source .'_'. $tax_slug; 693 | 694 | if ( ($content_source == "local") 695 | || (!$post_indexer_plugin) && (!$comment_indexer_plugin) ) { 696 | 697 | $tax_terms = get_transient( $trans_key ); 698 | if ($tax_terms !== false) 699 | return $tax_terms; 700 | 701 | $tax_terms = (array) get_terms($tax_slug, array('get' => 'all', 'hide_empty' => 0)); 702 | if ( is_wp_error($tax_terms) ) 703 | return false; 704 | 705 | set_transient( $trans_key, $tax_terms, 300 ); 706 | 707 | return $tax_terms; 708 | 709 | } else { 710 | 711 | $trans_key = 'live_stream_widget_terms_'. $content_source .'_'. $tax_slug; 712 | $tax_terms = get_site_transient( $trans_key ); 713 | if ($tax_terms !== false) 714 | return $tax_terms; 715 | 716 | if ($post_indexer_plugin === 2) { 717 | 718 | $select_query_str = "SELECT * FROM ". $wpdb->base_prefix . "site_terms "; 719 | $where_query_str = " WHERE type IN ('". $tax_slug ."') "; 720 | $orderby_query_str = " ORDER BY name "; 721 | $query_str = $select_query_str . $where_query_str . $orderby_query_str; 722 | $tax_terms = $wpdb->get_results($query_str); 723 | } else if (($post_indexer_plugin === 3) && (class_exists('postindexermodel'))) { 724 | 725 | $model = new postindexermodel(); 726 | $select_query_str = "SELECT t.term_id term_id, t.name name, t.slug slug, tt.count count FROM ". 727 | $model->network_terms ." AS t INNER JOIN ". $model->network_term_taxonomy 728 | ." AS tt ON t.term_id = tt.term_id"; 729 | $where_query_str = " WHERE tt.taxonomy IN ('". $tax_slug ."') "; 730 | $orderby_query_str = " ORDER BY name "; 731 | $query_str = $select_query_str . $where_query_str . $orderby_query_str; 732 | $tax_terms = $wpdb->get_results($query_str); 733 | } 734 | 735 | // When we read from the Post Indexer term table we don't get the parent field. This is required when we call the WP Walker class 736 | if ((isset($tax_terms)) && (count($tax_terms))) { 737 | foreach($tax_terms as $idx => $term) { 738 | $tax_terms[$idx]->parent = 0; 739 | } 740 | } else { 741 | $tax_terms = array(); 742 | } 743 | set_site_transient( $trans_key, $tax_terms, 300 ); 744 | 745 | return $tax_terms; 746 | } 747 | } 748 | 749 | function get_instance_user_content($instance) { 750 | 751 | if ( (!has_post_indexer_plugin()) && (!has_comment_indexer_plugin()) ) { 752 | return 'local'; 753 | } 754 | 755 | return $instance['show_users_content']; 756 | } 757 | 758 | /** 759 | * This utility function checks if the Post Indexer plugin is installed. 760 | * 761 | * @since 1.0.1 762 | * @see 763 | * 764 | * @param none 765 | * @return true if Post Indexer plugin is installed. false is not 766 | */ 767 | 768 | function has_post_indexer_plugin() { 769 | global $post_indexer_current_version; 770 | 771 | if ((isset($post_indexer_current_version)) && (!empty($post_indexer_current_version))) { 772 | return 2; 773 | } 774 | 775 | else if (class_exists('postindexermodel')) { 776 | return 3; 777 | } 778 | return false; 779 | } 780 | 781 | /** 782 | * This utility function checks if the Comment Indexer plugin is installed. 783 | * 784 | * @since 1.0.1 785 | * @see 786 | * 787 | * @param none 788 | * @return true if Comment Indexer plugin is installed. false is not 789 | */ 790 | function has_comment_indexer_plugin() { 791 | if (function_exists('comment_indexer_comment_insert_update')) 792 | return true; 793 | 794 | return false; 795 | } 796 | 797 | /** 798 | * Get the user_id of users for current blog. This will be used to filter the displayed items. 799 | * 800 | * @since 1.0.0 801 | * @see 802 | * 803 | * @param none 804 | * @return array of post_terms 805 | */ 806 | 807 | function live_stream_get_site_user_ids($instance, $widget_id) { 808 | global $wpdb; 809 | 810 | if ( $user_ids = get_site_transient( 'live_stream_widget_user_ids_'. $widget_id ) ) { 811 | return $user_ids; 812 | } 813 | 814 | $site_admin_ids = array(); 815 | 816 | $site_admins_logins = get_super_admins(); 817 | if ($site_admins_logins) { 818 | foreach($site_admins_logins as $site_admins_login) { 819 | $user = get_user_by('login', $site_admins_login); 820 | if (intval($user->ID)) { 821 | 822 | $blogs = get_blogs_of_user( $user->ID ); 823 | 824 | if (($blogs) && (isset($blogs[$wpdb->blogid]))) { 825 | $site_admin_ids[] = $user->ID; 826 | } 827 | } 828 | } 829 | } 830 | 831 | $user_args = array( 832 | 'number' => 0, 833 | 'blog_id' => $wpdb->blogid, 834 | 'fields' => array('ID') 835 | ); 836 | $wp_user_search = new WP_User_Query( $user_args ); 837 | $users_tmp = $wp_user_search->get_results(); 838 | if ($users_tmp) { 839 | $user_ids = array(); 840 | foreach($users_tmp as $user) { 841 | $user_ids[] = $user->ID; 842 | } 843 | } 844 | //echo "site_admin_ids
    "; print_r($site_admin_ids); echo "
    "; 845 | //echo "user_ids
    "; print_r($user_ids); echo "
    "; 846 | 847 | $all_user_ids = array_unique(array_merge($user_ids, $site_admin_ids)); 848 | //echo "all_user_ids
    "; print_r($all_user_ids); echo "
    "; 849 | set_site_transient( 'live_stream_widget_user_ids_'. $widget_id, $all_user_ids, 300); 850 | return $all_user_ids; 851 | } 852 | 853 | /** 854 | * This function queries the site post and comments tables populated by the PostIndexer and CommentIndexer plugins 855 | * The queries result is used to display the front-end items to the users. 856 | * 857 | * @since 1.0.0 858 | * @see 859 | * 860 | * @param $instance Widget instance 861 | * @return array of post_terms 862 | */ 863 | 864 | function live_stream_get_post_items($instance, $widget_id=0) { 865 | 866 | global $wpdb; 867 | 868 | if ( $all_items = get_transient( 'live_stream_widget_content_item_'. $widget_id ) ) { 869 | return $all_items; 870 | } 871 | 872 | $post_items = array(); 873 | $comment_items = array(); 874 | $all_items = array(); 875 | $post_ids = array(); 876 | $tax_query = array(); 877 | 878 | // Some defaults for us. 879 | if (!isset($instance['show_users_content'])) 880 | $instance['show_users_content'] = "local"; 881 | 882 | if ((!isset($instance['content_types'])) || (!count($instance['content_types']))) 883 | $instance['content_types'] = array('post', 'comment'); 884 | 885 | if ((!isset($instance['items_number'])) || (intval($instance['items_number']) < 2)) 886 | $instance['items_number'] = 1; 887 | 888 | $content_source = 'local'; 889 | if (($instance['show_users_content'] == '') || ($instance['show_users_content'] == "local")) 890 | $content_source = "local"; 891 | else 892 | $content_source = "site"; 893 | 894 | if ($instance['show_users_content'] == "site") 895 | $user_ids = live_stream_get_site_user_ids($instance, $widget_id); 896 | 897 | $post_indexer_plugin = has_post_indexer_plugin(); 898 | if ((!$post_indexer_plugin) && ($content_source != "local")) 899 | $content_source = 'local'; 900 | 901 | $tax_terms_query_str = ''; 902 | if ( (isset($instance['content_terms'])) && (count($instance['content_terms'])) ) { 903 | //echo "content_terms
    "; print_r($instance['content_terms']); echo "
    "; 904 | //die(); 905 | 906 | $tax_terms_array = array(); 907 | 908 | foreach($instance['content_terms'] as $tax_slug => $tax_terms) { 909 | 910 | //echo "tax_slug=[". $tax_slug ."]
    "; 911 | //echo "tax_terms
    "; print_r($tax_terms); echo "
    "; 912 | //continue; 913 | 914 | // Ignore our secret tax_slug. This is where we store the option to select all terms 915 | if ($tax_slug == "_select_all_") 916 | continue; 917 | 918 | // If the user selected the 'select all' checkbox on the terms set then we can ignore the taxonomy terms selected 919 | if (!isset($instance['content_terms']['_select_all_'][$tax_slug])) { 920 | 921 | if (!isset($tax_terms_array[$tax_slug])) 922 | $tax_terms_array[$tax_slug] = array(); 923 | 924 | $tax_terms_array[$tax_slug] = $tax_terms; 925 | } 926 | } 927 | 928 | if (count($tax_terms_array)) { 929 | foreach($tax_terms_array as $tax_slug => $tax_set) { 930 | if (!count($tax_set)) continue; 931 | 932 | if (($content_source == "local") || (($post_indexer_plugin === 3) && (class_exists('Network_Query')))) { 933 | $tax_query_item = array( 934 | 'taxonomy' => $tax_slug, 935 | 'field' => 'id', 936 | 'terms' => $tax_set 937 | ); 938 | $tax_query[] = $tax_query_item; 939 | } else { 940 | foreach($tax_set as $term_id) { 941 | if (strlen($tax_terms_query_str)) $tax_terms_query_str .= " OR "; 942 | $tax_terms_query_str .= " p.post_terms like '%|". $term_id ."|%' "; 943 | } 944 | } 945 | } 946 | } 947 | } 948 | 949 | if ( (isset($instance['content_types'])) && (array_search('post', $instance['content_types']) !== false) ) { 950 | 951 | if ($content_source == "local") { 952 | 953 | $post_query_args = array( 954 | 'post_type' => $instance['content_types'], 955 | 'post_status' => 'publish', 956 | 'posts_per_page' => $instance['items_number'], 957 | 'orderby' => 'date', 958 | 'order' => 'DESC' 959 | ); 960 | 961 | if ((isset($tax_query)) && (count($tax_query))) { 962 | $tax_query['relation'] = 'OR'; 963 | $post_query_args['tax_query'] = $tax_query; 964 | } 965 | 966 | // There is no provision in the WP_Query object to say "greater than date". So have to hack the WHERE 967 | if ((isset($instance['timekey'])) && (intval($instance['timekey']))) { 968 | add_filter( 'posts_where', 'live_stream_filter_posts_timekey_where' ); 969 | } 970 | //echo "post_query_args
    "; print_r($post_query_args); echo "
    "; 971 | 972 | $post_query = new WP_Query($post_query_args); 973 | 974 | if ((isset($instance['timekey'])) && (intval($instance['timekey']))) { 975 | remove_filter( 'posts_where', 'live_stream_filter_posts_timekey_where' ); 976 | } 977 | 978 | if (($post_query->posts) && (count($post_query->posts))) { 979 | foreach($post_query->posts as $post_item) { 980 | $post_item->post_id = $post_item->ID; 981 | $post_item->blog_id = $wpdb->blogid; 982 | $post_item->post_author_id = $post_item->post_author; 983 | $post_item->post_permalink = get_permalink($post_item->ID); 984 | $post_item->post_published_stamp = strtotime($post_item->post_date_gmt); 985 | 986 | $post_ids[] = $post_item->post_id; 987 | $all_items[$post_item->post_published_stamp] = $post_item; 988 | } 989 | } 990 | } else { 991 | 992 | if ($post_indexer_plugin === 2) { 993 | $select_query_str = "SELECT 994 | p.site_post_id, 995 | p.blog_id as blog_id, 996 | p.post_id as post_id, 997 | p.post_author as post_author_id, 998 | p.post_type as post_type, 999 | p.post_title as post_title, 1000 | p.post_content as post_content, 1001 | p.post_permalink as post_permalink, 1002 | p.post_published_stamp as post_published_stamp 1003 | FROM ". $wpdb->base_prefix . "site_posts p"; 1004 | 1005 | $where_query_str = "WHERE 1"; 1006 | 1007 | if ((isset($instance['timekey'])) && (intval($instance['timekey']))) { 1008 | $where_query_str .= " AND p.post_published_stamp > ". $instance['timekey']; 1009 | } 1010 | 1011 | if (($instance['show_users_content'] == "site") && (isset($user_ids)) && (count($user_ids))) { 1012 | $where_query_str .= " AND p.post_author IN (". implode(',', $user_ids) .") "; 1013 | } 1014 | 1015 | if (strlen($tax_terms_query_str)) { 1016 | $where_query_str .= " AND (". $tax_terms_query_str .") "; 1017 | } 1018 | 1019 | if ($instance['show_users_content'] == "local") { 1020 | $where_query_str .= " AND p.blog_id=". $wpdb->blogid ." "; 1021 | } 1022 | 1023 | $content_types_str = ''; 1024 | if ((isset($instance['content_types'])) && (count($instance['content_types']))) { 1025 | foreach($instance['content_types'] as $type) { 1026 | if (strlen($content_types_str)) 1027 | $content_types_str .= ","; 1028 | 1029 | $content_types_str .= "'". $type ."'"; 1030 | } 1031 | 1032 | if (strlen($content_types_str)) { 1033 | $where_query_str .= " AND p.post_type IN (". $content_types_str .") "; 1034 | } 1035 | } 1036 | 1037 | $orderby_query_str = " ORDER BY p.post_published_stamp DESC"; 1038 | $limit_query_str = " LIMIT ". $instance['items_number']; 1039 | 1040 | $query_str = $select_query_str ." ". $where_query_str ." ". $orderby_query_str ." ". $limit_query_str; 1041 | $post_items = $wpdb->get_results($query_str); 1042 | if ((isset($post_items)) && (count($post_items))) { 1043 | foreach($post_items as $item) { 1044 | $post_ids[] = $item->post_id; 1045 | $all_items[$item->post_published_stamp] = $item; 1046 | } 1047 | } 1048 | 1049 | } else if (($post_indexer_plugin === 3) && (class_exists('Network_Query'))) { 1050 | 1051 | $post_query_args = array( 1052 | 'post_type' => $instance['content_types'], 1053 | 'post_status' => 'publish', 1054 | 'posts_per_page' => $instance['items_number'], 1055 | 'orderby' => 'date', 1056 | 'order' => 'DESC' 1057 | ); 1058 | 1059 | if ($instance['show_users_content'] == "local") { 1060 | $post_query_args['blog_id'] = $wpdb->blogid; 1061 | } 1062 | 1063 | if ((isset($tax_query)) && (count($tax_query))) { 1064 | $tax_query['relation'] = 'OR'; 1065 | $post_query_args['tax_query'] = $tax_query; 1066 | } 1067 | 1068 | // There is n provision in the WP_Query object to say "greater than date". So have to hack the WHERE 1069 | if ((isset($instance['timekey'])) && (intval($instance['timekey']))) { 1070 | add_filter( 'posts_where', 'live_stream_filter_posts_timekey_where' ); 1071 | } 1072 | 1073 | // We need to turn off error_reporting to prevent Notices showing in case user has full reporting turned on. 1074 | $current_error_reporting = error_reporting(); 1075 | error_reporting(0); 1076 | $post_query = new Network_Query($post_query_args); 1077 | error_reporting($current_error_reporting); 1078 | 1079 | if ((isset($instance['timekey'])) && (intval($instance['timekey']))) { 1080 | remove_filter( 'posts_where', 'live_stream_filter_posts_timekey_where' ); 1081 | } 1082 | if (($post_query->posts) && (count($post_query->posts))) { 1083 | foreach($post_query->posts as $post_item) { 1084 | $post_item->post_id = $post_item->ID; 1085 | $post_item->blog_id = $post_item->BLOG_ID; 1086 | $post_item->post_author_id = $post_item->post_author; 1087 | $post_item->post_permalink = network_get_permalink( $post_item->BLOG_ID, $post_item->ID); 1088 | $post_item->post_published_stamp = strtotime($post_item->post_date_gmt); 1089 | if (strlen($post_item->post_excerpt)) 1090 | $post->post_content = $post_item->post_excerpt; 1091 | 1092 | $post_ids[] = $post_item->post_id; 1093 | $all_items[$post_item->post_published_stamp] = $post_item; 1094 | } 1095 | } 1096 | } 1097 | } 1098 | } 1099 | 1100 | /* Get the comments */ 1101 | if ( (isset($instance['content_types'])) && (array_search('comment', $instance['content_types']) !== false) ) { 1102 | 1103 | if ($content_source == "local") { 1104 | $select_query_str = "SELECT 1105 | c.comment_post_ID as post_id, 1106 | c.user_id as post_author_id, 1107 | c.comment_content as comment_content, 1108 | c.comment_author as post_author_name, 1109 | c.comment_author_email as post_author_email, 1110 | c.comment_date_gmt as post_published_stamp, 1111 | c.comment_ID as comment_id 1112 | 1113 | FROM ". $wpdb->prefix ."comments c"; 1114 | $where_query_str = ' WHERE 1 '; 1115 | $where_query_str .= " AND c.comment_approved = 1 "; 1116 | 1117 | if ((isset($instance['timekey'])) && (intval($instance['timekey']))) { 1118 | $where_query_str .= " AND post_published_stamp > ". $instance['timekey']; 1119 | } 1120 | 1121 | $orderby_query_str = ' ORDER BY c.comment_date_gmt DESC'; 1122 | $limit_query_str = " LIMIT ". $instance['items_number']; 1123 | 1124 | $query_str = $select_query_str ." ". $where_query_str ." ". $orderby_query_str ." ". $limit_query_str; 1125 | //echo "query_str=[". $query_str ."]
    "; 1126 | $comment_items = $wpdb->get_results($query_str); 1127 | 1128 | if ($comment_items) { 1129 | foreach($comment_items as $item) { 1130 | 1131 | $item->post_type = "comment"; 1132 | $item->blog_id = $wpdb->blogid; 1133 | $item->post_title = get_the_title($item->post_id); 1134 | $item->post_permalink = get_permalink($item->post_id); 1135 | $item->post_published_stamp = strtotime($item->post_published_stamp); 1136 | 1137 | $all_items[$item->post_published_stamp] = $item; 1138 | } 1139 | } 1140 | } else { 1141 | if ($post_indexer_plugin === 2) { 1142 | 1143 | $select_query_str = "SELECT 1144 | c.blog_id as blog_id, 1145 | c.comment_post_id as post_id, 1146 | c.comment_author_user_id as post_author_id, 1147 | c.comment_author as post_author_name, 1148 | c.comment_author_email as post_author_email, 1149 | p.post_title as post_title, 1150 | c.comment_content as comment_content, 1151 | c.comment_post_permalink as post_permalink, 1152 | c.comment_date_stamp as post_published_stamp, 1153 | c.comment_id as comment_id 1154 | FROM ". $wpdb->base_prefix . "site_comments c INNER JOIN ". $wpdb->base_prefix . 1155 | "site_posts p ON c.comment_post_id=p.post_id AND c.blog_id=p.blog_id "; 1156 | 1157 | } else if (($post_indexer_plugin === 3) && (class_exists('postindexermodel'))) { 1158 | 1159 | $model = new postindexermodel(); 1160 | 1161 | $select_query_str = "SELECT 1162 | c.blog_id as blog_id, 1163 | c.comment_post_id as post_id, 1164 | c.comment_author_user_id as post_author_id, 1165 | c.comment_author as post_author_name, 1166 | c.comment_author_email as post_author_email, 1167 | p.post_title as post_title, 1168 | c.comment_content as comment_content, 1169 | c.comment_post_permalink as post_permalink, 1170 | c.comment_date_stamp as post_published_stamp, 1171 | c.comment_id as comment_id 1172 | FROM ". $wpdb->base_prefix . "site_comments c INNER JOIN ". 1173 | $model->network_posts . " p ON c.comment_post_id=p.ID AND c.blog_id=p.BLOG_ID "; 1174 | } 1175 | if ((isset($select_query_str)) && (!empty($select_query_str))) { 1176 | 1177 | $where_query_str = 'WHERE 1 '; 1178 | $where_query_str .= " AND c.comment_approved = 1 "; 1179 | 1180 | if ((isset($instance['timekey'])) && (intval($instance['timekey']))) { 1181 | $where_query_str .= " AND p.post_published_stamp > ". $instance['timekey']; 1182 | } 1183 | 1184 | if (($instance['show_users_content'] == "site") && (isset($user_ids)) && (count($user_ids))) 1185 | $where_query_str .= " AND c.comment_author_user_id IN (". implode(',', $user_ids) .") "; 1186 | 1187 | // if ($instance['show_users_content'] == "local") 1188 | // $where_query_str .= " AND c.blog_id=". $wpdb->blogid ." "; 1189 | // else 1190 | // $where_query_str .= " AND c.blog_id = p.blog_id "; 1191 | 1192 | if ( (isset($terms_query_str)) && (strlen($terms_query_str)) ) { 1193 | $where_query_str .= " AND (". $terms_query_str .") "; 1194 | } 1195 | 1196 | $orderby_query_str = ' ORDER BY c.comment_date_stamp DESC'; 1197 | $limit_query_str = " LIMIT ". $instance['items_number']; 1198 | 1199 | $query_str = $select_query_str ." ". $where_query_str ." ". $orderby_query_str ." ". $limit_query_str; 1200 | $comment_items = $wpdb->get_results($query_str); 1201 | if ($comment_items) { 1202 | foreach($comment_items as $item) { 1203 | 1204 | $item->post_type = "comment"; 1205 | $all_items[$item->post_published_stamp] = $item; 1206 | } 1207 | } 1208 | 1209 | } 1210 | } 1211 | } 1212 | 1213 | if (($all_items) && (count($all_items))) { 1214 | ksort($all_items); 1215 | krsort($all_items); 1216 | } 1217 | 1218 | if (count($all_items) > $instance['items_number']) { 1219 | $all_items = array_slice($all_items, 0, $instance['items_number'], true); 1220 | } 1221 | 1222 | if ( (isset($instance['show_live'])) && ($instance['show_live'] == "live") ) { 1223 | // If we are showing 'live' content (AJAX) polling we set the transient timeout low. 1224 | set_transient( 'live_stream_widget_content_item_'. $widget_id, $all_items, intval($instance['interval_seconds'])+1 ); 1225 | } else { 1226 | // But for looping we set this longer. 1227 | set_transient( 'live_stream_widget_content_item_'. $widget_id, $all_items, 30 ); 1228 | } 1229 | 1230 | return $all_items; 1231 | } 1232 | 1233 | /** 1234 | * This filter is used when the source is 'local'. Since that option uses the WP_Query to access Posts we needed 1235 | * a way to tell WP_Query to only pull posts with GMT post_data newer than a given timestamp ($_POST['timekey']) 1236 | * 1237 | * @since 1.0.1 1238 | * @see 1239 | * 1240 | * @param string $where from WP_Query 1241 | * @return string $$where modified. 1242 | */ 1243 | function live_stream_filter_posts_timekey_where( $where = '' ) { 1244 | if (isset($_POST['timekey'])) { 1245 | $timekey = intval($_POST['timekey']); 1246 | 1247 | $where .= " AND post_date_gmt > '" . date('Y-m-d H:i:s', $timekey) . "' "; 1248 | } 1249 | return $where; 1250 | } 1251 | 1252 | 1253 | /** 1254 | * This function is given an array of items in which will be build the output list items for display 1255 | * 1256 | * @since 1.0.0 1257 | * @see 1258 | * 1259 | * @param object $instance This is the Widget instance. 1260 | * @param array $items The items result from the live_stream_get_post_items(); return; 1261 | * @param bool $echo true to echo the output or false to return the output 1262 | * @return string $items_output returned IF $echo is false. 1263 | */ 1264 | 1265 | function live_stream_build_display($instance, $items, $echo = true) { 1266 | 1267 | if ( (!$items) || (!is_array($items)) || (!count($items)) ) return; 1268 | // echo "instance
    "; print_r($instance); echo "
    "; 1269 | // echo "items
    "; print_r($items); echo "
    "; 1270 | // die(); 1271 | 1272 | krsort($items); 1273 | $items_output = ''; 1274 | 1275 | $blogs = array(); 1276 | 1277 | //echo "instance
    "; print_r($instance); echo "
    "; 1278 | foreach($items as $key => $item) { 1279 | 1280 | if (isset($_POST['timekey'])) { 1281 | if (intval( intval( $key ) <= $_POST['timekey'] ) ) 1282 | continue; 1283 | } 1284 | 1285 | if (is_multisite()) { 1286 | if ((isset($item->blog_id)) && (intval($item->blog_id))) { 1287 | $blog_id = $item->blog_id; 1288 | 1289 | if (isset($blogs[intval($item->blog_id)])) { 1290 | $blog = $blogs[intval($item->blog_id)]; 1291 | } else { 1292 | $blog = get_blog_details($item->blog_id); 1293 | if ($blog) { 1294 | $blogs[intval($item->blog_id)] = $blog; 1295 | } else { 1296 | unset($blog); 1297 | } 1298 | } 1299 | } 1300 | } else { 1301 | $blog = new stdClass; 1302 | $blog->blogname = get_option( 'blogname' ); 1303 | $blog->siteurl = get_option( 'siteurl' ); 1304 | //echo "blog
    "; print_r($blog); echo "
    "; 1305 | } 1306 | 1307 | $wrapper_class = "live-stream-item-". $item->post_type; 1308 | if ((isset($instance['show_avatar'])) && ($instance['show_avatar'] == "on")) { 1309 | $wrapper_class = " live-stream-text-has-avatar"; 1310 | } 1311 | 1312 | if ((isset($instance['link_target'])) && ($instance['link_target'] == "on")) { 1313 | $link_target = ' target="_blank" '; 1314 | } else { 1315 | $link_target = ''; 1316 | } 1317 | 1318 | $item_output = '
  • '; 1319 | 1320 | $user_data = array(); 1321 | 1322 | if (intval($item->post_author_id) ) { 1323 | $userdata = get_userdata( intval($item->post_author_id) ); 1324 | if ($userdata) { 1325 | $user_data['ID'] = $userdata->ID; 1326 | $user_data['user_email'] = $userdata->user_email; 1327 | $user_data['display_name'] = $userdata->display_name; 1328 | } 1329 | } 1330 | 1331 | if (!isset($user_data['ID'])) 1332 | $user_data['ID'] = 0; 1333 | 1334 | if (!isset($user_data['user_email'])) { 1335 | if ((isset($item->post_author_email)) && (strlen($item->post_author_email))) { 1336 | $user_data['user_email'] = $item->post_author_email; 1337 | } else { 1338 | $user_data['user_email'] = ''; 1339 | } 1340 | } 1341 | 1342 | if (!isset($user_data['display_name'])) { 1343 | 1344 | if ((isset($item->post_author_name)) && (strlen($item->post_author_name))) { 1345 | $user_data['display_name'] = $item->post_author_name; 1346 | } else { 1347 | $user_data['display_name'] = ''; 1348 | } 1349 | } 1350 | 1351 | /* Build an anchor wrapper for the author which is used in multiple places */ 1352 | if ((isset($blog->siteurl)) && (intval($item->post_author_id) )) { 1353 | $author_anchor_begin = ''; 1355 | $author_anchor_end = ''; 1356 | 1357 | } else { 1358 | if ($item->post_type == "comment") { 1359 | $author_anchor_begin = ''; 1360 | $author_anchor_end = ''; 1361 | } else { 1362 | $author_anchor_begin = ''; 1363 | $author_anchor_end = ''; 1364 | } 1365 | } 1366 | 1367 | /* User Avatar */ 1368 | if ((isset($instance['show_avatar'])) && ($instance['show_avatar'] == "on")) { 1369 | if ((isset($user_data['user_email'])) && (strlen($user_data['user_email']))) { 1370 | $avatar = get_avatar($user_data['user_email'], 30, null, $user_data['display_name']); 1371 | } else { 1372 | $avatar = get_avatar("dummy@dummy.com", 30, null, $user_data['display_name']); 1373 | } 1374 | $avatar = get_avatar($user_data['user_email'], 30, null, $user_data['display_name']); 1375 | if (!empty($avatar)) { 1376 | $item_output .= '
    '; 1377 | $item_output .= $author_anchor_begin . $avatar . $author_anchor_end; 1378 | $item_output .= '
    '; 1379 | } 1380 | } 1381 | 1382 | /* Begin text container wrapper */ 1383 | $item_output .= '
    '; 1384 | 1385 | 1386 | /* Show the User Name */ 1387 | if (isset($user_data['display_name'])) 1388 | $item_output .= $author_anchor_begin . $user_data['display_name'] . $author_anchor_end ." "; 1389 | 1390 | $item_content = ''; 1391 | if ((isset($instance['content_chars'])) && (intval($instance['content_chars']))) { 1392 | if ( ($item->post_type == "comment") && (isset($item->comment_content)) && (strlen($item->comment_content)) ) { 1393 | $item_content = strip_tags($item->comment_content); 1394 | } else if ((isset($item->post_content)) && (strlen($item->post_content))) { 1395 | $item_content = strip_tags($item->post_content); 1396 | } 1397 | 1398 | if (strlen($item_content)) { 1399 | $item_content = substr($item_content, 0, $instance['content_chars']); 1400 | $item_content = ''. $item_content .'... '; 1401 | } 1402 | } 1403 | 1404 | if ($item->post_type == "comment") { 1405 | if (strlen($item_output)) 1406 | $item_output .= " "; 1407 | $item_output .= $item_content; 1408 | 1409 | $item_output .= ' '. __("commented on", 'live-stream-widget') .' '; 1410 | 1411 | /* Show the Post Title */ 1412 | if (isset($blogs[$item->blog_id])) { 1413 | if (strlen($item_output)) $item_output .= " "; ; 1414 | $post_anchor_begin = ''; 1415 | $post_anchor_end = ''; 1416 | 1417 | } else { 1418 | $post_anchor_begin = ''; 1419 | $post_anchor_end = ''; 1420 | } 1421 | 1422 | $item_output .= $post_anchor_begin . $item->post_title . $post_anchor_end ." "; 1423 | 1424 | } else { 1425 | if (strlen($item_output)) 1426 | $item_output .= " "; 1427 | $item_output .= $item_content; 1428 | 1429 | $item_output .= ' '. __('published', 'live-stream-widget') .' '; 1430 | 1431 | /* Show the Post Title */ 1432 | if (strlen($item_output)) $item_output .= " "; 1433 | $item_output .= ''. $item->post_title ." "; 1434 | 1435 | //if (strlen($item_content)) $item_output .= " ". $item_content; 1436 | } 1437 | 1438 | 1439 | /* Show the Blog domain */ 1440 | if ((isset($instance['show_users_content'])) && ($instance['show_users_content'] != "local")) { 1441 | if (isset($blog->siteurl)) { 1442 | $site_anchor_begin = ''; 1443 | $site_anchor_end = ''; 1444 | $item_output .= __("via", 'live-stream-widget') ." ". $site_anchor_begin . $blog->blogname . $site_anchor_end ." "; 1445 | } 1446 | } 1447 | 1448 | 1449 | /* Show the Post/Comment human time */ 1450 | $item_output .= ''; 1478 | 1479 | 1480 | 1481 | /* Closing the item text wrapper */ 1482 | $item_output .= '
    '; 1483 | 1484 | $item_output .= '
  • '; 1485 | 1486 | $items_output .= $item_output; 1487 | } 1488 | 1489 | if (strlen($items_output)) { 1490 | if ($echo == true) 1491 | echo $items_output; 1492 | else 1493 | return $items_output; 1494 | } 1495 | } 1496 | 1497 | /** 1498 | * This function handles the AJAX update requests from the front-end widget. The instance ID ($_POST['widget_id']) is passed 1499 | * via $_POST so this means the function can support multiple widgets if needed. 1500 | * 1501 | * @since 1.0.0 1502 | * @see 1503 | * 1504 | * @param none 1505 | * @return none 1506 | */ 1507 | 1508 | function live_stream_update_ajax_proc() { 1509 | 1510 | if (isset($_POST['widget_id'])) 1511 | $widget_id = intval($_POST['widget_id']); 1512 | 1513 | if (isset($_POST['timekey'])) 1514 | $timekey = intval($_POST['timekey']); 1515 | 1516 | if ((isset($widget_id)) && (isset($timekey))) { 1517 | $live_stream_widgets = get_option('widget_live-stream-widget'); 1518 | if (($live_stream_widgets) && (isset($live_stream_widgets[$widget_id]))) { 1519 | $instance = $live_stream_widgets[$widget_id]; 1520 | 1521 | $instance['timekey'] = $timekey; 1522 | $instance['doing_ajax'] = true; 1523 | //$instance['items_number'] = 1; 1524 | 1525 | $items = live_stream_get_post_items($instance); 1526 | if (($items) && (count($items))) { 1527 | //ksort($items); 1528 | 1529 | // We only want to update a single row per a request. Don't want to overwhelm the user. 1530 | $items = array_slice($items, 0, 1, true); 1531 | 1532 | live_stream_build_display($instance, $items, true); 1533 | } 1534 | } 1535 | } 1536 | 1537 | die(); 1538 | } 1539 | 1540 | //function is_edublogs() { return true;} 1541 | --------------------------------------------------------------------------------