Skip to content

Instantly share code, notes, and snippets.

@remcotolsma
Last active October 6, 2015 09:51
Show Gist options
  • Save remcotolsma/de639ea3e6281435d07f to your computer and use it in GitHub Desktop.
Save remcotolsma/de639ea3e6281435d07f to your computer and use it in GitHub Desktop.
InfiniteWP multiUser bug

InfiniteWP multiUser bug

index.php

...

$mainJson = json_encode(panelRequestManager::getSitesUpdates());

...

$sitesData = json_encode(panelRequestManager::getSites());

...

var mainJson = <?php echo $mainJson?>;
var sitesjson = mainJson.siteView;
var pluginsjson = mainJson.pluginsView.plugins;
var themesjson = mainJson.themesView.themes;
var translationsjson=mainJson.translationsView.translations;
var wpjson = mainJson.coreView.core;
var toolTipData = <?php echo $toolTipData;?>;
var favourites = <?php echo $favourites; ?>;
var site = <?php echo  $sitesData;?>;

panelRequestManager.php

public static function getSites(){
		
		$sitesData = array();
		
		if(function_exists('multiUserGetSites')){
			multiUserGetSites($sitesData);
		}
		else{
			$sitesData = DB::getArray("?:sites", "siteID, URL, adminURL, name, IP, WPVersion, adminUsername, isOpenSSLActive, network, parent, httpAuth, callOpt, connectURL, connectionStatus, links, notes", "1 ORDER BY name", "siteID");
		}

...
	public static function getSitesUpdates($userID = ''){

		...

		//to get error message in sitesData
		getAllSitesStatsWithError();

		//adding error message to the sites Data
		$cronReloadCompCheckData = unserialize(getOption("cronReloadCompCheck"));
		
		if($cronReloadCompCheckData && is_array($cronReloadCompCheckData) && !empty($cronReloadCompCheckData['ignore'])){
			foreach($cronReloadCompCheckData['ignore'] as $key => $data){
				$siteView[$data['siteID']]['error'] = $data['errorMsg'];
			}
		}

		return array('siteView' => $siteView, 'pluginsView' => $pluginView, 'themesView' => $themeView, 'translationsView' => $translationsView, 'coreView' => $coreView, 'siteViewCount' => $siteViewCount, 'totalUpdateCount' => $totalUpdateCount, 'lastReloadTime' => $lastReloadTime);
	}

js/load.js

function displayUpdateContent(view) {
    var content = "",
        emptyStatusType, json, childFlag, WPCount, pluginsCount, themesCount, totalCount, displayName, updateCount, firstKey, mtypeVar, extraClass, typeName, typeVar, uType, versionContent, itemClasses, checkBoxClass, hiddenButton, itemName, iversionContent, iversionContent;
    "sites" == view ? (content = content + '<div class="th_sub rep_sprite"> <div class="update_by_group float-left select_box_cont ">' + groupGenerate(1, "bottom") + '</div> <div class="label float-right"><span style="margin-right:132px;">THEMES</span></div> <div class="label float-right"><span style="margin-right:21px;">PLUGINS</span></div> <div class="label float-right"><span style="margin-right:31px;">WP</span></div> </div><div class="empty_data_set hiddenCheck" style="display:none"> <div class="line2">Hurray! Everything is up-to-date.</div></div>', emptyStatusType = "Websites") : emptyStatusType = "wp" == view ? "WordPress installations" : view.toTitleCase(), content += '<div class="rows_cont"><div class="no_match hiddenCont" style="display:none">Bummer, there are no matches.<br />Try typing fewer characters.</div>', json = eval(view + "json");
    var pFlag = 0,
        childFlag;
    mtypeVar = "";
    var objKey = 0;
    return null != json && void 0 != json && getPropertyCount(json) > 0 ? $.each(json, function(e, t) {
        childFlag = 0, "sites" == view ? (WPCount = void 0 != json[e].core ? getPropertyCount(json[e].core) : 0, pluginsCount = void 0 != json[e].plugins ? getPropertyCount(json[e].plugins) : 0, themesCount = void 0 != json[e].themes ? getPropertyCount(json[e].themes) : 0, totalCount = WPCount + pluginsCount + themesCount, displayName = site[e].name, updateCount = site[e].updateCount, pFlag = 0) : (firstKey = getFirstKey(t), displayName = "wp" == view ? e : "translations" == view ? "Translations are available" : t[firstKey].name, totalCount = getPropertyCount(t), pFlag = 1);
        var i = "active",
            a = '<div class="row_checkbox main_checkbox"></div>',
            s = '<a class="update_group needConfirm" selector="parent_' + parentFlag + '" parent="parent_' + parentFlag + '"><span class="status_parent_' + parentFlag + ' statusSpan">Update All</span></a>',
            l = "";
        "undefined" != typeof t.error && (i = "", a = "", s = "", l = "update_error"), content = 0 == pFlag ? content + '<div class="ind_row_cont ' + l + " js_sites " + i + " visible parent_" + parentFlag + '" selector="parent_' + parentFlag + '" siteid="' + e + '">' : content + '<div class="ind_row_cont ' + l + " " + i + " row_parent_" + parentFlag + " parent_" + parentFlag + '" parent="parent_' + parentFlag + '" selector="' + view + '" did="' + e + '" >', content = content + '<div class="row_summary" > <div class="row_arrow"></div> ' + a + ' <div class="row_name searchable">' + displayName + "</div>", "sites" == view && "undefined" != typeof mainJson.siteViewCount[e] && (content = content + '<div class="row_update_count updateCount_wp_parent_' + parentFlag + '"><span>' + mainJson.siteViewCount[e].core + '</span></div> <div class="row_update_count updateCount_plugins_parent_' + parentFlag + '"><span>' + mainJson.siteViewCount[e].plugins + '</span></div> <div class="row_update_count updateCount_themes_parent_' + parentFlag + '"><span>' + mainJson.siteViewCount[e].themes + "</span></div>"), content = content + '<div class="row_action float-left">' + s + '</div> <div class="clear-both"></div></div><div class="row_detailed" style="display:none"><div class="rh"><div class="row_arrow"></div>' + a + '<div class="row_name">' + displayName + '</div><div class="row_action float-right">' + s + '</div><div class="clear-both"></div></div><div class="rd">', 1 == pFlag && ("plugins" == view ? mtypeVar = "Plugins" : "themes" == view ? mtypeVar = "Themes" : "wp" == view ? mtypeVar = "WordPress" : (view = "translations") && (mtypeVar = "Translations"), getPropertyCount(t) > 1 && "undefined" != typeof t.error && (content = content + '<div class="select_action_long select_parent_' + parentFlag + '"><div class="select_cont float-left"><span>Select: </span><a class="all" selector="parent_' + parentFlag + '">All</a><a class="invert"  selector="parent_' + parentFlag + '">Invert</a><a class="none" selector="parent_' + parentFlag + '">None</a></div><a class="action float-right update_group needConfirm" selector="parent_' + parentFlag + '" parent="parent_' + parentFlag + '"><span class="status_parent_' + parentFlag + ' statusSpan">Update All </span><span class="typeVar typeVar_parent_' + parentFlag + '  test21">' + mtypeVar + '</span></a><div class="clear-both"></div></div>')), $.each(t, function(t, i) {
            if (extraClass = 0 == pFlag ? "row_child_" + childFlag + parentFlag : "row_parent_" + parentFlag, content = content + '<div class="row_updatee ' + extraClass + '"><div class="row_updatee_ind">', 1 == pFlag && (content += '<div class="items_cont_long float-left">'), 0 == pFlag) {
                var a = '<div class="count float-left"><span selector="child_' + childFlag + parentFlag + '">' + getPropertyCount(i) + "</span></div>";
                "core" == t ? typeName = "WP" : "error" == t ? (typeName = "error", a = "") : (typeName = t, typeVar = t.toTitleCase()), content = content + '<div class="label_updatee"><div class="label droid700 float-left">' + typeName + "</div>" + a + '<div class="clear-both"></div></div>', content += '<div class="items_cont float-left">', getPropertyCount(i) > 1 && "error" != t && (content = content + '<div class="select_action select_child_' + childFlag + parentFlag + '"><div class="select_cont float-left"><span>Select: </span><a class="all" selector="child_' + childFlag + parentFlag + '" parent="parent_' + parentFlag + '">All</a><a class="invert" parent="parent_' + parentFlag + '"  selector="child_' + childFlag + parentFlag + '">Invert</a><a class="none" parent="parent_' + parentFlag + '" selector="child_' + childFlag + parentFlag + '">None</a></div><a class="action float-right update_group needConfirm" parent="parent_' + parentFlag + '"  selector="child_' + childFlag + parentFlag + '"><span class="status_child_' + childFlag + parentFlag + ' statusSpan">Update All </span><span class="typeVar typeVar_child_' + childFlag + parentFlag + '">' + typeVar + '</span></a><div class="clear-both"></div></div>')
            }
            "sites" != view ? ("wp" == view ? (oversionContent = '<a class="cutClass">v' + i.current_version + "</a>", uType = "core", versionContent = '<a href="http://codex.wordpress.org/Changelog/' + e + '" target="_blank">v' + e + "</a>") : "translations" == view ? (oversionContent = "Some of your translations are no longer up ", uType = "translations", versionContent = "date.") : (oversionContent = '<a class="cutClass">v' + i.old_version + "</a>", versionContent = "plugins" == view ? '<a href="http://wordpress.org/extend/plugins/' + i.slug + '/changelog/" target="_blank" >v' + i.new_version + "</a>" : '<a class="cutClass">v' + i.new_version + "</a>", uType = view.toLowerCase()), itemClasses = "active", checkBoxClass = "", hiddenButton = "Hide", 1 == i.hiddenItem && (itemClasses = "hidden", checkBoxClass = "style='display:none'", hiddenButton = "Show", updateCheckArray["parent_" + parentFlag] = 1), content = content + '<div class="item_ind plugin_theme_wp_group_hide ' + itemClasses + "  float-left parent_" + parentFlag + '  selectOption" iname="' + i.name + '" parent="parent_' + parentFlag + '" selector="parent_' + parentFlag + '" did="' + e + '" sid="' + t + '" utype="' + uType + '" onclick=""><div class="row_checkbox"' + checkBoxClass + "></div>", content += "sites" != view ? '<div class="item" style="width:750px">' : '<div class="item">', content = content + site[t].name + ' - <span class="version">' + oversionContent + '</span> to <span class="version">' + versionContent + '</span></div><div class="actions"><a class="float-left update_single" parent="parent_' + parentFlag + '" selector="parent_' + parentFlag + '" >Update</a> <a class="float-left hideItem" parent="parent_' + parentFlag + '" selector="parent_' + parentFlag + '">' + hiddenButton + "</a></div></div>") : "error" == t ? (hyphen = "", "core" == t || (oversionContent = "", hyphen = " -", itemName = "error", uType = t), itemClasses = "active", checkBoxClass = "", hiddenButton = "Hide", items = "", content = content + '<div class="item_ind   float-left parent_' + parentFlag + " child_" + childFlag + parentFlag + ' hasParent" iname="' + itemName + '" selector="child_' + childFlag + parentFlag + '" parent="parent_' + parentFlag + '" did="' + items + '" sid="' + e + '" utype="' + uType + '" onclick=""><div class="item">' + i + " </div></div>") : $.each(i, function(i, a) {
                hyphen = "", "core" == t ? (oversionContent = '<a class="cutClass">v' + a.current_version + "</a>", iversionContent = '<a href="http://codex.wordpress.org/Changelog/' + i + '" target="_blank">v' + i + "</a>", uType = t.toLowerCase(), itemName = "", hyphen = "") : "translations" == t ? (oversionContent = "Some of your translations are no longer up ", iversionContent = "date.", uType = t.toLowerCase(), itemName = "", hyphen = "") : (oversionContent = '<a class="cutClass">v' + a.old_version + "</a>", hyphen = " -", itemName = a.name, iversionContent = "plugins" == t ? '<a href="http://wordpress.org/extend/plugins/' + a.slug + '/changelog/" target="_blank">v' + a.new_version + "</a>" : '<a class="cutClass">v' + a.new_version + "</a>", uType = t), itemClasses = "active", checkBoxClass = "", hiddenButton = "Hide", 1 == a.hiddenItem && (itemClasses = "hidden", checkBoxClass = "style='display:none'", hiddenButton = "Show", updateCheckArray["parent_" + parentFlag] = 1, updateCheckArray["child_" + childFlag + parentFlag] = 1), content = content + '<div class="item_ind   ' + itemClasses + "   float-left parent_" + parentFlag + " child_" + childFlag + parentFlag + ' selectOption hasParent" iname="' + itemName + '" selector="child_' + childFlag + parentFlag + '" parent="parent_' + parentFlag + '" did="' + i + '" sid="' + e + '" utype="' + uType + '" onclick=""><div class="row_checkbox" ' + checkBoxClass + '></div><div class="item">' + itemName + hyphen + ' <span class="version">' + oversionContent + '</span> to <span class="version">' + iversionContent + '</span></div><div class="actions"><a class="float-left update_single" parent="parent_' + parentFlag + '" selector="child_' + childFlag + parentFlag + '">Update</a> <a class="float-left hideItem" parent="parent_' + parentFlag + '" selector="child_' + childFlag + parentFlag + '">' + hiddenButton + "</a></div></div>"
            }), content += '</div><div class="clear-both"></div></div></div>', childFlag++
        }), "sites" != view && (content += "<div class='clear-both'></div>"), content += "</div></div></div>", parentFlag++
    }) : content = '<div class="empty_data_set"> <div class="line2">Hurray! All ' + emptyStatusType + " are up-to-date.</div></div>", content
}

Problem

The displayUpdateContent JavaScript function is iterating over sitesjson, but somehow not all sites in this array are available in the site variable. This is resuling in the following error:

site[e].name is undefined

Reproduce problem in console:

jQuery.each( sitesjson, function( e, t ) {
	console.log( e );
	console.log( site[e] );	
} );

It looks like sites with errors are always added to sitesjson even if the user doesn't have access to these sites. See the getSitesUpdates function after the getAllSitesStatsWithError function call.

Fix

A quick fix for this issue is by checking on the user status and only add sites with error if the user is an admin user.

...
		if(userStatus() == "admin"){
			//to get error message in sitesData
			getAllSitesStatsWithError();
			
			//adding error message to the sites Data
			$cronReloadCompCheckData = unserialize(getOption("cronReloadCompCheck"));
			
			if($cronReloadCompCheckData && is_array($cronReloadCompCheckData) && !empty($cronReloadCompCheckData['ignore'])){
				foreach($cronReloadCompCheckData['ignore'] as $key => $data){
					$siteView[$data['siteID']]['error'] = $data['errorMsg'];
				}
			}
		}
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment