: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
startUpdateCycle: function ( id ) {
var updateCycle = setTimeout( function () {
function requestPosts ( id ) {
action: la_plugin_slug_down + '_sources',
$.post( vars.ajaxurl, data ).done( function( feed ) {
var feeds = self.model.get( 'feeds' );
serverFeed = JSON.parse( feed );
console.log( 'Error parsing serverFeed JSON' );
// update feeds model individually
feeds[ serverFeed.id ] = serverFeed;
var changed = self.model.get( 'feeds_changed' );
var state = changed[ id ] && changed[ id ][ 'state' ];
console.log( serverFeed )
console.log( JSON.stringify( changed ) )
if ( serverFeed [ 'status' ] == 1 || serverFeed [ 'status' ] == 0 ) { // feed resolved
// delete specific feed from changed hash because its status resolved
clearTimeout( updateCycle );
updateCycle = setTimeout( function () {
console.log( 'renderBoostsUI changed ')
FlowFlow.renderBoostsUI( self.model );
if ( serverFeed [ 'status' ] != 1 ) {
console.log( 'feed status requestPosts', serverFeed [ 'status' ] )
FlowFlow.showNotification( ( serverFeed [ 'status' ] == 1 ? 'Yay' : 'Something went wrong' ) + '! Feed "<span>' + ( feeds[ id ].type === 'wordpress' ? ( feeds[ id ]['category-name'] || feeds[ id ]['wordpress-type'] ) : feeds[ id ][ 'content' ] ).toUpperCase() + '</span>" ' + ( serverFeed [ 'status' ] == 1 ? 'was successfully' : 'was' ) + ' ' + ( state == 'deleted' ? 'deleted' : ( state == 'created' ? 'created' : 'updated' ) ) + ( serverFeed [ 'status' ] == 1 ? '' : ' with errors' ) + '<i class="flaticon-' + ( serverFeed [ 'status' ] == 1 ? serverFeed [ 'type' ].toLowerCase() : 'error' ) + '"></i>' );
renderFeedsList: function ( changed, errorsOnly, searchTerm ) {
var feeds = this.model.get('feeds');
console.log('renderFeedsList changed', JSON.stringify( changed ));
if ( ! _.isEmpty( feeds ) ) {
_.each( feeds, function ( feed ) {
var uid, enabled, status, lastUpdate;
var $feed, $error, info, prop, ikey, ival, interval;
// if it's in changed hash we are waiting for status resolve
var isChanged = changed && changed[ feed.id ];
// console.log( 'RENDER FEED', isChanged, feed )
if ( _.isArray( feed.errors ) && _.isEmpty( feed.errors) ) {
// pass error feed so it renders when only error feeds are requested
else if ( searchTerm && searchTerm.length > 2 ) {
// filter out all feeds that doesn't match search term
if ( feed.content.indexOf( searchTerm ) == -1 ) {
else if ( feed.page && feed.page != self.currentPage ) { // filter out all feeds not belonging to current page
if ( feed['boosted'] === 'yep' ) settings['boosted'] = feed['boosted'];
if ( feed['type'] === 'rss' ) {
settings['content'] = feed['channel-name'] || feed['content'];
else if ( feed['content'] ) {
settings['content'] = feed['content'];
settings['content'] = feed['category-name'] || feed['wordpress-type'];
if ( feed['timeline-type'] ) settings['timeline-type'] = feed['timeline-type'];
if ( feed['mod'] === 'yep' ) settings['mod'] = feed['mod'];
settings['id'] = 'ID: ' + feed['id'];
type = settings['timeline-type'];
icon = '<i class="flaticon-feed_type_user"></i>';
icon = '<i class="flaticon-feed_type_like"></i>';
icon = '<i class="flaticon-feed_type_hash"></i>';
icon = '<i class="flaticon-feed_type_loc"></i>';
// todo refactor this crap
for ( prop in settings ) {
ikey = capitaliseFirstLetter( prop.replace(' timeline', '').replace('_', ' ').replace('-', ' ').replace('timeline ', '') );
ival = stripslashes( settings[prop] );
if ( prop !== 'content' ) ival = capitaliseFirstLetter ( ival );
if ( prop === 'mod' ) ival = 'moderated';
ival = ival.replace('_timeline', '').replace('http://', '').replace('https://', '');
ival = ival.substring(0, 20) + '...';
if ( ikey === 'Boosted' && ival === 'Yep' ) {
info += '<span class="highlight hilite-boost ff-item__draggable"><i class="flaticon-rocket" style="display: inline-block;"></i></span>';
if ( ikey.toLowerCase() == 'type' && plugin == "insta_flow" ) continue;
info = info + '<span class="highlight' + ( ikey === 'Id' ? ' highlight-id' : '' ) + '">' + ( plugin == "insta_flow" && ikey.toLowerCase() === 'content' ? icon : '' ) + ival + '</span>';
if (feed.cache_lifetime == 5) {
interval = 'Every 5 min';
} else if (feed.cache_lifetime == 30) {
interval = 'Every 30 min';
} else if (feed.cache_lifetime == 60) {
} else if (feed.cache_lifetime == 120) {
interval = 'Every 2 hours';
} else if (feed.cache_lifetime == 360) {
interval = 'Every 6 hours';
} else if (feed.cache_lifetime == 1440) {
} else if (feed.cache_lifetime == 10080) {
interval = 'Once a week';
status = isChanged ? '<span class="cache-status-waiting">' : ( (feed.status == 1) ? '<span class="cache-status-ok">' : '<span class="cache-status-error">' );
lastUpdate = feed.last_update && feed.last_update !== 'N/A' ? (feed.last_update + ' (' + interval + ')') : 'N/A';
feedsListStr = feedsListStr +
'<tr data-uid="' + uid + '" data-network="' + feed.type + '" class="feed-row ' + ( feed.enabled == 'yep' ? 'feed-enabled' : 'feed-disabled' ) + ( isChanged ? ' feed-waiting-status' : '' ) + ( feed.boosted == 'yep' ? ' feed-boosted' : '' ) + '">' +
'<td class="controls"><div class="loader-wrapper"><div class="throbber-loader"></div></div><i class="flaticon-tool_more"></i><ul class="feed-dropdown-menu"><li data-action="filter">Filter feed</li><li data-action="cache">Rebuild cache</li><li data-action="check">Connections</li></ul><i class="flaticon-tool_edit"></i> <i class="flaticon-tool_delete"></i></td>' +
( plugin == 'insta_flow' ? '' : '<td class="td-feed"><i class="flaticon-' + feed.type + '"></i>' + /*capitaliseFirstLetter(feed.type) +*/ '</td>' ) +
'<td class="td-status">' + status + '</span></td>' +
'<td class="td-info">' + info + '</td>' +
'<td class="td-last-update">' + lastUpdate + '</td>' +
'<td class="td-enabled"><label for="feed-enabled-' + uid + '"><input ' + ( feed.enabled == 'yep' ? 'checked' : '' ) + ' id="feed-enabled-' + uid + '" class="switcher" type="checkbox" name="feed-enabled-' + uid + '" value="yep"><div><div></div></div></label></td>' +
feedsListStr = '<tr><td class="empty-cell" colspan="6">Please add at least one feed</td></tr>';
this.$el.find('table.feeds-list tbody').html( feedsListStr );
// now render errors here
renderFilters: function( uid ){
var $excludeList = $('.filter-labels[data-type="exclude"]');
var $includeList = $('.filter-labels[data-type="include"]');
var exclude = this.model.get('feeds')[uid]['filter-by-words'];
var include = this.model.get('feeds')[uid]['include'];
if (exclude == undefined) exclude = '';
if (include == undefined) include = '';
var excludeArr = exclude == '' ? [] : exclude.split(',');
var includeArr = include == '' ? [] : include.split(',');
excludeArr.forEach(function (item, i) {
'<li class="filter-label">' + item +
'<i data-action="delete-filter" data-id="' + uid + '" data-type="exclude" data-content="' + item + '" class="flaticon-feed_type_user"></i>' +
$excludeList.append($label);
includeArr.forEach(function (item, i) {
'<li class="filter-label">' + item +
'<i data-action="delete-filter" data-id="' + uid + '" data-type="include" data-content="' + item + '" class="flaticon-feed_type_user"></i>' +
$includeList.append($label);
addFilter: function (e) {
if (e.which != 13) return;
var $field = $(e.target);
var id = $field.data('id');
var type = $field.data('type');
var content = $field.val();
var $list = $('[data-filter-uid="' + id + '"] .filter-labels[data-type="' + type + '"]');
var $holder = $('[data-filter-uid="' + id + '"] [data-type="filter-' + type + '-holder"]');
var filters = $holder.val() == "" ? [] : $holder.val().split(',');
'<li class="filter-label">' + content +
'<i data-action="delete-filter" data-id="' + id + '" data-type="' + type + '" data-content="' + content + '" class="flaticon-feed_type_user"></i>' +
if(filters.indexOf(content) == -1){
$holder.val(filters.join(','));
this.model.attributes.feeds[id]['filter-by-words'] = filters.join(',');
this.model.attributes.feeds[id]['include'] = filters.join(',');
$holder.trigger('change');
deleteFilter: function(e){
var id = $el.data('id') || $el.closest('.feed-view').data('filter-uid');
var type = $el.data('type');
var content = $(e.target).data('content');
var $label = $(e.target).closest('li');
var $holder = $('[data-filter-uid="' + id + '"] [data-type="filter-' + type + '-holder"]');
var filters = $holder.val() == "" ? [] : $holder.val().split(',');
filters.forEach(function (item, i) {
if(item == content.replace(/\\/g, '')) filters.splice(i, 1);
$holder.val(filters.join(','));
this.model.attributes.feeds[id]['filter-by-words'] = filters.join(',');
this.model.attributes.feeds[id]['include'] = filters.join(',');
console.log(this.model.attributes);
$holder.trigger('change');
toggleFeed: function (e) {
var $row = $t.closest('[data-uid]');
var uid = $row.data('uid');
var type = $row.data( 'network' );
var $view = this.$popup.find('[data-uid="' + uid + '"]'), $filterView;
$view = $( _.template(templates[ type + 'View'])({
$filterView = $( _.template(templates['filterView'])({
this.$el.find( '#feed-views' ).append( $view );
this.$el.find( '#filter-views' ).append( $filterView );
this.setInputsValue( uid );
var $channeling = $view.children('input:hidden');
//feeds[uid]['enabled'] = e.target.checked ? 'yep' : 'nope';
$channeling.val(e.target.checked ? 'yep' : 'nope').change();
savePage: function ( page ) {
sessionStorage.setItem('ff_feeds_page', page );
addFeedErrors: function () {
var feeds = this.model.get('feeds');
self.errorsPresent = false;
_.each( feeds, function (feed) {
var errors = feed.errors;
// render only current page
// CHANGED: render all because of filters
// if ( feed.page && feed.page != self.currentPage ) return
if (typeof errors !== 'object') {
errors = JSON.parse(errors);
if (!errors.length) return;
$feed = self.$el.find('tr[data-uid="' + id + '"]');
$error = $('<span class="cache-status-error"></span>');
$error.data('err', errors);
$feed.find('.td-status').html('').append($error).parent().addClass('tr-error');
self.errorsPresent = true;
setInputsValue: function ( feedId ) {
var feeds = this.model.get('feeds');
if (typeof feeds !== 'object') feeds = JSON.parse(feeds);
_.each(feeds, function (feed) {
var uid, name, $input, val;
if ( feedId && feedId != uid ) return;
if ( name === 'id' || name === 'type' ) continue;
$input = self.$el.find('[name="' + uid + '-' + name + '"]');
if ($input.is(':radio') || $input.is(':checkbox')) {
if ($t.val() == feed[name]) $t.prop('checked', true);
$input.val(val ? stripslashes(val.toString()) : '');
initPaginator: function () {
var feeds = this.model.get('feeds');
var $list = this.$el.find('#feeds-list');
if ( $list.jPages()) $list.jPages('destroy');
var feedsArr = Object.keys( feeds );
if (feedsArr.length > 8) {
this.$el.addClass('jp-visible');
this.$el.removeClass('jp-visible');
return this.$el.find("div.holder").jPages({
startPage: this.currentPage,
containerID : "feeds-list",
hideError: function (e) {
var $rel = $(e.relatedTarget);
if ($rel.is('#error-popup')) return;
FlowFlow.$errorPopup.removeClass('visible');
addFeedStepOne: function(e){
this.$popup.removeClass('add-feed-step-2').addClass('add-feed-step-1');
FlowFlow.checkScrollbar();
FlowFlow.$html.addClass('popup_visible');
this.$popup.on('click', this.popupClick);
var uid = $t.closest('[data-uid]').data('uid');
var $popup = this.$popup;
var feed = this.model.get('feeds') ? this.model.get('feeds')[uid] : null
var network = feed && feed.type;
var $view = $popup.find('.feed-view[data-uid=' + uid + ']');
var $filterView = $popup.find('.feed-view[data-filter-uid=' + uid + ']');
if ( ! $view.length && ! $filterView.length ) {
$view = $( _.template(templates[feed.type + 'View'])({
$filterView = $( _.template(templates['filterView'])({
this.$el.find( '#feed-views' ).append( $view );
this.$el.find( '#filter-views' ).append( $filterView );
this.setInputsValue( uid );
$popup.find('.feed-view-visible').removeClass('feed-view-visible');
$popup.find('.feed-view[data-uid=' + uid + ']').addClass('feed-view-visible');
$popup.addClass('add-feed-step-2');
$popup.find('.feed-popup-controls').hide();
if (feed && feed.enabled === 'nope') {
$popup.find('.feed-popup-controls.enable').show();
$popup.find('.feed-popup-controls.edit').show();