Plugin Directory

Changeset 2852700


Ignore:
Timestamp:
01/23/2023 05:24:00 AM (3 years ago)
Author:
majick
Message:

1.0.7 trunk commit

Location:
teleporter/trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • teleporter/trunk/js/teleporter.dev.js

    r2818074 r2852700  
    55/* --- Set Default Settings --- */
    66/* 1.0.0: added pageload timeout setting */
    7 var teleporter = {debug: false, fadetime: 2000, timeout: 10000, ignore: ['no-transition','no-teleporter'], dynamic: [], iframe: 'teleporter-iframe', loading: 'teleporter-loading', 'siteurl': ''};
     7/* 1.0.6: added existing definition check */
     8if (typeof teleporter == 'undefined') {
     9    var teleporter = {debug: false, fadetime: 2000, timeout: 10000, ignore: ['.no-transition','.no-teleporter'], dynamic: [], iframe: 'teleporter-iframe', loading: 'teleporter-loading', 'siteurl': ''};
     10}
    811
    912/* --- Set Initial Variables --- */
     
    436439
    437440    /* check against ignore classes */
    438     if (!skip && teleporter.ignore.length && (typeof el.classList != 'undefined') && el.classList.length) {
     441    if (!skip && teleporter.ignore.length) {
    439442        for (i in teleporter.ignore) {
    440             if (el.classList.contains(teleporter.ignore[i])) {skip = true;}
     443            if (el.matches(teleporter.ignore[i])) {skip = true;}
    441444        }
    442445    }
     
    530533/* --- Add Dynamic Link Clicks --- */
    531534/* 1.0.4: added event delegation clicks for dynamic link classes */
     535/* 1.0.6: allow for any selectors not just classes */
    532536function teleporter_dynamic_link_clicks() {
    533537    if (!teleporter.dynamic.length) {return;}
    534     var dynamic_classes = '';
     538    var dynamic_selectors = '';
    535539    for (i = 0; i < teleporter.dynamic.length; i++) {
    536         if (dynamic_classes != '') {dynamic_classes += ', ';}
    537         dynamic_classes += '.'+teleporter.dynamic[i];
    538     }
    539     if (teleporter.debug) {console.log('Dynamic Classes: '+dynamic_classes);}
    540     jQuery('a').on('click', dynamic_classes, function(e) {
     540        if (dynamic_selectors != '') {dynamic_selectors += ', ';}
     541        dynamic_selectors += teleporter.dynamic[i];
     542    }
     543    if (teleporter.debug) {console.log('Dynamic Selectors: '+dynamic_selectors);}
     544    jQuery('a').on('click', dynamic_selectors, function(e) {
    541545        e.stopImmediatePropagation();
    542546        e.preventDefault();
  • teleporter/trunk/js/teleporter.js

    r2818074 r2852700  
    1 var teleporter = {debug: false, fadetime: 2000, timeout: 10000, ignore: ['no-transition','no-teleporter'], dynamic: [], iframe: 'teleporter-iframe', loading: 'teleporter-loading', 'siteurl': ''};
     1if (typeof teleporter == 'undefined') {
     2    var teleporter = {debug: false, fadetime: 2000, timeout: 10000, ignore: ['.no-transition','.no-teleporter'], dynamic: [], iframe: 'teleporter-iframe', loading: 'teleporter-loading', 'siteurl': ''};
     3}
    24var t_topwin; t_topwin = teleporter_top_window();
    35if (typeof t_topwin.t_loading == 'undefined') {t_topwin.t_loading = false;}
     
    300302        if ((u.indexOf(a) === 0) || (u.indexOf(b) === 0)) {skip = false;}
    301303    }
    302     if (!skip && teleporter.ignore.length && (typeof el.classList != 'undefined') && el.classList.length) {
     304    if (!skip && teleporter.ignore.length) {
    303305        for (i in teleporter.ignore) {
    304             if (el.classList.contains(teleporter.ignore[i])) {skip = true;}
     306            if (el.matches(teleporter.ignore[i])) {skip = true;}
    305307        }
    306308    }
     
    364366function teleporter_dynamic_link_clicks() {
    365367    if (!teleporter.dynamic.length) {return;}
    366     var dynamic_classes = '';
     368    var dynamic_selectors = '';
    367369    for (i = 0; i < teleporter.dynamic.length; i++) {
    368         if (dynamic_classes != '') {dynamic_classes += ', ';}
    369         dynamic_classes += '.'+teleporter.dynamic[i];
    370     }
    371     if (teleporter.debug) {console.log('Dynamic Classes: '+dynamic_classes);}
    372     jQuery('a').on('click', dynamic_classes, function(e) {
     370        if (dynamic_selectors != '') {dynamic_selectors += ', ';}
     371        dynamic_selectors += teleporter.dynamic[i];
     372    }
     373    if (teleporter.debug) {console.log('Dynamic Selectors: '+dynamic_selectors);}
     374    jQuery('a').on('click', dynamic_selectors, function(e) {
    373375        e.stopImmediatePropagation();
    374376        e.preventDefault();
  • teleporter/trunk/js/teleporter.min.js

    r2818074 r2852700  
    1 var teleporter = {debug: false, fadetime: 2000, timeout: 10000, ignore: ['no-transition','no-teleporter'], dynamic: [], iframe: 'teleporter-iframe', loading: 'teleporter-loading', 'siteurl': ''};  var t_topwin; t_topwin = teleporter_top_window();  if (typeof t_topwin.t_loading == 'undefined') {t_topwin.t_loading = false;}  if (typeof t_topwin.t_loaded == 'undefined') {t_topwin.t_loaded = false;}  if (typeof t_topwin.t_pushing == 'undefined') {t_topwin.t_pushing = false;}  if (typeof t_topwin.t_initialurl == 'undefined') {t_topwin.t_initialurl = window.location.href;}  if (typeof t_topwin.t_poppedstate == 'undefined') {  if  (typeof t_topwin.History == 'function') {t_topwin.t_poppedstate = t_topwin.History.getState();}  else {t_topwin.t_poppedstate = ('state' in t_topwin.history && t_topwin.history.state !== null);}  }  function teleporter_transition_page(link) {  if ((typeof History != 'function') && !window.history) {return true;}  if (typeof t_topwin.stateurls !== 'undefined') {  stateurls = t_topwin.stateurls;  for (i in stateurls) {  if (stateurls[i] == link.href) {  if (i == t_topwin.currentstate) {return false;}  teleporter_switch_state(i);  title = t_topwin.statetitles[i];  var obj = {id: i, title: title, url: link.href};  t_topwin.t_pushing = true;  if (typeof t_topwin.History == 'function') {t_topwin.History.replaceState(obj, title, link.href);}  else if (t_topwin.history) {t_topwin.history.replaceState(obj, title, link.href);}  t_topwin.t_pushing = false;  t_topwin.currentstate = i;  return false;  }  }  }  iframe = teleporter_add_iframe(link.href);  teleporter_show_loading(link.href);  return false;  }  function teleporter_transition_check(url, win) {  href = null; iframe = null; topdoc = t_topwin.document;  if (t_topwin != win.self) {  iframes = topdoc.getElementsByClassName(teleporter.iframe);  if (!url) {url = win.location.href;}  for (i = 0; i < iframes.length; i++) {  if (url == iframes[i].src) {iframe = iframes[i];}  }  if (!iframe) {  return;  }  if (iframe.src != t_topwin.location.href) {  teleporter_hide_loading();      body = topdoc.getElementsByTagName('body')[0];      if (!t_topwin.bodymargin) {t_topwin.bodymargin = body.style.margin;}      if (!t_topwin.bodypadding) {t_topwin.bodypadding = body.style.padding;}      body.style.margin = '0'; body.style.padding = '0'; body.style.overflow = 'hidden';  if (iframe.style.display != 'block') {  if ((typeof t_topwin.jQuery == 'function') && teleporter.fadetime) {  t_topwin.jQuery(iframe).fadeIn(teleporter.fadetime);  } else {iframe.style.display = 'block';}  }  href = iframe.src;      }  } else {href = win.location.href;}  if (href) {  stateid = teleporter_push_state(href, win);  if (iframe) {iframe.setAttribute('id', teleporter.iframe+'-'+stateid);}  }  }  function teleporter_push_state(href, win) {  titletag = win.document.getElementsByTagName('title');  if (titletag.length) {title = titletag[0].innerHTML;} else {title = '';}  if (typeof t_topwin.statecount === 'undefined') {  t_topwin.statecount = 0; t_topwin.windowstateid = 0; stateid = 0;  stateurls = []; stateurls[0] = href; t_topwin.stateurls = stateurls;  statetitles = []; statetitles[0] = title; t_topwin.statetitles = statetitles;  } else {  t_topwin.statecount++; stateid = t_topwin.statecount;  if ((t_topwin != win.self) && (typeof win.windowstateid == 'undefined') ) {  win.windowstateid = stateid;  t_topwin.stateurls[stateid] = href;  t_topwin.statetitles[stateid] = title;  }  }  var obj = {id: stateid, title: title, url: href};  t_topwin.t_pushing = true;  if (typeof t_topwin.History == 'function') {t_topwin.History.pushState(obj, title, href);}  else if (t_topwin.history) {t_topwin.history.pushState(obj, title, href);}  t_topwin.t_pushing = false;  teleporter_custom_event('teleporter-state-pushed', obj);  t_topwin.currentstate = stateid;  t_topwin.t_loaded = t_topwin.t_loading; t_topwin.t_loading = false;  return stateid;  }  function teleporter_show_loading(href) {  t_topwin.t_loading = href;  setTimeout(function() {  if (!t_topwin.t_loading) {return;}  href = t_topwin.t_loading;  console.log('Page load timeout reached. Displaying URL: '+href);  iframes = t_topwin.document.getElementsByClassName(teleporter.iframe);   for (i = 0; i < iframes.length; i++) {   if (href == iframes[i].src) {iframe = iframes[i];}  }  if (!iframe) {return;}  win = iframe.contentWindow;  teleporter_transition_check(href, win);  }, teleporter.timeout);  if (!teleporter.loading) {return;}  topdoc = t_topwin.document;  topdoc.getElementsByTagName('body')[0].classList.add('teleporter-loading');  topdoc.getElementById(teleporter.loading).className = 'reset';  setTimeout(function() {topdoc.getElementById(teleporter.loading).className = 'loading';}, 250);  iframes = topdoc.getElementsByClassName(teleporter.iframe);  for (i = 0; i < iframes.length; i++) {  doc = iframes[i].contentDocument || iframes[i].contentWindow.document;  if (doc.getElementById(teleporter.loading)) {doc.getElementById(teleporter.loading).className = 'reset';}  }  setTimeout(function() {  for (i = 0; i < iframes.length; i++) {  doc = iframes[i].contentDocument || iframes[i].contentWindow.document;  body = doc.getElementsByTagName('body')[0];  if (body) {body.classList.add('teleporter-loading');}  if (doc.getElementById(teleporter.loading)) {doc.getElementById(teleporter.loading).className = 'loading';}  }  }, 250);  }  function teleporter_hide_loading() {  if (!teleporter.loading) {return;}  topdoc = t_topwin.document;  topdoc.getElementById(teleporter.loading).className = '';  topdoc.getElementsByTagName('body')[0].classList.remove('teleporter-loading');  iframes = topdoc.getElementsByClassName(teleporter.iframe);  for (i = 0; i < iframes.length; i++) {  doc = iframes[i].contentDocument || iframes[i].contentWindow.document;  body = doc.getElementsByTagName('body')[0];  if (body) {body.classList.remove('teleporter-loading');}  if (doc.getElementById(teleporter.loading)) {doc.getElementById(teleporter.loading).className = '';}  }  }  function teleporter_add_popstate_checker() {  if (typeof window.History == 'function') {  (function(window,undefined) {  History.Adapter.bind(window, 'statechange', function (event) {  teleporter_custom_event('teleporter-popstate-event', {event: event});  teleporter_popstate_checker(event);  });  })(window);  } else {  window.addEventListener('popstate', function(event) {  teleporter_custom_event('teleporter-popstate-event', {event: event});  teleporter_popstate_checker(event);  }, false );  }  }  function teleporter_popstate_checker(event) {  t_topwin.initialpop = !t_topwin.t_poppedstate && (window.location.href == t_topwin.t_initialurl);  t_topwin.t_poppedstate = true; if (t_topwin.initialpop) {return;}  if (t_topwin.t_pushing) {return;}  if ((typeof t_topwin.backclicked != 'undefined') && t_topwin.backclicked) {  t_topwin.backclicked = false; return;  }  stateid = null;  if (event.state) {console.log('Event State'); console.log(event);}  if  (typeof t_topwin.History != 'undefined') {  state = t_topwin.History.getState();  if (state.data.id) {stateid = state.data.id;}  else {  for (i = 0; i < t_topwin.stateurls.length; i++) {  if (stateurls[i] == state.url) {stateid = i;}  }  }  } else if (t_topwin.history) {  if (event.state) {state = event.state; stateid = state.id;}  else if (t_topwin.history.state) {state = t_topwin.history.state; stateid = state.id;}  else {return true;}  } else {return true;}  if ((stateid === null) || (t_topwin.stateurls == 'undefined') || (state.url != t_topwin.stateurls[stateid])) {  if (state.url == t_topwin.t_initialurl) {  t_topwin.backclicked = true;  if (typeof t_topwin.History == 'function') {t_topwin.History.back();}  else if (t_topwin.history) {history.back();}  } else {  teleporter_transition_page({href: state.url});  }  return;  }  if (event.preventDefault) {event.preventDefault();}  if (event.stopImmediatePropagation) {event.stopImmediatePropagation();}  teleporter_switch_state(stateid);  }  function teleporter_switch_state(stateid) {  if (typeof t_topwin.windowstateid == 'undefined') {return;}  if (typeof t_topwin.currentstate != 'undefined') {currentstate = t_topwin.currentstate;}  else {currentstate = 0; t_topwin.currentstate = 0;}  if (stateid == currentstate) {return;}  teleporter_custom_event('teleporter-switch-state', {stateid: stateid});  iframes = t_topwin.document.getElementsByClassName(teleporter.iframe);  iframe = false;  for (i = 0; i < iframes.length; i++) {  if (iframes[i].id == teleporter.iframe+'-'+stateid) {  iframe = iframes[i]; j = i;  }  }  if (t_topwin.windowstateid == stateid) {  body = t_topwin.document.getElementsByTagName('body')[0];  body.style.margin = t_topwin.bodymargin;  body.style.padding = t_topwin.bodypadding;  body.style.overflow = 'scroll';  for (i = 0; i < iframes.length; i++) {  if (iframes[i].style.display != 'none') {  if ((typeof jQuery == 'function') && teleporter.fadetime) {  jQuery(iframes[i]).fadeOut(teleporter.fadetime);  } else {iframes[i].style.display = 'none';}  }  }  t_topwin.currentstate = 0;  } else if (iframe) {  body = t_topwin.document.getElementsByTagName('body')[0];  body.style.margin = '0'; body.style.padding = '0'; body.style.overflow = 'hidden';  for (i = 0; i < iframes.length; i++) {  if ((i != j) && (iframes[i].style.display != 'none')) {  if ((typeof jQuery == 'function') && teleporter.fadetime) {  jQuery(iframes[i]).fadeOut(teleporter.fadetime);  } else {iframes[i].style.display = 'none';}  }  }  if ((typeof jQuery == 'function') && teleporter.fadetime) {  jQuery(iframe).fadeIn(teleporter.fadetime);  } else {iframe.style.display = 'block';}  }  t_topwin.document.title = t_topwin.statetitles[stateid];  t_topwin.currentstate = stateid;  teleporter_custom_event('teleporter-transitioned', {stateid: stateid});  }  function teleporter_add_iframe(src) {  iframe = document.createElement('iframe');  iframe.setAttribute('class', teleporter.iframe);  iframe.setAttribute('name', teleporter.iframe);  iframe.setAttribute('src', src);  iframe.setAttribute('width', '100%');  iframe.setAttribute('height', '100%');  iframe.setAttribute('frameborder', '0');  iframe.setAttribute('scrolling', 'auto');  iframe.setAttribute('allowfullscreen', 'true');  iframe.setAttribute('style', 'display:none;');  t_topwin.document.getElementsByTagName('body')[0].appendChild(iframe);  return iframe;  }  function teleporter_skip_link(el) {  if (el.getAttribute('teleporter') == '1') {return true;}  if ((typeof el.href == 'undefined') || (el.href == '')) {return true;}  if ((typeof el.target != 'undefined') && (el.target != null) && (el.target != '_self') && (el.target != '')) {return true;}  if ((typeof el.onclick != 'undefined') && (el.onclick != null) && (el.onclick != '')) {return true;}  u = el.href; skip = true;  if ((u.indexOf('javascript') === 0) || (u.indexOf('mailto') === 0) || (u.indexOf('tel') === 0)) {return true;}  if ((u.indexOf('#') === 0) || (u.indexOf('?') === 0)) {skip = false;}  if ((teleporter.siteurl != '') && (u.indexOf(teleporter.siteurl) === 0)) {skip = false;}  if (el.host == t_topwin.location.host) {  a = t_topwin.location.protocol+'//'+t_topwin.location.host;  b = '//'+t_topwin.location.host;  if ((u.indexOf(a) === 0) || (u.indexOf(b) === 0)) {skip = false;}  }  if (!skip && teleporter.ignore.length && (typeof el.classList != 'undefined') && el.classList.length) {  for (i in teleporter.ignore) {  if (el.classList.contains(teleporter.ignore[i])) {skip = true;}  }  }  if (teleporter.debug) {if (!skip) {console.log('Found internal URL: '+u);} }  return skip;  }  addEventListener('unload', function(event) {  t_topwin.windowstateid = 'undefined';  }, false);  function teleporter_top_window() {  try {test = window.top.location; return window.top;} catch(e) {  return teleporter_get_window_parent(window.self);  }  }  function teleporter_get_window_parent(win) {  parentwindow = false;  try {test = win.parent.location; parentwindow = win.parent;} catch(e) {return false;}  if (parentwindow) {  if (parentwindow == win) {return win;}  maybe = teleporter_get_window_parent(parentwindow);  if (maybe) {return maybe;}  return parentwindow;  }  return win;  }  function teleporter_add_link_events() {  jQuery('a').each(function() {  el = jQuery(this)[0];  skip = teleporter_skip_link(el);  if (!skip) {  ev = jQuery._data(el, 'events');  if (ev && ev.click && teleporter.debug) {console.log(ev.click);}  el.setAttribute('teleporter', '1');  teleporter_add_link_event(el);  }  });  }  function teleporter_add_link_event(el) {  el.addEventListener('click', function(e) {  e.stopImmediatePropagation();  e.preventDefault();  target = jQuery(e.target);  if (target.prop('tagName') != 'a') {target = target.closest('a');}  element = target[0];  return teleporter_transition_page(element);  });  }  function teleporter_add_link_onclicks() {  alinks = document.getElementsByTagName('a');  for (var i = 0; i < alinks.length; i++) {  skip = teleporter_skip_link(alinks[i]);  if (!skip) {  alinks[i].setAttribute('teleporter', '1');  teleporter_add_link_onclick(alinks[i]);  }  }  }  function teleporter_add_link_onclick(el) {  el.setAttribute('onclick', 'return teleporter_transition_page(this);');  }  function teleporter_dynamic_link_clicks() {  if (!teleporter.dynamic.length) {return;}  var dynamic_classes = '';  for (i = 0; i < teleporter.dynamic.length; i++) {  if (dynamic_classes != '') {dynamic_classes += ', ';}  dynamic_classes += '.'+teleporter.dynamic[i];  }  if (teleporter.debug) {console.log('Dynamic Classes: '+dynamic_classes);}  jQuery('a').on('click', dynamic_classes, function(e) {  e.stopImmediatePropagation();  e.preventDefault();  target = jQuery(e.target);  if (target.prop('tagName') != 'a') {target = target.closest('a');}  if (target.getAttribute('teleporter') == '1') {return;}  element = target[0];  skip = teleporter_skip_link(element);  if (!skip) {  if (teleporter.debug) {console.log(target);}  return teleporter_transition_page(element);  }  });  }  if (typeof window.jQuery !== 'undefined') {  jQuery(document).ready(function() {  if (!teleporter.iframe) {return;}  if (parent.document) {document.getElementsByTagName('body')[0].style.overflow = 'scroll';}  teleporter_custom_event('teleporter-check-links', false);  teleporter_add_link_events();  teleporter_dynamic_link_clicks();  teleporter_custom_event('teleporter-links-checked', false);  teleporter_transition_check(false, window);  teleporter_add_popstate_checker();  setTimeout(function() {teleporter_add_link_events();;}, 5000);  });  } else {  (function(funcName, baseObj) {  "use strict"; funcName = funcName || 'documentReady'; baseObj = baseObj || window;  var readyList = []; var readyFired = false; var readyEventHandlersInstalled = false;  function ready() {  if (!readyFired) {  readyFired = true;  for (var i = 0; i < readyList.length; i++) {  readyList[i].fn.call(window, readyList[i].ctx);  }  readyList = [];  }  }  function readyStateChange() {if (document.readyState === "complete") {ready();} }  baseObj[funcName] = function(callback, context) {  if (readyFired) {setTimeout(function() {callback(context);}, 1); return;}  else {readyList.push({fn: callback, ctx: context});}  if (document.readyState === 'complete' || (!document.attachEvent && document.readyState === 'interactive')) {  setTimeout(ready, 1);  } else if (!readyEventHandlersInstalled) {  if (document.addEventListener) {  document.addEventListener('DOMContentLoaded', ready, false);  window.addEventListener('load', ready, false);  } else {  document.attachEvent('onreadystatechange', readyStateChange);  window.attachEvent('onload', ready);  }  readyEventHandlersInstalled = true;  }  }  })('documentReady', window);  window.documentReady(function() {  if (!teleporter.iframe) {return;}  if (parent.document) {document.getElementsByTagName('body')[0].style.overflow = 'scroll';}  teleporter_custom_event('teleporter-check-links', false);  teleporter_add_link_onclicks();  teleporter_custom_event('teleporter-links-checked', false);  teleporter_transition_check(false, window);  teleporter_add_popstate_checker();  setTimeout(function() {teleporter_add_link_onclicks();}, 5000);  });  }  function teleporter_custom_event(name, detail) {  params = {bubbles: false, cancelable: false, detail: detail};  var event = new CustomEvent(name, params); document.dispatchEvent(event);  }  (function () {  if (typeof window.CustomEvent === 'function') {return false;}  function CustomEvent(event, params) {  params = params || {bubbles: false, cancelable: false, detail: undefined};  var evt = document.createEvent('CustomEvent');  evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);  return evt;  }  CustomEvent.prototype = window.Event.prototype;  window.CustomEvent = CustomEvent;  })();
     1if (typeof teleporter == 'undefined') {  var teleporter = {debug: false, fadetime: 2000, timeout: 10000, ignore: ['.no-transition','.no-teleporter'], dynamic: [], iframe: 'teleporter-iframe', loading: 'teleporter-loading', 'siteurl': ''};  }  var t_topwin; t_topwin = teleporter_top_window();  if (typeof t_topwin.t_loading == 'undefined') {t_topwin.t_loading = false;}  if (typeof t_topwin.t_loaded == 'undefined') {t_topwin.t_loaded = false;}  if (typeof t_topwin.t_pushing == 'undefined') {t_topwin.t_pushing = false;}  if (typeof t_topwin.t_initialurl == 'undefined') {t_topwin.t_initialurl = window.location.href;}  if (typeof t_topwin.t_poppedstate == 'undefined') {  if  (typeof t_topwin.History == 'function') {t_topwin.t_poppedstate = t_topwin.History.getState();}  else {t_topwin.t_poppedstate = ('state' in t_topwin.history && t_topwin.history.state !== null);}  }  function teleporter_transition_page(link) {  if ((typeof History != 'function') && !window.history) {return true;}  if (typeof t_topwin.stateurls !== 'undefined') {  stateurls = t_topwin.stateurls;  for (i in stateurls) {  if (stateurls[i] == link.href) {  if (i == t_topwin.currentstate) {return false;}  teleporter_switch_state(i);  title = t_topwin.statetitles[i];  var obj = {id: i, title: title, url: link.href};  t_topwin.t_pushing = true;  if (typeof t_topwin.History == 'function') {t_topwin.History.replaceState(obj, title, link.href);}  else if (t_topwin.history) {t_topwin.history.replaceState(obj, title, link.href);}  t_topwin.t_pushing = false;  t_topwin.currentstate = i;  return false;  }  }  }  iframe = teleporter_add_iframe(link.href);  teleporter_show_loading(link.href);  return false;  }  function teleporter_transition_check(url, win) {  href = null; iframe = null; topdoc = t_topwin.document;  if (t_topwin != win.self) {  iframes = topdoc.getElementsByClassName(teleporter.iframe);  if (!url) {url = win.location.href;}  for (i = 0; i < iframes.length; i++) {  if (url == iframes[i].src) {iframe = iframes[i];}  }  if (!iframe) {  return;  }  if (iframe.src != t_topwin.location.href) {  teleporter_hide_loading();      body = topdoc.getElementsByTagName('body')[0];      if (!t_topwin.bodymargin) {t_topwin.bodymargin = body.style.margin;}      if (!t_topwin.bodypadding) {t_topwin.bodypadding = body.style.padding;}      body.style.margin = '0'; body.style.padding = '0'; body.style.overflow = 'hidden';  if (iframe.style.display != 'block') {  if ((typeof t_topwin.jQuery == 'function') && teleporter.fadetime) {  t_topwin.jQuery(iframe).fadeIn(teleporter.fadetime);  } else {iframe.style.display = 'block';}  }  href = iframe.src;      }  } else {href = win.location.href;}  if (href) {  stateid = teleporter_push_state(href, win);  if (iframe) {iframe.setAttribute('id', teleporter.iframe+'-'+stateid);}  }  }  function teleporter_push_state(href, win) {  titletag = win.document.getElementsByTagName('title');  if (titletag.length) {title = titletag[0].innerHTML;} else {title = '';}  if (typeof t_topwin.statecount === 'undefined') {  t_topwin.statecount = 0; t_topwin.windowstateid = 0; stateid = 0;  stateurls = []; stateurls[0] = href; t_topwin.stateurls = stateurls;  statetitles = []; statetitles[0] = title; t_topwin.statetitles = statetitles;  } else {  t_topwin.statecount++; stateid = t_topwin.statecount;  if ((t_topwin != win.self) && (typeof win.windowstateid == 'undefined') ) {  win.windowstateid = stateid;  t_topwin.stateurls[stateid] = href;  t_topwin.statetitles[stateid] = title;  }  }  var obj = {id: stateid, title: title, url: href};  t_topwin.t_pushing = true;  if (typeof t_topwin.History == 'function') {t_topwin.History.pushState(obj, title, href);}  else if (t_topwin.history) {t_topwin.history.pushState(obj, title, href);}  t_topwin.t_pushing = false;  teleporter_custom_event('teleporter-state-pushed', obj);  t_topwin.currentstate = stateid;  t_topwin.t_loaded = t_topwin.t_loading; t_topwin.t_loading = false;  return stateid;  }  function teleporter_show_loading(href) {  t_topwin.t_loading = href;  setTimeout(function() {  if (!t_topwin.t_loading) {return;}  href = t_topwin.t_loading;  console.log('Page load timeout reached. Displaying URL: '+href);  iframes = t_topwin.document.getElementsByClassName(teleporter.iframe);   for (i = 0; i < iframes.length; i++) {   if (href == iframes[i].src) {iframe = iframes[i];}  }  if (!iframe) {return;}  win = iframe.contentWindow;  teleporter_transition_check(href, win);  }, teleporter.timeout);  if (!teleporter.loading) {return;}  topdoc = t_topwin.document;  topdoc.getElementsByTagName('body')[0].classList.add('teleporter-loading');  topdoc.getElementById(teleporter.loading).className = 'reset';  setTimeout(function() {topdoc.getElementById(teleporter.loading).className = 'loading';}, 250);  iframes = topdoc.getElementsByClassName(teleporter.iframe);  for (i = 0; i < iframes.length; i++) {  doc = iframes[i].contentDocument || iframes[i].contentWindow.document;  if (doc.getElementById(teleporter.loading)) {doc.getElementById(teleporter.loading).className = 'reset';}  }  setTimeout(function() {  for (i = 0; i < iframes.length; i++) {  doc = iframes[i].contentDocument || iframes[i].contentWindow.document;  body = doc.getElementsByTagName('body')[0];  if (body) {body.classList.add('teleporter-loading');}  if (doc.getElementById(teleporter.loading)) {doc.getElementById(teleporter.loading).className = 'loading';}  }  }, 250);  }  function teleporter_hide_loading() {  if (!teleporter.loading) {return;}  topdoc = t_topwin.document;  topdoc.getElementById(teleporter.loading).className = '';  topdoc.getElementsByTagName('body')[0].classList.remove('teleporter-loading');  iframes = topdoc.getElementsByClassName(teleporter.iframe);  for (i = 0; i < iframes.length; i++) {  doc = iframes[i].contentDocument || iframes[i].contentWindow.document;  body = doc.getElementsByTagName('body')[0];  if (body) {body.classList.remove('teleporter-loading');}  if (doc.getElementById(teleporter.loading)) {doc.getElementById(teleporter.loading).className = '';}  }  }  function teleporter_add_popstate_checker() {  if (typeof window.History == 'function') {  (function(window,undefined) {  History.Adapter.bind(window, 'statechange', function (event) {  teleporter_custom_event('teleporter-popstate-event', {event: event});  teleporter_popstate_checker(event);  });  })(window);  } else {  window.addEventListener('popstate', function(event) {  teleporter_custom_event('teleporter-popstate-event', {event: event});  teleporter_popstate_checker(event);  }, false );  }  }  function teleporter_popstate_checker(event) {  t_topwin.initialpop = !t_topwin.t_poppedstate && (window.location.href == t_topwin.t_initialurl);  t_topwin.t_poppedstate = true; if (t_topwin.initialpop) {return;}  if (t_topwin.t_pushing) {return;}  if ((typeof t_topwin.backclicked != 'undefined') && t_topwin.backclicked) {  t_topwin.backclicked = false; return;  }  stateid = null;  if (event.state) {console.log('Event State'); console.log(event);}  if  (typeof t_topwin.History != 'undefined') {  state = t_topwin.History.getState();  if (state.data.id) {stateid = state.data.id;}  else {  for (i = 0; i < t_topwin.stateurls.length; i++) {  if (stateurls[i] == state.url) {stateid = i;}  }  }  } else if (t_topwin.history) {  if (event.state) {state = event.state; stateid = state.id;}  else if (t_topwin.history.state) {state = t_topwin.history.state; stateid = state.id;}  else {return true;}  } else {return true;}  if ((stateid === null) || (t_topwin.stateurls == 'undefined') || (state.url != t_topwin.stateurls[stateid])) {  if (state.url == t_topwin.t_initialurl) {  t_topwin.backclicked = true;  if (typeof t_topwin.History == 'function') {t_topwin.History.back();}  else if (t_topwin.history) {history.back();}  } else {  teleporter_transition_page({href: state.url});  }  return;  }  if (event.preventDefault) {event.preventDefault();}  if (event.stopImmediatePropagation) {event.stopImmediatePropagation();}  teleporter_switch_state(stateid);  }  function teleporter_switch_state(stateid) {  if (typeof t_topwin.windowstateid == 'undefined') {return;}  if (typeof t_topwin.currentstate != 'undefined') {currentstate = t_topwin.currentstate;}  else {currentstate = 0; t_topwin.currentstate = 0;}  if (stateid == currentstate) {return;}  teleporter_custom_event('teleporter-switch-state', {stateid: stateid});  iframes = t_topwin.document.getElementsByClassName(teleporter.iframe);  iframe = false;  for (i = 0; i < iframes.length; i++) {  if (iframes[i].id == teleporter.iframe+'-'+stateid) {  iframe = iframes[i]; j = i;  }  }  if (t_topwin.windowstateid == stateid) {  body = t_topwin.document.getElementsByTagName('body')[0];  body.style.margin = t_topwin.bodymargin;  body.style.padding = t_topwin.bodypadding;  body.style.overflow = 'scroll';  for (i = 0; i < iframes.length; i++) {  if (iframes[i].style.display != 'none') {  if ((typeof jQuery == 'function') && teleporter.fadetime) {  jQuery(iframes[i]).fadeOut(teleporter.fadetime);  } else {iframes[i].style.display = 'none';}  }  }  t_topwin.currentstate = 0;  } else if (iframe) {  body = t_topwin.document.getElementsByTagName('body')[0];  body.style.margin = '0'; body.style.padding = '0'; body.style.overflow = 'hidden';  for (i = 0; i < iframes.length; i++) {  if ((i != j) && (iframes[i].style.display != 'none')) {  if ((typeof jQuery == 'function') && teleporter.fadetime) {  jQuery(iframes[i]).fadeOut(teleporter.fadetime);  } else {iframes[i].style.display = 'none';}  }  }  if ((typeof jQuery == 'function') && teleporter.fadetime) {  jQuery(iframe).fadeIn(teleporter.fadetime);  } else {iframe.style.display = 'block';}  }  t_topwin.document.title = t_topwin.statetitles[stateid];  t_topwin.currentstate = stateid;  teleporter_custom_event('teleporter-transitioned', {stateid: stateid});  }  function teleporter_add_iframe(src) {  iframe = document.createElement('iframe');  iframe.setAttribute('class', teleporter.iframe);  iframe.setAttribute('name', teleporter.iframe);  iframe.setAttribute('src', src);  iframe.setAttribute('width', '100%');  iframe.setAttribute('height', '100%');  iframe.setAttribute('frameborder', '0');  iframe.setAttribute('scrolling', 'auto');  iframe.setAttribute('allowfullscreen', 'true');  iframe.setAttribute('style', 'display:none;');  t_topwin.document.getElementsByTagName('body')[0].appendChild(iframe);  return iframe;  }  function teleporter_skip_link(el) {  if (el.getAttribute('teleporter') == '1') {return true;}  if ((typeof el.href == 'undefined') || (el.href == '')) {return true;}  if ((typeof el.target != 'undefined') && (el.target != null) && (el.target != '_self') && (el.target != '')) {return true;}  if ((typeof el.onclick != 'undefined') && (el.onclick != null) && (el.onclick != '')) {return true;}  u = el.href; skip = true;  if ((u.indexOf('javascript') === 0) || (u.indexOf('mailto') === 0) || (u.indexOf('tel') === 0)) {return true;}  if ((u.indexOf('#') === 0) || (u.indexOf('?') === 0)) {skip = false;}  if ((teleporter.siteurl != '') && (u.indexOf(teleporter.siteurl) === 0)) {skip = false;}  if (el.host == t_topwin.location.host) {  a = t_topwin.location.protocol+'//'+t_topwin.location.host;  b = '//'+t_topwin.location.host;  if ((u.indexOf(a) === 0) || (u.indexOf(b) === 0)) {skip = false;}  }  if (!skip && teleporter.ignore.length) {  for (i in teleporter.ignore) {  if (el.matches(teleporter.ignore[i])) {skip = true;}  }  }  if (teleporter.debug) {if (!skip) {console.log('Found internal URL: '+u);} }  return skip;  }  addEventListener('unload', function(event) {  t_topwin.windowstateid = 'undefined';  }, false);  function teleporter_top_window() {  try {test = window.top.location; return window.top;} catch(e) {  return teleporter_get_window_parent(window.self);  }  }  function teleporter_get_window_parent(win) {  parentwindow = false;  try {test = win.parent.location; parentwindow = win.parent;} catch(e) {return false;}  if (parentwindow) {  if (parentwindow == win) {return win;}  maybe = teleporter_get_window_parent(parentwindow);  if (maybe) {return maybe;}  return parentwindow;  }  return win;  }  function teleporter_add_link_events() {  jQuery('a').each(function() {  el = jQuery(this)[0];  skip = teleporter_skip_link(el);  if (!skip) {  ev = jQuery._data(el, 'events');  if (ev && ev.click && teleporter.debug) {console.log(ev.click);}  el.setAttribute('teleporter', '1');  teleporter_add_link_event(el);  }  });  }  function teleporter_add_link_event(el) {  el.addEventListener('click', function(e) {  e.stopImmediatePropagation();  e.preventDefault();  target = jQuery(e.target);  if (target.prop('tagName') != 'a') {target = target.closest('a');}  element = target[0];  return teleporter_transition_page(element);  });  }  function teleporter_add_link_onclicks() {  alinks = document.getElementsByTagName('a');  for (var i = 0; i < alinks.length; i++) {  skip = teleporter_skip_link(alinks[i]);  if (!skip) {  alinks[i].setAttribute('teleporter', '1');  teleporter_add_link_onclick(alinks[i]);  }  }  }  function teleporter_add_link_onclick(el) {  el.setAttribute('onclick', 'return teleporter_transition_page(this);');  }  function teleporter_dynamic_link_clicks() {  if (!teleporter.dynamic.length) {return;}  var dynamic_selectors = '';  for (i = 0; i < teleporter.dynamic.length; i++) {  if (dynamic_selectors != '') {dynamic_selectors += ', ';}  dynamic_selectors += teleporter.dynamic[i];  }  if (teleporter.debug) {console.log('Dynamic Selectors: '+dynamic_selectors);}  jQuery('a').on('click', dynamic_selectors, function(e) {  e.stopImmediatePropagation();  e.preventDefault();  target = jQuery(e.target);  if (target.prop('tagName') != 'a') {target = target.closest('a');}  if (target.getAttribute('teleporter') == '1') {return;}  element = target[0];  skip = teleporter_skip_link(element);  if (!skip) {  if (teleporter.debug) {console.log(target);}  return teleporter_transition_page(element);  }  });  }  if (typeof window.jQuery !== 'undefined') {  jQuery(document).ready(function() {  if (!teleporter.iframe) {return;}  if (parent.document) {document.getElementsByTagName('body')[0].style.overflow = 'scroll';}  teleporter_custom_event('teleporter-check-links', false);  teleporter_add_link_events();  teleporter_dynamic_link_clicks();  teleporter_custom_event('teleporter-links-checked', false);  teleporter_transition_check(false, window);  teleporter_add_popstate_checker();  setTimeout(function() {teleporter_add_link_events();;}, 5000);  });  } else {  (function(funcName, baseObj) {  "use strict"; funcName = funcName || 'documentReady'; baseObj = baseObj || window;  var readyList = []; var readyFired = false; var readyEventHandlersInstalled = false;  function ready() {  if (!readyFired) {  readyFired = true;  for (var i = 0; i < readyList.length; i++) {  readyList[i].fn.call(window, readyList[i].ctx);  }  readyList = [];  }  }  function readyStateChange() {if (document.readyState === "complete") {ready();} }  baseObj[funcName] = function(callback, context) {  if (readyFired) {setTimeout(function() {callback(context);}, 1); return;}  else {readyList.push({fn: callback, ctx: context});}  if (document.readyState === 'complete' || (!document.attachEvent && document.readyState === 'interactive')) {  setTimeout(ready, 1);  } else if (!readyEventHandlersInstalled) {  if (document.addEventListener) {  document.addEventListener('DOMContentLoaded', ready, false);  window.addEventListener('load', ready, false);  } else {  document.attachEvent('onreadystatechange', readyStateChange);  window.attachEvent('onload', ready);  }  readyEventHandlersInstalled = true;  }  }  })('documentReady', window);  window.documentReady(function() {  if (!teleporter.iframe) {return;}  if (parent.document) {document.getElementsByTagName('body')[0].style.overflow = 'scroll';}  teleporter_custom_event('teleporter-check-links', false);  teleporter_add_link_onclicks();  teleporter_custom_event('teleporter-links-checked', false);  teleporter_transition_check(false, window);  teleporter_add_popstate_checker();  setTimeout(function() {teleporter_add_link_onclicks();}, 5000);  });  }  function teleporter_custom_event(name, detail) {  params = {bubbles: false, cancelable: false, detail: detail};  var event = new CustomEvent(name, params); document.dispatchEvent(event);  }  (function () {  if (typeof window.CustomEvent === 'function') {return false;}  function CustomEvent(event, params) {  params = params || {bubbles: false, cancelable: false, detail: undefined};  var evt = document.createEvent('CustomEvent');  evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);  return evt;  }  CustomEvent.prototype = window.Event.prototype;  window.CustomEvent = CustomEvent;  })();
  • teleporter/trunk/loader.php

    r2817374 r2852700  
    66//
    77// --------------
    8 // Version: 1.2.8
     8// Version: 1.2.9
    99// --------------
    1010// Note: Changelog and structure at end of file.
     
    29742974                        echo "  document.getElementById('settings-action').value = 'reset';" . PHP_EOL;
    29752975                        echo "  document.getElementById('settings-form').submit();" . PHP_EOL;
    2976                         echo "});" . PHP_EOL;
    2977                         // echo "}" . PHP_EOL;
     2976                        echo "});" . "\n";
     2977                        // echo "}" . "\n";
    29782978
    29792979                    } elseif ( 'number_step' == $script ) {
     
    29882988                            if ((max !== false) && (newvalue > parseInt(max))) {newvalue = max;}
    29892989                            document.getElementById(id).value = newvalue;
    2990                         }" . PHP_EOL; */
     2990                        }" . "\n"; */
    29912991                        // 1.2.5: replace with jQuery click function to remove onclick attributes
     2992                        // 1.2.9: fix for possible empty value converting to NaN
    29922993                        echo "jQuery('.number-button').on('click', function() {
    29932994                            if (jQuery(this).hasClass('number-up-button')) {multiplier = 1;}
     
    29962997                            data = jQuery('#'+idref).attr('data').split(',');
    29972998                            min = data[0]; max = data[1]; step = data[2];
    2998                             value = parseInt(jQuery('#'+idref).val());
     2999                            value = jQuery('#'+idref).val();
     3000                            if (value == '') {value = 0;} else {value = parseInt(value);}               
    29993001                            newvalue = value + (multiplier * parseInt(step));
    30003002                            if ((min !== false) && (newvalue < parseInt(min))) {newvalue = min;}
    30013003                            if ((max !== false) && (newvalue > parseInt(max))) {newvalue = max;}
    30023004                            jQuery('#'+idref).val(newvalue);
    3003                         });" . PHP_EOL;
     3005                        });" . "\n";
    30043006
    30053007                    } elseif ( 'media_functions' == $script ) {
     
    30523054                            });
    30533055
    3054                         });" . PHP_EOL;
     3056                        });" . "\n";
    30553057
    30563058                    } elseif ( 'colorpicker_init' == $script ) {
    30573059
    30583060                        // --- initialize color pickers ---
    3059                         echo "jQuery(document).ready(function(){" . PHP_EOL;
    3060                         echo "  if (jQuery('.color-picker').length) {jQuery('.color-picker').wpColorPicker();}" . PHP_EOL;
    3061                         echo "});" . PHP_EOL;
     3061                        echo "jQuery(document).ready(function(){" . "\n";
     3062                        echo "  if (jQuery('.color-picker').length) {jQuery('.color-picker').wpColorPicker();}" . "\n";
     3063                        echo "});" . "\n";
    30623064
    30633065                    }
     
    30833085
    30843086            // --- page styles ---
    3085             $styles[] = '#wrapbox {margin-right: 20px;}';
     3087            // 1.2.9: add padding to bottom of settings form
     3088            $styles[] = '#wrapbox {margin-right: 20px; padding-bottom: 20px;}';
    30863089
    30873090            // --- plugin header styles ---
     
    31183121            $styles[] = '.settings-input input.setting-textarea {width:100%;}';
    31193122            $styles[] = '.settings-input select.setting-select {min-width:100px; max-width:100%;}';
    3120 
     3123           
    31213124            // --- toggle input styles ---
    31223125            // Ref: https://www.w3schools.com/howto/howto_css_switch.asp
     
    34693472// =========
    34703473
     3474// == 1.2.9 ==
     3475// - fix empty number field converting to NaN value
     3476// - add bottom padding to settings form wrap box
     3477
    34713478// == 1.2.8 ==
    34723479// - fix saving non-alpha colours in coloralpha fields
     
    36193626// == 0.9.0 ==
    36203627// - Development Version
    3621 
  • teleporter/trunk/readme.txt

    r2818074 r2852700  
    44Tags: transition, page transition, single page application, ajax page load
    55Requires at least: 4.0.0
    6 Tested up to: 6.1
    7 Stable tag: 1.0.5
     6Tested up to: 6.1.1
     7Stable tag: 1.0.7
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    2727= How do I get started?
    2828
    29 Once you have activated the plugin, any internal links on your site will automatically be loaded via page transitions. See the next question for what links are affected.
     29Once you have activated the plugin, any internal links on your site will automatically be loaded via page transitions. Visit the plugin settings page to modify the default plugin behaviour.
     30
     31= How does it work? =
     32
     33Teleporter loads new content in iframes within the existing window, then uses the Browser History API to keep track of the content that is loaded. It then monitors the `onpopstate` event so that browser forward and back buttons continue to load the desired content, with the added ability to fade between them.
    3034
    3135= Which links are affected? =
     
    3438
    35391. Does not have a target attribute set.
    36 2. Does not have an onclick attribute already set.
    37 3. Does not have a class of `no-transition` or `no-teleporter`.
    38 4. Does not have an URL starting with `#` or `?`
    39 5. Does not have an URL starting with Site URL.
     402. Does not have an onclick attribute already explicitly set.
     413. Does not have a class of `no-transition` or `no-teleporter` (or other specified classes.)
     424. Does not have an URL starting with `#` or `?` or `mailto:` or `tel:`
     435. Does not have an URL starting with the current Site URL.
    40446. Does not have an URL with a hostname matching the current page.
    41457. Does not have an URL containing `/wp-admin/` or `wp-login.php`.
     
    4347This is a comprehensive attempt to match and transition between internal links only. (If you think there is something missing here please open a Github issue.)
    4448
    45 = How is dynamic link content handled? =
     49= How are dynamic links handled? =
    4650
    4751As of 1.0.4, Teleporter will also handle dynamic link content. That is, links added to the page later. Simply specify the classes of these links on the plugin settings page, and they are then handled with click event delegation (instead of being directly adding to the `a` link.) So for example, if you have a mobile menu that creates links upon expanding it with a `.mobile-link` class, you can add `mobile-link` in the plugin settings. When the mobile menu link is clicked, Teleporter will transition the page as normal. This makes it possible to use Teleporter with frontend builder or frameworks that add their content with javascript.
    4852
    49 = How does it work? =
    50 
    51 Teleporter loads new content in iframes within the existing window, then uses the Browser History API to keep track of the content that is loaded. It then monitors the `onpopstate` event so that browser forward and back buttons continue to load the desired content, with the added ability to fade between them.
     53Similarly, if there are links that you wish to force to not transition for some reason, you can use the setting for ignore link classes in the same way. And, if you need to use selectors other than classes for these links, you can use the filters `teleporter_dynamic_selectors` and `teleporter_ignore_selectors` to add those respectively also.
    5254
    5355= Will it break other scripts? =
     
    6870
    6971== Changelog ==
     72
     73= 1.0.7 =
     74* Updated: Plugin Panel (1.2.9)
     75* Updated: WordQuest Library (1.8.2)
     76* Fixed: add extra onclick function for iPhone event bubbling
     77* Improved: added checks to not load for admin/previews/editing modes
     78
     79= 1.0.6 =
     80* Added: filter to allow for non-class ignore/dynamic selectors
     81* Fixed: dynamic link event bubbling on iPhone (via cursor:pointer)
     82* Fixed: method of adding of comment-reply-link ignore class
    7083
    7184= 1.0.5 =
  • teleporter/trunk/teleporter.php

    r2818074 r2852700  
    33/*
    44Plugin Name: Teleporter
    5 Plugin URI: http://wordquest.org/plugins/teleporter/
     5Plugin URI: https://wordquest.org/plugins/teleporter/
    66Author: Tony Hayes
    77Description: Seamless fading Page Transitions via the Browser History API
    8 Version: 1.0.5
    9 Author URI: http://wordquest.org
     8Version: 1.0.6
     9Author URI: https://wordquest.org
    1010GitHub Plugin URI: majick777/teleporter
    1111*/
     
    3131// - Enqueue Teleporter Scripts
    3232// - Localize Script Settings
     33// - Dynamic Link iPhone Fix
    3334// - Add History API Support
    3435// - Add Teleporter Styles
     
    144145        if ( file_exists( $wqhelper ) ) {
    145146            include $wqhelper;
    146             global $wordquestplugins; $slug = $args['slug'];
     147            global $wordquestplugins;
     148            $slug = $args['slug'];
    147149            $wordquestplugins[$slug] = $args;
    148150        }
     
    333335// ------------------
    334336
     337// -----------------------------
     338// Check if Admin or Editor Mode
     339// -----------------------------
     340function teleporter_is_admin_or_editor() {
     341
     342    // -- admin or preview ---
     343    if ( is_admin() ) {
     344        return true;
     345    }
     346    // --- customizer preview or page preview ---
     347    if ( is_customize_preview() || isset( $_REQUEST['preview_id'] ) ) {
     348        return true;
     349    }
     350    // --- block editor ---
     351    if ( function_exists( 'get_current_screen' ) ) {
     352        $current_screen = get_current_screen();
     353        if ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) {
     354            return true;
     355        }
     356    }
     357    // --- gutenberg plugin ---
     358    if ( function_exists( 'is_gutenberg_page' ) && is_gutenberg_page() ) {
     359        return true;
     360    }
     361    // --- elementor ---
     362    if ( ( isset( $_REQUEST['action'] ) && ( 'elementor' == $_REQUEST['action'] ) ) || isset( $_REQUEST['elementor-preview'] ) ) {
     363        return true;
     364    }
     365    // --- beaver builder ---
     366    if ( isset( $_REQUEST['fl_builder'] ) || isset( $_REQUEST['fl_builder_preview'] ) ) {
     367        return true;
     368    }
     369   
     370    return false;
     371}
     372
    335373// --------------------------
    336374// Enqueue Teleporter Scripts
     
    338376add_action( 'wp_enqueue_scripts', 'teleporter_enqueue_scripts' );
    339377function teleporter_enqueue_scripts() {
     378
     379    // 1.0.7: added double checks to bug out in admin/editing modes
     380    if ( teleporter_is_admin_or_editor() ) {
     381        return;
     382    }
    340383
    341384    // --- check settings ---
     
    373416    if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
    374417        $suffix = '';
    375     } elseif ( 'yes' == $teleporter_debug ) {
    376         $suffix = '';
    377418    } elseif ( isset( $_REQUEST['teleporter-debug'] ) ) {
    378419        if ( '1' == $_REQUEST['teleporter-debug'] ) {
     
    383424            $suffix = '.dev';
    384425        }
     426    } elseif ( 'yes' == $teleporter_debug ) {
     427        $suffix = '';
    385428    } else {
    386429        $suffix = '.min';
     
    390433    wp_enqueue_script( 'teleporter', $teleporter_url, array( 'jquery' ), $version, false );
    391434
    392     if ( isset( $_REQUEST['teleporter-debug'] ) && ( '1' == $_REQUEST['teleporter-debug'] ) ) {
     435    if ( $teleporter_debug || isset( $_REQUEST['teleporter-debug'] ) ) {
    393436        echo '<span style="display:none;">Teleporter Script Enqueued: ' . $teleporter_url . '</span>';
    394437    }
     
    448491                $ignore .= ',';
    449492            }
    450             $ignore .= "'" . esc_js( trim( $ignore_class ) ) . "'";
     493            $ignore .= "'." . esc_js( trim( $ignore_class ) ) . "'";
     494        }
     495    }
     496    // 1.0.6: add filter for other more specific (not just class) selectors
     497    $ignore_selectors = apply_filters( 'teleporter_ignore_selectors', '' );
     498    if ( $ignore_selectors && is_string( $ignore_selectors ) ) {
     499        if ( strstr( $ignore_selectors, ',' ) ) {
     500            $ignore_selectors = explode( ',', $ignore_selectors );
     501        } else {
     502            $ignore_selectors = array( $ignore_selectors );
     503        }
     504    }
     505    if ( is_array( $ignore_selectors ) && ( count( $ignore_selectors ) > 0 ) ) {
     506        foreach ( $ignore_selectors as $ignore_selector ) {
     507            if ( strlen( $ignore ) > 1 ) {
     508                $ignore .= ',';
     509            }
     510            $ignore .= "'" . esc_js( trim( $ignore_selector ) ) . "'";
    451511        }
    452512    }
     
    465525        }
    466526    }
    467     if ( is_array( $dynamic_classes ) && !empty( $dynamic_classes ) && ( count( $dynamic_classes ) > 0 ) ) {
    468         foreach ( $dynamic_classes as $i => $dynamic_class ) {
    469             if ( $i > 0 ) {
     527    if ( is_array( $dynamic_classes ) && ( count( $dynamic_classes ) > 0 ) ) {
     528        foreach ( $dynamic_classes as $dynamic_class ) {
     529            if ( strlen( $dynamic ) > 1 ) {
    470530                $dynamic .= ',';
    471531            }
    472             $dynamic .= "'" . esc_js( trim( $dynamic_class ) ) . "'";
     532            $dynamic .= "'." . esc_js( trim( $dynamic_class ) ) . "'";
     533        }
     534    }
     535    // 1.0.6: add filter for other more specific (not just class) selectors
     536    $dynamic_selectors = apply_filters( 'teleporter_dynamic_selectors', '' );
     537    if ( $dynamic_selectors && is_string( $dynamic_selectors ) ) {
     538        if ( strstr( $dynamic_selectors, ',' ) ) {
     539            $dynamic_selectors = explode( ',', $dynamic_selectors );
     540        } else {
     541            $dynamic_selectors = array( $dynamic_selectors );
     542        }
     543    }
     544    if ( is_array( $dynamic_selectors ) && ( count( $dynamic_selectors ) > 0 ) ) {
     545        foreach ( $dynamic_selectors as $dynamic_selector ) {
     546            if ( strlen( $dynamic ) > 1 ) {
     547                $dynamic .= ',';
     548            }
     549            $dynamic .= "'" . esc_js( trim( $dynamic_selector ) ) . "'";
    473550        }
    474551    }
     
    559636    wp_add_inline_script( 'teleporter', $js );
    560637
     638    // 1.0.6: added to fix dunamic links on iphones
     639    if ( is_array( $dynamic_classes ) && !empty( $dynamic_classes ) && ( count( $dynamic_classes ) > 0 ) ) {
     640        add_action( 'wp_footer', 'teleporter_dynamic_link_iphone_fix' );
     641    }
     642
     643}
     644
     645// -----------------------
     646// Dynamic Link iPhone Fix
     647// -----------------------
     648// 1.0.6: added for iPhone Safari click event bubbling
     649function teleporter_dynamic_link_iphone_fix() {
     650
     651    $dynamic_classes = teleporter_get_setting( 'dynamic_link_classes' );
     652    $dynamic_classes = apply_filters( 'teleporter_dynamic_classes', $dynamic_classes );
     653    $dynamic = '';
     654    if ( $dynamic_classes && is_string( $dynamic_classes ) ) {
     655        if ( strstr( $dynamic_classes, ',' ) ) {
     656            $dynamic_classes = explode( ',', $dynamic_classes );
     657        } else {
     658            $dynamic_classes = array( $dynamic_classes );
     659        }
     660    }
     661    echo '<style>';
     662    if ( is_array( $dynamic_classes ) && !empty( $dynamic_classes ) && ( count( $dynamic_classes ) > 0 ) ) {
     663        // ref: https://gravitydept.com/blog/js-click-event-bubbling-on-ios
     664        foreach ( $dynamic_classes as $i => $dynamic_class ) {
     665            if ( $i > 0 ) {
     666                echo ',';
     667            }
     668            echo '.' . esc_html( trim( $dynamic_class ) );
     669        }
     670        echo ', ';
     671    }
     672    // 1.0.7: add is-ios class selector in any case
     673    echo '.is-ios * {cursor: pointer;}</style>' . "\n";
     674
     675    // 1.0.7: detect iOS and add onclick function to body children
     676    // (an onclick function may be needed 'between body and element')
     677    // ref: https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
     678    echo "<script>jQuery(document).ready(function() {
     679        isIOS = ['iPhone Simulator','iPad Simulator','iPod Simulator','iPhone','iPad','iPod'].includes(navigator.platform);
     680        if (isIOS) {
     681            document.querySelector('html').classList.add('is-ios');
     682            jQuery('body').children().each(function() {
     683                if (!jQuery(this).is('[onclick],script,style,link')) {jQuery(this).attr('onclick','function(){}');}
     684            });
     685        }
     686    });</script>" . "\n";
    561687}
    562688
     
    567693add_filter( 'teleporter_ignore_classes', 'teleporter_ignore_comment_reply_link_classes' );
    568694function teleporter_ignore_comment_reply_link_classes( $classes ) {
    569     if ( !is_array( $classes ) ) {
    570         $classes = array();
    571     }
    572     $classes[] = 'comment-reply-link';
     695
     696    // 1.0.6: allow for array or string value
     697    if ( is_array( $classes ) ) {
     698        $classes[] = 'comment-reply-link';
     699    } elseif ( '' != $classes ) {
     700        $classes .= ',comment-reply-link';
     701    } else {
     702        $classes = 'comment-reply-link';
     703    }
     704   
    573705    return $classes;
    574706}
     
    816948newlinka = document.createElement('a');
    817949newlinka.innerHTML = 'JS Added Link A';
    818 newlinka.href = 'somepage.php';
     950newlinka.href = '?page=a';
    819951newlinka.onclick = function() {alert("JS Added Link A"); return false;};
    820952document.getElementById('links').appendChild(newlinka);
     
    823955document.getElementById('links').appendChild(bra);
    824956document.getElementById('links').appendChild(brb);
     957
    825958newlinkb = document.createElement('a');
    826 newlinkb.innerHTML = 'JS Added Link B';
    827 newlinkb.setAttribute('href', 'somepage.php');
    828 newlinkb.setAttribute('onclick', 'alert("JS Added Link B"); return false;');
     959newlinkb.innerHTML = 'Add JS Link';
     960newlinkb.setAttribute('href', 'javascript:void(0);');
     961newlinkb.setAttribute('onclick', 'teleporter_add_dynamic_link(); return false;');
    829962document.getElementById('links').appendChild(newlinkb);
    830963brc = document.createElement('br');
     
    833966document.getElementById('links').appendChild(brd);
    834967
    835 /* Add jQuery Links */
    836 if (typeof jQuery !== 'undefined') {
    837 
     968/* Add Dynamic Links */
     969function teleporter_add_dynamic_link() {
     970    newlink = document.createElement('a');
     971    newlink.innerHTML = 'Dynamically Added Link';
     972    newlink.href = '?page=a';
     973    newlink.setAttribute('class', 'dynamic-link');
     974    document.getElementById('links').appendChild(newlink);
     975    br = document.createElement('br');
     976    document.getElementById('links').appendChild(br);
    838977}
    839978</script>
  • teleporter/trunk/wordquest.php

    r2817374 r2852700  
    55// ===============================
    66
    7 $wordquestversion = '1.7.7';
     7$wordquestversion = '1.8.2';
    88
    99// === Notes ===
     
    5757    'wpm'   => 'https://wpmedic.tech',
    5858    'prn'   => 'https://pluginreview.net',
    59     'bio'   => 'https://bioship.space'
     59    'bio'   => 'https://bioship.space',
    6060);
    6161
     
    8989// ------------------------------------------
    9090// 1.5.0: use admin_init not plugins_loaded so as to be usable by themes
    91 if ( !has_action( 'admin_init', 'wqhelper_admin_loader', 1 ) ) {
     91// 1.8.0: remove unnecessary third parameter
     92if ( !has_action( 'admin_init', 'wqhelper_admin_loader' ) ) {
    9293    add_action( 'admin_init', 'wqhelper_admin_loader', 1 );
    9394}
    94 if ( !function_exists('wqhelper_admin_loader' ) ) {
     95if ( !function_exists( 'wqhelper_admin_loader' ) ) {
    9596 function wqhelper_admin_loader() {
    96     global $wqdebug;
     97    global $wqdebug;
    9798
    9899    // --- maybe set debug mode ---
    99100    // 1.6.6: check debug switch here so we can check permissions
    100     if ( current_user_can('manage_options' ) ) {
    101         if ( isset( $_REQUEST['wqdebug'] ) ) {
    102             if ( in_array( $_REQUEST['wqdebug'], array( '1', 'yes' ) ) ) {
    103                 $wqdebug = true;
    104             }
    105         }
     101    if ( current_user_can( 'manage_options' ) ) {
     102        // 1.8.1: use sanitize_text_field on request variable
     103        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     104        if ( isset( $_REQUEST['wqdebug'] ) && in_array( sanitize_title( $_REQUEST['wqdebug'] ), array( '1', 'yes' ) ) ) {
     105            $wqdebug = true;
     106        }
    106107    }
    107108
    108109    // --- maybe remove old action ---
    109     // 1.6.0: maybe remove the pre 1.6.0 loader action
    110     if ( has_action('admin_init', 'wordquest_admin_load' ) ) {
    111         remove_action( 'admin_init', 'wordquest_admin_load' );
    112     }
     110    // 1.6.0: maybe remove the pre 1.6.0 loader action
     111    if ( has_action( 'admin_init', 'wordquest_admin_load' ) ) {
     112        remove_action( 'admin_init', 'wordquest_admin_load' );
     113    }
    113114
    114115    // --- set helper version to use ---
    115     // 1.6.0: new globals used for new method
    116     global $wordquesthelper, $wordquesthelpers;
    117     $wordquesthelper = max( $wordquesthelpers );
    118     if ( $wqdebug ) {
    119         echo "<!-- WQ Helper Versions: " . print_r( $wordquesthelpers, true ) . " -->";
    120         echo "<!-- Latest Version: " . esc_html( $wordquesthelper ) . " -->";
    121     }
     116    // 1.6.0: new globals used for new method
     117    global $wordquesthelper, $wordquesthelpers;
     118    $wordquesthelper = max( $wordquesthelpers );
     119    if ( $wqdebug ) {
     120        // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     121        echo "<!-- WQ Helper Versions: " . esc_html( print_r( $wordquesthelpers, true ) ) . " -->";
     122        echo "<!-- Latest Version: " . esc_html( $wordquesthelper ) . " -->";
     123    }
    122124
    123125    // --- load callable functions ---
     
    125127    global $wqcaller, $wqfunctions;
    126128    $functionname = 'wqhelper_caller_';
    127     $func = $functionname . $wordquesthelper;
    128     if ( $wqdebug ) {
    129         echo "<!-- Caller Name: " . esc_html( $func ) . " -->";
    130     }
     129    $func = $functionname . $wordquesthelper;
     130    if ( $wqdebug ) {
     131        echo "<!-- Caller Name: " . esc_html( $func ) . " -->";
     132    }
    131133
    132134    // --- set callable functions ---
     
    137139    }
    138140    if ( $wqdebug ) {
    139         echo "<!-- Caller Object: "; var_dump( $wqcaller ); echo " -->";
     141        // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     142        echo "<!-- Caller Object: " . esc_html( print_r( $wqcaller, true ) ) . " -->";
    140143    }
    141144
    142145    // --- load admin notices ---
    143     // 1.5.0: set up any admin notices via helper version
    144     // 1.6.0: ...use caller function directly for this
    145     $adminnotices = 'wqhelper_admin_notices';
    146     if ( is_callable( $wqcaller ) ) {
    147         $wqcaller( $adminnotices );
    148     } elseif ( function_exists( $adminnotices ) ) {
    149         call_user_func( $adminnotices );
    150     }
    151 
     146    // 1.5.0: set up any admin notices via helper version
     147    // 1.6.0: ...use caller function directly for this
     148    $adminnotices = 'wqhelper_admin_notices';
     149    if ( is_callable( $wqcaller ) ) {
     150        $wqcaller( $adminnotices );
     151    } elseif ( function_exists( $adminnotices ) ) {
     152        call_user_func( $adminnotices );
     153    }
    152154 }
    153155}
     
    164166            $wqcaller = function( $function, $args = null ) {
    165167                global $wordquesthelper, $wqfunctions;
    166                 $func = $function . '_' . $wordquesthelper;
    167                 // echo "<!-- Called Function: ".$func." -->";
     168                    $func = $function . '_' . $wordquesthelper;
     169                    // echo "<!-- Called Function: ".$func." -->";
    168170                if ( is_callable( $wqfunctions[$func] ) ) {
    169171                    return $wqfunctions[$func]( $args );
     
    171173                    return call_user_func( $func, $args );
    172174                }
     175                // 1.8.0: added missing return null statement
     176                return null;
    173177            };
    174178        }
     
    235239 function wqhelper_translate( $string ) {
    236240     return $GLOBALS['wqcaller']( __FUNCTION__, $string );
    237     }
     241 }
    238242}
    239243
     
    259263if ( !function_exists( 'wqhelper_sidebar_patreon_button' ) ) {
    260264 function wqhelper_sidebar_patreon_button( $args = null ) {
    261     return $GLOBALS['wqcaller']( __FUNCTION__, $args );
     265    return $GLOBALS['wqcaller']( __FUNCTION__, $args );
    262266 }
    263267}
     
    297301// - wqhelper_process_rss_feed
    298302// - wqhelper_load_category_feed
     303// - wqhelper_get_feed_ad
    299304
    300305// --- add dashboard feed widget ---
     
    331336if ( !function_exists( 'wqhelper_load_category_feed' ) ) {
    332337 function wqhelper_load_category_feed( $args = null ) {
    333     // 1.7.7: simplified admin condition logic
     338    // 1.7.7: simplified admin condition logic
    334339    if ( is_admin() ) {
    335340        return $GLOBALS['wqcaller']( __FUNCTION__, $args );
    336341    }
     342    // 1.8.0: added missing empty return
     343    return '';
     344 }
     345}
     346// --- get feed ad ---
     347// 1.8.0: added feed ad wrapper function
     348if ( !function_exists( 'wqhelper_get_feed_ad' ) ) {
     349 function wqhelper_get_feed_ad( $args = null ) {
     350    return $GLOBALS['wqcaller']( __FUNCTION__, $args );
    337351 }
    338352}
     
    352366 function wqhelper_admin_styles( $args = null ) {
    353367    remove_action( 'admin_footer', 'wordquest_admin_styles' );
    354     return $GLOBALS['wqcaller']( __FUNCTION__, $args );
     368    return $GLOBALS['wqcaller']( __FUNCTION__, $args );
    355369 }
    356370}
     
    365379 function wqhelper_admin_scripts( $args = null ) {
    366380    remove_action( 'admin_footer', 'wordquest_admin_scripts' );
    367     return $GLOBALS['wqcaller']( __FUNCTION__, $args );
     381    return $GLOBALS['wqcaller']( __FUNCTION__, $args );
    368382 }
    369383}
     
    403417// 1.6.0: ! NOTE ! caller exception ! use matching form version function here just in case...
    404418if ( !has_action( 'wp_ajax_wqhelper_update_sidebar_boxes', 'wqhelper_update_sidebar_boxes' ) ) {
    405     add_action( 'wp_ajax_wqhelper_update_sidebar_boxes', 'wqhelper_update_sidebar_boxes' );
    406 }
    407 if ( !function_exists('wqhelper_update_sidebar_boxes' ) ) {
     419    add_action( 'wp_ajax_wqhelper_update_sidebar_boxes', 'wqhelper_update_sidebar_boxes' );
     420}
     421if ( !function_exists( 'wqhelper_update_sidebar_boxes' ) ) {
    408422 function wqhelper_update_sidebar_boxes() {
    409423
    410424    // --- get helper version ---
    411     if ( !isset( $_POST['wqhv'] ) ) {
    412         return;
    413     } else {
    414         $wqhv = $_POST['wqhv'];
    415     }
    416     // 1.6.6: added sanitization of version value
    417     if ( !is_numeric( $wqhv ) || ( strlen( $wqhv ) !== 3 ) ) {
    418         return;
    419     }
     425    // phpcs:ignore WordPress.Security.NonceVerification.Missing
     426    if ( !isset( $_POST['wqhv'] ) ) {
     427        return;
     428    } else {
     429        // 1.8.1: sanitize to integer and cast to string
     430        // phpcs:ignore WordPress.Security.NonceVerification.Missing
     431        $wqhv = (string) absint( $_POST['wqhv'] );
     432    }
     433    // 1.6.6: added sanitization of version value
     434    // 1.8.1: simplified to check for 3 digits only
     435    if ( strlen( $wqhv ) !== 3 ) {
     436        return;
     437    }
    420438
    421439    // --- set matching function version ---
    422     $func = 'wqhelper_update_sidebar_options_' . $wqhv;
     440    $func = 'wqhelper_update_sidebar_options_' . $wqhv;
    423441
    424442    // --- call function ---
    425     // 1.6.5: fix to function call method
    426     global $wqfunctions;
    427     if ( is_callable( $wqfunctions[$func] ) ) {
    428         $wqfunctions[$func]();
    429     } elseif ( function_exists( $func ) ) {
    430         call_user_func( $func );
    431     }
     443    // 1.6.5: fix to function call method
     444    global $wqfunctions;
     445    if ( is_callable( $wqfunctions[$func] ) ) {
     446        $wqfunctions[$func]();
     447    } elseif ( function_exists( $func ) ) {
     448        call_user_func( $func );
     449    }
    432450 }
    433451}
     
    455473            return bioship_translate( $string );
    456474        }
    457         if ( function_exists('translate' ) ) {
    458             return translate( $string, 'default' );
     475        if ( function_exists( 'translate' ) ) {
     476            // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
     477            return translate( (string) $string, 'default' );
    459478        }
    460479        return $string;
     
    470489    $wqfunctions[$funcname] = function() {
    471490
    472     // 1.7.7: bug out if using Adminsanity Notices box
    473     if ( defined( 'ADMINSANITY_LOAD_NOTICES' ) && ADMINSANITY_LOAD_NOTICES ) {
     491    // 1.7.7: bug out if already using AdminSanity Notices box
     492    // 1.7.8: replace with better check for AdminSanity Notices box
     493    global $adminsanity;
     494    if ( isset( $adminsanity ) && isset( $adminsanity['load'] ) && $adminsanity['load']['notices'] ) {
    474495        return;
    475496    }
     
    487508
    488509    // --- toggle notice box script ---
    489     echo "<script>function togglenoticebox() {divid = 'adminnoticewrap';
     510    echo "<script>function wq_togglenoticebox() {divid = 'adminnoticewrap';
    490511    if (document.getElementById(divid).style.display == '') {
    491512        document.getElementById(divid).style.display = 'none'; document.getElementById('adminnoticearrow').innerHTML = '&#9662;';}
     
    496517
    497518    // --- output notice box ---
    498     $adminnotices = ''; // $adminnotices = '('.$notices.')';
    499519    echo '<div style="width:680px" id="adminnoticebox" class="postbox">';
    500     echo '<h3 class="hndle" style="margin:7px 14px;font-size:12pt;" onclick="togglenoticebox();">';
     520    echo '<h3 class="hndle" style="margin:7px 14px;font-size:12pt;" onclick="wq_togglenoticebox();">';
    501521    echo '<span id="adminnoticearrow">&#9662;</span> &nbsp; ';
    502     echo wqhelper_translate( 'Admin Notices' );
    503     echo $adminnotices . '</span></h3>';
    504     echo '<div id="adminnoticewrap" style="display:none";><h2></h2></div></div>';
    505 
    506     // echo '<div style="width:75%" id="adminnoticebox" class="postbox">';
    507     // echo '<h3 class="hndle" style="margin-left:20px;" onclick="togglenoticebox();"><span>&#9660; ';
    508     // echo wqhelper_translate('Admin Notices');
    509     // echo ' ('.$adminnotices.')</span></h3>';
    510     // echo '<div id="adminnoticewrap" style="display:none";><h2></h2></div></div>';
     522    echo esc_html( wqhelper_translate( 'Admin Notices' ) );
     523    echo '</span></h3><div id="adminnoticewrap" style="display:none;"><h2></h2></div></div>';
    511524
    512525 };
     
    521534if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    522535    $wqfunctions[$funcname] = function() {
    523     global $wordquestplugins;
    524     foreach ( $wordquestplugins as $pluginslug => $wqplugin ) {
     536
     537    global $wordquestplugins;
     538    foreach ( $wordquestplugins as $pluginslug => $wqplugin ) {
    525539
    526540        // --- check current user capabilities ---
     
    529543        if ( current_user_can( 'manage_options' )
    530544            || ( ( 'bioship' == $pluginslug ) && current_user_can( 'install_themes' ) )
    531             || ( ( 'bioship' != $pluginslug ) && current_user_can( 'install_plugins') ) ) {
     545            || ( ( 'bioship' != $pluginslug ) && current_user_can( 'install_plugins' ) ) ) {
    532546                $shownotice = true;
    533547        }
     
    561575                // --- check usage length ---
    562576                $reminder = false;
    563                 $installtime = @strtotime( $sidebaroptions['installdate'] );
     577                $installtime = strtotime( $sidebaroptions['installdate'] );
    564578                $timesince = time() - $installtime;
    565579                $dayssince = floor( $timesince / ( 24 * 60 * 60 ) );
     
    584598
    585599                if ( $reminder ) {
    586                     // --- add an admin reminder notice ---
    587                     global $wqreminder;
    588                     $wqreminder[$pluginslug] = $wqplugin;
    589                     $wqreminder[$pluginslug]['days'] = $dayssince;
    590                     $wqreminder[$pluginslug]['notice'] = $reminder;
    591                     add_action( 'admin_notices', 'wqhelper_reminder_notice' );
    592                 }
    593             } else {
    594                 $sidebaroptions['installdate'] = date( 'Y-m-d' );
    595                 update_option( $prefix . '_sidebar_options', $sidebaroptions );
    596             }
    597         }
    598     }
     600                    // --- add an admin reminder notice ---
     601                    global $wqreminder;
     602                    $wqreminder[$pluginslug] = $wqplugin;
     603                    $wqreminder[$pluginslug]['days'] = $dayssince;
     604                    $wqreminder[$pluginslug]['notice'] = $reminder;
     605                    add_action( 'admin_notices', 'wqhelper_reminder_notice' );
     606                }
     607            } else {
     608                $sidebaroptions['installdate'] = date( 'Y-m-d' );
     609                update_option( $prefix . '_sidebar_options', $sidebaroptions );
     610            }
     611        }
     612    }
    599613 };
    600614}
     
    614628
    615629            // --- reminder wrapper ---
    616             echo "<div class='updated notice is-dismissable' id='" . esc_attr( $pluginslug ) . "-reminder-notice' style='font-size:16px; line-height:24px; margin:0;'>";
    617 
    618             echo wqhelper_translate( "You've been enjoying" ) . ' ';
    619             echo $wqreminder[$pluginslug]['title'] . ' ' . wqhelper_translate( 'for' ) . ' ';
    620             echo $wqreminder[$pluginslug]['days'] . ' ' . wqhelper_translate( 'days' ) . '. ';
    621             echo wqhelper_translate( "If you like it, here's some ways you can help make it better" ) . ':<br>';
     630            echo '<div class="updated notice is-dismissable" id="' . esc_attr( $pluginslug ) . '-reminder-notice" style="font-size:16px; line-height:24px; margin:0;">';
     631
     632            echo esc_html( wqhelper_translate( "You've been enjoying" ) ) . ' ';
     633            echo esc_html( $wqreminder[$pluginslug]['title'] ) . ' ' . esc_html( wqhelper_translate( 'for' ) ) . ' ';
     634            echo esc_html( $wqreminder[$pluginslug]['days'] ) . ' ' . esc_html( wqhelper_translate( 'days' ) ) . '. ';
     635            echo esc_html( wqhelper_translate( "If you like it, here's some ways you can help make it better" ) ) . ':<br>';
    622636
    623637            // Action Links Table
     
    659673                            if ( 'bioship' == $pluginslug ) {
    660674                                // theme rate link --
    661                                 echo '<a class="notice-link" href="' . esc_url( $wqurls['wp'] ) . '/support/theme/' . $pluginslug . '/reviews/#new-post" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Rate this Theme' ) ) . '</a>';
     675                                $rateurl = $wqurls['wp'] . '/support/theme/' . $pluginslug . '/reviews/#new-post';
     676                                echo '<a class="notice-link" href="' . esc_url( $rateurl ) . '" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Rate this Theme' ) ) . '</a>';
    662677                            } else {
    663678                                // --- plugin rate link ---
    664                                 echo '<a class="notice-link" href="' . esc_url( $wqurls['wp'] ) . '/support/plugin/' . $pluginslug . '/reviews/#new-post" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Rate this Plugin' ) ) . '</a>';
     679                                $rateurl = $wqurls['wp'] . '/support/plugin/' . $pluginslug . '/reviews/#new-post';
     680                                echo '<a class="notice-link" href="' . esc_url( $rateurl ) . '" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Rate this Plugin' ) ) . '</a>';
    665681                            }
    666682                        echo '</li>';
     
    678694                            echo '<a class="notice-link" href="' . esc_url( $wqurls['bio'] ) . '#share" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Share this Theme' ) ) . '</a>';
    679695                        } else {
    680                             echo '<a class="notice-link" href="' . esc_url( $wqurls['wq'] ) . '/plugins/' . $pluginslug . '/#share" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Share this Plugin' ) ) . '</a>';
     696                            $shareurl = $wqurls['wq'] . '/plugins/' . $pluginslug . '/#share';
     697                            echo '<a class="notice-link" href="' . esc_url( $shareurl ) . '" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Share this Plugin' ) ) . '</a>';
    681698                        }
    682699                    echo '</li>';
     
    687704                    echo '<li>';
    688705                        echo '<span style="color:#00E;" class="dashicons dashicons-email-alt"></span> ';
    689                         echo '<a class="notice-link" href="' . esc_url( $wqurls['wq'] ) . '/support/' . $pluginslug . '" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Provide Feedback' ) ) . '</a>';
     706                        $supporturl = $wqurls['wq'] . '/support/' . $pluginslug;
     707                        echo '<a class="notice-link" href="' . esc_url( $supporturl ) . '" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Provide Feedback' ) ) . '</a>';
    690708                    echo "</li>";
    691709
     
    699717                        $upgradeurl = admin_url( 'admin.php' ) . '?page=' . $wqreminder['slug'] . '-pricing';
    700718                        echo '<li><a href="' . esc_url( $upgradeurl ) . '">';
    701                             echo '<b>&rarr; ' . wqhelper_translate( 'Go PRO' ) .'</b>';
     719                            echo '<b>&rarr; ' . esc_html( wqhelper_translate( 'Go PRO' ) ) . '</b>';
    702720                        echo '</a></li>';
    703721                    }
     
    710728                echo '<a href="' . esc_url( $dismisslink ) . '" target="wqdismissframe" style="text-decoration:none;" title="' . esc_attr( wqhelper_translate( 'Dismiss this Notice' ) ) . '">';
    711729                echo '<div class="dashicons dashicons-dismiss" style="font-size:16px;"></div></a>';
    712                
     730
    713731            echo '</td></tr></table></div>';
    714         }
    715 
    716         // --- notice styles ---
    717         // 1.7.5: added notice styling
    718         echo "<style>#wq-reminders ul {list-style:none; padding:0; margin:0;}
     732        }
     733
     734        // --- notice styles ---
     735        // 1.7.5: added notice styling
     736        echo "<style>#wq-reminders ul {list-style:none; padding:0; margin:0;}
    719737        #wq-reminders ul li {display:inline-block; margin-left:15px;}
    720738        #wq-reminders span.dashicons {display:inline; font-size:16px; color:#00E; vertical-align:middle;}
    721739        .notice-link {text-decoration:none;} .notice-link:hover {text-decoration:underline;}</style>";
    722740
    723         // --- notice dismissal iframe ---
    724         echo '<iframe style="display:none;" src="javascript:void(0);" name="wqdismissframe" id="wqdimissframe"></iframe>';
     741        // --- notice dismissal iframe ---
     742        echo '<iframe style="display:none;" src="javascript:void(0);" name="wqdismissframe" id="wqdimissframe"></iframe>';
    725743    };
    726744}
     
    730748// -----------------------
    731749$funcname = 'wqhelper_reminder_dismiss_' . $wqhv;
    732 if ( !isset( $wqfunctions[$funcname]) || !is_callable( $wqfunctions[$funcname] ) ) {
     750if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    733751    $wqfunctions[$funcname] = function() {
    734752
    735753        // --- check conditions ---
    736         $pluginslug = $_REQUEST['slug'];
    737         $notice = $_REQUEST['notice'];
    738         if ( ( '30' != $notice ) && ( '90' != $notice ) && ( '365' != $notice ) ) {
     754        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     755        $pluginslug = sanitize_title( $_REQUEST['slug'] );
     756        // 1.8.1: sanitize to integer and validate against array
     757        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     758        $notice = absint( $_REQUEST['notice'] );
     759        if ( !in_array( $notice, array( 30, 90, 365 ) ) ) {
    739760            return;
    740761        }
     
    780801        // 1.5.0: get plugin info (maximum twice daily)
    781802        $plugininfo = get_transient( 'wordquest_plugin_info' );
    782        
     803
    783804        // clear transient when debugging
    784805        if ( $wqdebug ) {
    785806            $plugininfo = '';
    786         } 
     807        }
    787808
    788809        // --- maybe get plugin info now ---
     
    791812            $args = array( 'timeout' => 15 );
    792813            $plugininfo = wp_remote_get( $pluginsurl, $args );
    793             if ( !is_wp_error($plugininfo ) ) {
     814            if ( !is_wp_error( $plugininfo ) ) {
    794815                $plugininfo = $plugininfo['body'];
    795816                $dataend = "*****END DATA*****";
     
    798819                    $plugininfo = substr( $plugininfo, 0, $pos );
    799820                    $plugininfo = json_decode( $plugininfo, true );
    800                     set_transient( 'wordquest_plugin_info', $plugininfo, (12*60*60 ) );
     821                    set_transient( 'wordquest_plugin_info', $plugininfo, ( 12 * 60 * 60 ) );
    801822                } else {
    802823                    $plugininfo = '';
     
    808829
    809830        if ( $wqdebug ) {
    810             echo "<!-- Plugin Info: "; print_r( $plugininfo ); echo " -->";
     831            // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     832            echo "<!-- Plugin Info: " . esc_html( print_r( $plugininfo ) ) . " -->";
    811833        }
    812834        return $plugininfo;
     
    817839// Version Specific Admin Page
    818840// ---------------------------
    819 $funcname = 'wqhelper_admin_page_'.$wqhv;
    820 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     841$funcname = 'wqhelper_admin_page_' . $wqhv;
     842if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    821843    $wqfunctions[$funcname] = function() {
    822844
     
    829851
    830852    // --- toggle metabox script ---
    831     echo "<script>function togglemetabox(divid) {
    832         var divid = divid+'-inside';
     853    echo "<script>function wq_togglemetabox(divid) {
     854        divid += '-inside';
    833855        if (document.getElementById(divid).style.display == '') {
    834856            document.getElementById(divid).style.display = 'none';
     
    855877        'wporgslug' => false,
    856878    );
    857     $args = array('wordquest', 'special');
    858     wqhelper_sidebar_floatbox($args);
     879    $args = array( 'wordquest', 'special' );
     880    wqhelper_sidebar_floatbox( $args );
    859881
    860882    // --- load sticky kit on sidebar ---
    861883    // 1.6.5: replace floatmenu with stickykit
    862     echo wqhelper_sidebar_stickykitscript();
    863     echo '<style>#floatdiv {float:right;} #wpcontent, #wpfooter {margin-left:150px !important;}</style>';
    864     echo '<script>jQuery("#floatdiv").stick_in_parent();</script>';
    865     unset($wordquestplugins['wordquest']);
     884    // 1.8.1: use new echo argument on stickykit function
     885    wqhelper_sidebar_stickykitscript( true );
     886    echo "<style>#floatdiv {float:right;} #wpcontent, #wpfooter {margin-left:150px !important;}</style>";
     887    echo "<script>jQuery('#floatdiv').stick_in_parent();</script>";
     888    unset( $wordquestplugins['wordquest'] );
    866889
    867890    // echo wqhelper_sidebar_floatmenuscript();
     
    880903
    881904    // --- Admin Page Title ---
    882     $wordquesticon = plugins_url('images/wordquest.png', __FILE__);
     905    $wordquesticon = plugins_url( 'images/wordquest.png', __FILE__ );
    883906    echo '<style>.wqlink {text-decoration:none;} .wqlink:hover {text-decoration:underline;}</style>';
    884     echo '<table><tr><td width="20"></td><td><img src="'.$wordquesticon.'"></td><td width="20"></td>';
    885     echo '<td><div id="page-title"><a href="'.$wqurls['wq'].'" target=_blank><h2>WordQuest Alliance</h2></a></div></td>';
    886     echo '<td width="30"></td><td><h4>&rarr; <a href="'.$wqurls['wq'].'/register/" class="wqlink" target=_blank>'.wqhelper_translate('Join').'</a></h4></td>';
    887     echo '<td> / </td><td><h4><a href="'.$wqurls['wq'].'/login/"  class="wqlink" target=_blank>'.wqhelper_translate('Login').'</a></h4></td>';
    888     echo '<td width="20"></td><td><h4>&rarr; <a href="'.$wqurls['wq'].'/solutions/"  class="wqlink" target=_blank>'.wqhelper_translate('Solutions').'</a></h4></td>';
    889     echo '<td width="20"></td><td><h4>&rarr; <a href="'.$wqurls['wq'].'/contribute/"  class="wqlink" target=_blank>'.wqhelper_translate('Contribute').'</a></h4></td>';
     907    echo '<table><tr>';
     908        echo '<td width="20"></td>';
     909        echo '<td><img src="' . esc_url( $wordquesticon ) . '" alt="' . esc_attr( wqhelper_translate( 'WordQuest icon' ) ) . '"></td>';
     910        echo '<td width="20"></td>';
     911        echo '<td><div id="page-title"><a href="' . esc_url( $wqurls['wq'] ) . '" target="_blank"><h2>WordQuest Alliance</h2></a></div></td>';
     912        echo '<td width="30"></td>';
     913        echo '<td><h4>&rarr; <a href="' . esc_url( $wqurls['wq'] ) . '/register/" class="wqlink" target="_blank">' . esc_html( wqhelper_translate( 'Join' ) ) . '</a></h4></td>';
     914        echo '<td> / </td>';
     915        echo '<td><h4><a href="' . esc_url( $wqurls['wq'] ) . '/login/" class="wqlink" target="_blank">' . esc_html( wqhelper_translate( 'Login' ) ) . '</a></h4></td>';
     916        echo '<td width="20"></td>';
     917        echo '<td><h4>&rarr; <a href="' . esc_url( $wqurls['wq'] ) . '/solutions/" class="wqlink" target="_blank">' . esc_html( wqhelper_translate( 'Solutions' ) ) . '</a></h4></td>';
     918        echo '<td width="20"></td>';
     919        echo '<td><h4>&rarr; <a href="' . esc_url( $wqurls['wq'] ) . '/contribute/" class="wqlink" target="_blank">' . esc_html( wqhelper_translate( 'Contribute' ) ) . '</a></h4></td>';
    890920    echo '</tr></table>';
    891921
    892922    // --- Output Plugins Column ---
    893     wqhelper_admin_plugins_column(null);
     923    wqhelper_admin_plugins_column( null );
    894924
    895925    // --- Output Feeds Column ---
    896     wqhelper_admin_feeds_column(null);
     926    wqhelper_admin_feeds_column( null );
    897927
    898928    // --- Wordquest Sidebar 'plugin' box ---
    899     function wq_sidebar_plugin_footer() {
    900         global $wqurls;
    901         $iconurl = plugins_url('images/wordquest.png', __FILE__);
    902         echo '<div id="pluginfooter"><div class="stuffbox" style="width:250px;background-color:#ffffff;"><h3>Source Info</h3><div class="inside">';
    903         echo "<center><table><tr>";
    904         echo "<td><a href='".$wqurls['wq']."' target='_blank'><img src='".$iconurl."' border=0></a></td></td>";
    905         echo "<td width='14'></td>";
    906         echo "<td><a href='".$wqurls['wq']."' target='_blank'>WordQuest Alliance</a><br>";
    907         echo "<a href='".$wqurls['wq']."/plugins/' target='_blank'><b>&rarr; WordQuest Plugins</b></a><br>";
    908         echo "<a href='".$wqurls['prn']."/directory/' target='_blank'>&rarr; Plugin Directory</a></td>";
    909         echo "</tr></table></center>";
    910         echo '</div></div></div>';
     929    if ( !function_exists( 'wq_sidebar_plugin_footer' ) ) {
     930        function wq_sidebar_plugin_footer() {
     931            global $wqurls;
     932            $iconurl = plugins_url( 'images/wordquest.png', __FILE__ );
     933            echo '<div id="pluginfooter"><div class="stuffbox" style="width:250px;background-color:#ffffff;"><h3>' . esc_html( wqhelper_translate( 'Source Info' ) ) . '</h3><div class="inside">';
     934            echo '<center><table><tr>';
     935                echo '<td><a href="' . esc_url( $wqurls['wq'] ) . '" target="_blank"><img src="' . esc_url( $iconurl ) . '" alt="' . esc_attr( wqhelper_translate( 'WordQuest Icon' ) ) . ' "border="0"></a></td>';
     936                echo '<td width="14"></td>';
     937                echo '<td><a href="' . esc_url( $wqurls['wq'] ) . '" target="_blank">WordQuest Alliance</a><br>';
     938                echo '<a href="' . esc_url( $wqurls['wq'] ) . '/plugins/" target="_blank"><b>&rarr; WordQuest Plugins</b></a><br>';
     939                echo '<a href="' . esc_url( $wqurls['prn'] ) . '/directory/" target="_blank">&rarr; Plugin Directory</a></td>';
     940                echo '</tr></table></center>';
     941            echo '</div></div></div>';
     942        }
    911943    }
    912944
     
    923955// Version Specific Plugins Column
    924956// -------------------------------
    925 $funcname = 'wqhelper_admin_plugins_column_'.$wqhv;
    926 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    927     $wqfunctions[$funcname] = function($args) {
     957$funcname = 'wqhelper_admin_plugins_column_' . $wqhv;
     958if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     959    $wqfunctions[$funcname] = function( $args ) {
    928960
    929961    global $wordquesthelper, $wordquestplugins, $wqurls, $wqdebug;
     
    932964    // 1.6.6: check if current WQ plugins are all installed via WordPress.Org
    933965    // (if so, only provide option to install other WQ plugins in repository)
    934     global $wordpressorgonly; $wordpressorgonly = true;
    935     foreach ($wordquestplugins as $pluginslug => $plugin) {
    936         // if this is false, it was from wordquest not wordpress
    937         if (!$plugin['wporg']) {$wordpressorgonly = false;}
     966    global $wq_wordpress_org;
     967    $wq_wordpress_org = true;
     968    foreach ( $wordquestplugins as $pluginslug => $plugin ) {
     969        // - if this is false, it was from WordQuest not WordPress -
     970        if ( !$plugin['wporg'] ) {
     971            $wq_wordpress_org = false;
     972        }
    938973    }
    939974
     
    942977    // TODO: test all options here more thoroughly..?
    943978    echo "<script>
    944     function dopluginaction(pluginslug) {
    945         var selectelement = document.getElementById(pluginslug+'-action');
    946         var actionvalue = selectelement.options[selectelement.selectedIndex].value;
    947         var linkel = document.getElementById(pluginslug+'-link');
    948         var adminpageurl = '".admin_url('admin.php')."';
     979    function wq_plugin_action(pluginslug) {
     980        selectelement = document.getElementById(pluginslug+'-action');
     981        actionvalue = selectelement.options[selectelement.selectedIndex].value;
     982        linkel = document.getElementById(pluginslug+'-link');
     983        adminpageurl = '" . esc_url( admin_url( 'admin.php' ) ) . "';
     984        wqurl = '" . esc_url( $wqurls['wq'] ) . "';
    949985        if (actionvalue == 'settings') {linkel.target = '_self'; linkel.href = adminpageurl+'?page='+pluginslug;}
    950986        if (actionvalue == 'update') {linkel.target = '_self'; linkel.href = document.getElementById(pluginslug+'-update-link').value;}
     
    952988        if (actionvalue == 'install') {linkel.target = '_self'; linkel.href = document.getElementById(pluginslug+'-install-link').value;}
    953989        if (actionvalue == 'support') {linkel.target = '_blank'; linkel.href = adminpageurl+'?page='+pluginslug+'-wp-support-forum';}
    954         if (actionvalue == 'donate') {linkel.target = '_blank'; linkel.href = '".$wqurls['wq']."/contribute/?plugin='+pluginslug;}
    955         if (actionvalue == 'testimonial') {linkel.target = '_blank'; linkel.href = '".$wqurls['wq']."/contribute/?tab=testimonial';}
    956         if (actionvalue == 'rate') {linkel = '_blank'; linkel.href = '".$wqurls['wp']."/plugins/'+pluginslug+'/reviews/#new-post';}
    957         if (actionvalue == 'development') {linkel.target = '_blank'; linkel.href= '".$wqurls['wq']."/contribute/?tab=development';}
     990        if (actionvalue == 'donate') {linkel.target = '_blank'; linkel.href = wqurl+'/contribute/?plugin='+pluginslug;}
     991        if (actionvalue == 'testimonial') {linkel.target = '_blank'; linkel.href = wqurl+'/contribute/?tab=testimonial';}
     992        if (actionvalue == 'rate') {linkel.target = '_blank'; linkel.href = '" . esc_url( $wqurls['wp'] ) . "/plugins/'+pluginslug+'/reviews/#new-post';}
     993        if (actionvalue == 'development') {linkel.target = '_blank'; linkel.href= wqurl+'/contribute/?tab=development';}
    958994        if (actionvalue == 'contact') {linkel.target = '_self'; linkel.href = adminpageurl+'?page='+pluginslug+'-contact';}
    959         if (actionvalue == 'home') {linkel.target = '_blank'; linkel.href = '".$wqurls['wq']."/plugins/'+pluginslug+'/';}
     995        if (actionvalue == 'home') {linkel.target = '_blank'; linkel.href = wqurl+'/plugins/'+pluginslug+'/';}
    960996        if (actionvalue == 'upgrade') {linkel.target = '_self'; linkel.href = adminpageurl+'?page='+pluginslug+'-pricing';}
    961997        if (actionvalue == 'account') {linkel.target = '_self'; linkel.href = adminpageurl+'?page='+pluginslug+'-account';}
     
    9661002
    9671003    // --- Get Installed and Active Plugin Slugs ---
    968     $i = 0; foreach ($wordquestplugins as $pluginslug => $values) {$pluginslugs[$i] = $pluginslug; $i++;}
     1004    $i = 0;
     1005    $pluginslugs = array();
     1006    foreach ( $wordquestplugins as $pluginslug => $values ) {
     1007        $pluginslugs[$i] = $pluginslug;
     1008        $i++;
     1009    }
    9691010    // if ($wqdebug) {echo "<!-- Active Wordquest Plugins: "; print_r($pluginslugs); echo " -->";}
    9701011
    9711012    // --- Get All Installed Plugins Info ---
    972     $i = 0; $installedplugins = get_plugins();
    973     foreach ($installedplugins as $pluginfile => $values) {$installedslugs[$i] = sanitize_title($values['Name']); $i++;}
     1013    $i = 0;
     1014    $installedplugins = get_plugins();
     1015    $installedslugs = array();
     1016    foreach ( $installedplugins as $pluginfile => $values ) {
     1017        $installedslugs[$i] = sanitize_title( $values['Name'] );
     1018        $i++;
     1019    }
    9741020    // if ($wqdebug) {echo "<!-- Installed Plugins: "; print_r($installedplugins); echo " -->";}
    9751021    // if ($wqdebug) {echo "<!-- Installed Plugin Slugs: "; print_r($installedslugs); echo " -->";}
     
    9781024    // ----------------------
    9791025    // 1.6.6: define empty pluginupdates array
    980     $i = 0; $updateplugins = get_site_transient('update_plugins'); $pluginupdates = array();
     1026    $i = 0;
     1027    $updateplugins = get_site_transient( 'update_plugins' );
     1028    $pluginupdates = array();
    9811029    // 1.7.3: adde property exists check
    982     if (property_exists($updateplugins, 'response')) {
    983         foreach ($updateplugins->response as $pluginfile => $values) {$pluginupdates[$i] = $values->slug; $i++;}
     1030    if ( property_exists( $updateplugins, 'response' ) ) {
     1031        foreach ( $updateplugins->response as $pluginfile => $values ) {
     1032            $pluginupdates[$i] = $values->slug;
     1033            $i++;
     1034        }
    9841035    }
    9851036    // if ($wqdebug) {echo "<!-- Plugin Updates: "; print_r($updateplugins); echo " -->";}
     
    9901041
    9911042    // process plugin info
    992     $i = 0; $wqplugins = $wqpluginslugs = array();
    993     if (is_array($plugininfo)) {
    994         foreach ($plugininfo as $plugin) {
    995             // print_r($plugin); // debug point
    996             if (isset($plugin['slug'])) {
    997                 $wqpluginslugs[$i] = $pluginslug = $plugin['slug']; $i++;
    998                 if (isset($plugin['title'])) {$wqplugins[$pluginslug]['title'] = $plugin['title'];}
    999                 if (isset($plugin['home'])) {$wqplugins[$pluginslug]['home'] = $plugin['home'];}
    1000                 if (isset($plugin['description'])) {$wqplugins[$pluginslug]['description'] = $plugin['description'];}
    1001                 if (isset($plugin['icon'])) {$wqplugins[$pluginslug]['icon'] = $plugin['icon'];}
    1002                 if (isset($plugin['paidplans'])) {$wqplugins[$pluginslug]['paidplans'] = $plugin['paidplans'];}
    1003                 if (isset($plugin['package'])) {$wqplugins[$pluginslug]['package'] = $plugin['package'];}
    1004 
    1005                 if (isset($plugin['tags'])) {$wqplugins[$pluginslug]['tags'] = $plugin['tags'];}
    1006                 if (isset($plugin['cats'])) {$wqplugins[$pluginslug]['cats'] = $plugin['cats'];}
     1043    $i = 0;
     1044    $wqplugins = $wqpluginslugs = array();
     1045    if ( is_array( $plugininfo ) ) {
     1046        foreach ( $plugininfo as $plugin ) {
     1047            // print_r( $plugin ); // debug point
     1048            if ( isset( $plugin['slug'] ) ) {
     1049                $wqpluginslugs[$i] = $pluginslug = $plugin['slug'];
     1050                $i++;
     1051                if ( isset( $plugin['title'] ) ) {
     1052                    $wqplugins[$pluginslug]['title'] = $plugin['title'];
     1053                }
     1054                if ( isset( $plugin['home'] ) ) {
     1055                    $wqplugins[$pluginslug]['home'] = $plugin['home'];
     1056                }
     1057                if ( isset( $plugin['description'] ) ) {
     1058                    $wqplugins[$pluginslug]['description'] = $plugin['description'];
     1059                }
     1060                if ( isset( $plugin['icon'] ) ) {
     1061                    $wqplugins[$pluginslug]['icon'] = $plugin['icon'];
     1062                }
     1063                if ( isset( $plugin['paidplans'] ) ) {
     1064                    $wqplugins[$pluginslug]['paidplans'] = $plugin['paidplans'];
     1065                }
     1066                if ( isset( $plugin['package'] ) ) {
     1067                    $wqplugins[$pluginslug]['package'] = $plugin['package'];
     1068                }
     1069
     1070                if ( isset( $plugin['tags'] ) ) {
     1071                    $wqplugins[$pluginslug]['tags'] = $plugin['tags'];
     1072                }
     1073                if ( isset( $plugin['cats'] ) ) {
     1074                    $wqplugins[$pluginslug]['cats'] = $plugin['cats'];
     1075                }
    10071076
    10081077                // 1.6.5: check release date and status
    1009                 if (isset($plugin['releasedate'])) {$wqplugins[$pluginslug]['releasedate'] = $plugin['releasedate'];}
    1010                 if (isset($plugin['releasestatus'])) {$wqplugins[$pluginslug]['releasestatus'] = $plugin['releasestatus'];}
    1011                 else {$wqplugins[$pluginslug]['releasestatus'] = 'Upcoming';}
     1078                if ( isset( $plugin['releasedate'] ) ) {
     1079                    $wqplugins[$pluginslug]['releasedate'] = $plugin['releasedate'];
     1080                }
     1081                if ( isset( $plugin['releasestatus'] ) ) {
     1082                    $wqplugins[$pluginslug]['releasestatus'] = $plugin['releasestatus'];
     1083                } else {
     1084                    $wqplugins[$pluginslug]['releasestatus'] = 'Upcoming';
     1085                }
    10121086
    10131087                // 1.6.6: check for wordpress.org slug
    1014                 if (isset($plugin['wporgslug'])) {$wqplugins[$pluginslug]['wporgslug'] = $plugin['wporgslug'];}
    1015                 else {$wpplugins[$pluginslug]['wporgslug'] = false;}
    1016 
    1017                 if (in_array($pluginslug, $installedslugs)) {$wqplugins[$pluginslug]['installed'] = 'yes';}
    1018                 else {$wqplugins[$pluginslug]['installed'] = 'no';}
     1088                if ( isset( $plugin['wporgslug'] ) ) {
     1089                    $wqplugins[$pluginslug]['wporgslug'] = $plugin['wporgslug'];
     1090                } else {
     1091                    $wpplugins[$pluginslug]['wporgslug'] = false;
     1092                }
     1093
     1094                if ( in_array( $pluginslug, $installedslugs ) ) {
     1095                    $wqplugins[$pluginslug]['installed'] = 'yes';
     1096                } else {
     1097                    $wqplugins[$pluginslug]['installed'] = 'no';
     1098                }
    10191099
    10201100                // --- get latest plugin release ---
    1021                 if (isset($plugin['latestrelease']) && ($plugin['latestrelease'] == 'yes')) {
     1101                if ( isset( $plugin['latestrelease'] ) && ( 'yes' == $plugin['latestrelease'] ) ) {
    10221102                    $wqplugins[$pluginslug]['latestrelease'] = 'yes';
    10231103                    $latestrelease = $wqplugins[$pluginslug];
     
    10271107                // --- get next plugin release ---
    10281108                // 1.6.5: check for next plugin release also
    1029                 if (isset($plugin['nextrelease']) && ($plugin['nextrelease'] == 'yes')) {
     1109                if ( isset( $plugin['nextrelease'] ) && ( 'yes' == $plugin['nextrelease'] ) ) {
    10301110                    $wqplugins[$pluginslug]['nextrelease'] = 'yes';
    10311111                    $nextrelease = $wqplugins[$pluginslug];
     
    10361116    }
    10371117    // if ($wqdebug) {echo "<!-- WQ Plugin Slugs: "; print_r($wqpluginslugs); echo " -->";}
    1038     if ($wqdebug) {echo "<!-- WQ Plugins: "; print_r($wqplugins); echo " -->";}
     1118    if ( $wqdebug ) {
     1119        // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     1120        echo "<!-- WQ Plugins: " . esc_html( print_r( $wqplugins ) ) . " -->";
     1121    }
    10391122
    10401123    // --- maybe set Plugin Release Info ---
    10411124    global $wqreleases;
    1042     if (isset($latestrelease)) {$wqreleases['latest'] = $latestrelease;}
    1043     if (isset($nextrelease)) {$wqreleases['next'] = $nextrelease;}
     1125    if ( isset( $latestrelease ) ) {
     1126        $wqreleases['latest'] = $latestrelease;
     1127    }
     1128    if ( isset( $nextrelease ) ) {
     1129        $wqreleases['next'] = $nextrelease;
     1130    }
    10441131
    10451132    // --- get Installed Wordquest Plugin Data ---
    1046     $plugins = array(); $inactiveplugins = array();
     1133    $plugins = $inactiveplugins = $pluginfiles = $inactiveversions = array();
    10471134    $i = $j = 0;
    1048     foreach ($installedplugins as $pluginfile => $values) {
    1049 
    1050         $pluginslug = sanitize_title($values['Name']);
     1135    foreach ( $installedplugins as $pluginfile => $values ) {
     1136
     1137        $pluginslug = sanitize_title( $values['Name'] );
    10511138        $pluginfiles[$pluginslug] = $pluginfile;
    10521139        // echo '***'.$pluginslug.'***'; // debug point
    1053         if (in_array($pluginslug, $wqpluginslugs) || in_array($pluginslug, $pluginslugs)) {
     1140        if ( in_array( $pluginslug, $wqpluginslugs ) || in_array( $pluginslug, $pluginslugs ) ) {
    10541141
    10551142            // --- set plugin data ---
     
    10611148
    10621149            // --- check for matching plugin update ---
    1063             if (in_array($pluginslug, $pluginupdates)) {$plugins[$i]['update'] = 'yes';}
    1064             else {$plugins[$i]['update'] = 'no';}
     1150            if ( in_array( $pluginslug, $pluginupdates ) ) {
     1151                $plugins[$i]['update'] = 'yes';
     1152            } else {
     1153                $plugins[$i]['update'] = 'no';
     1154            }
    10651155
    10661156            // --- filter out to get inactive plugins ---
    1067             if (!in_array($pluginslug, $pluginslugs)) {
    1068                 $inactiveplugins[$j] = $pluginslug; $j++;
     1157            if ( !in_array( $pluginslug, $pluginslugs ) ) {
    10691158                $inactiveversions[$pluginslug] = $values['Version'];
     1159                $inactiveplugins[$j] = $pluginslug;
     1160                $j++;
    10701161            }
    10711162            $i++;
     
    10761167
    10771168    // --- check if BioShip Theme installed ---
    1078     $themes = wp_get_themes(); $bioshipinstalled = false;
    1079     foreach ($themes as $theme) {if ($theme->stylesheet == 'bioship') {$bioshipinstalled = true;} }
     1169    $themes = wp_get_themes();
     1170    $bioshipinstalled = false;
     1171    foreach ( $themes as $theme ) {
     1172        // 1.8.0: use public get_stylesheet method
     1173        if ( 'bioship' == $theme->get_stylesheet() ) {
     1174            $bioshipinstalled = true;
     1175        }
     1176    }
    10801177
    10811178    // --- open plugin column ---
     
    10841181        // Active Plugin Panel
    10851182        // -------------------
    1086         $boxid = 'wordquestactive'; $boxtitle = wqhelper_translate('Active WordQuest Plugins');
    1087         echo '<div id="'.$boxid.'" class="postbox">';
    1088         echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1089         echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;"><table>';
    1090         foreach ($wordquestplugins as $pluginslug => $plugin) {
    1091             if ($pluginslug != 'bioship') { // filter out theme here
     1183        $boxid = 'wordquestactive';
     1184        $boxtitle = wqhelper_translate( 'Active WordQuest Plugins' );
     1185        echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1186        echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1187        echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1188        echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside" style="margin-bottom:0;"><table>';
     1189        foreach ( $wordquestplugins as $pluginslug => $plugin ) {
     1190            // filter out theme here
     1191            if ( 'bioship' != $pluginslug ) {
    10921192
    10931193                // --- set update link ---
    1094                 if (in_array($pluginslug, $pluginupdates)) {
    1095                     $updatelink = admin_url('update.php').'?action=upgrade-plugin&plugin='.$pluginfiles[$pluginslug];
    1096                     $updatelink = wp_nonce_url($updatelink, 'upgrade-plugin_'.$pluginfiles[$pluginslug]);
    1097                     echo "<input type='hidden' id='".$pluginslug."-update-link' value='".$updatelink."'>";
     1194                if ( in_array( $pluginslug, $pluginupdates ) ) {
     1195                    $updatelink = admin_url( 'update.php' ) . '?action=upgrade-plugin&plugin=' . $pluginfiles[$pluginslug];
     1196                    $updatelink = wp_nonce_url( $updatelink, 'upgrade-plugin_' . $pluginfiles[$pluginslug] );
     1197                    echo '<input type="hidden" id="' . esc_attr( $pluginslug ) . '-update-link" value="' . esc_url( $updatelink ) . '">';
    10981198                }
    10991199
    11001200                // --- linked title and version ---
    1101                 echo "<tr><td><a href='".$wqurls['wq']."/plugins/".$pluginslug."' class='pluginlink' target=_blank>";
    1102                 echo $plugin['title']."</a></td><td width='20'></td>";
    1103                 echo "<td>".$plugin['version']."</td><td width='20'></td>";
     1201                echo '<tr><td>';
     1202                    echo '<a href="' . esc_url( $wqurls['wq'] ) . '/plugins/' . esc_attr( $pluginslug ) . '" class="pluginlink" target="_blank">';
     1203                    echo esc_html( $plugin['title'] ) . '</a>';
     1204                echo '</td><td width="20"></td><td>';
     1205                    echo esc_html( $plugin['version'] );
     1206                echo '</td><td width="20"></td>';
    11041207
    11051208                // --- update / settings options ---
    1106                 echo "<td><select name='".$pluginslug."-action' id='".$pluginslug."-action' style='font-size:8pt;'>";
    1107                 if (in_array($pluginslug, $pluginupdates)) {
    1108                     echo "<option value='update' selected='selected'>".wqhelper_translate('Update')."</option>";
    1109                     echo "<option value='settings'>".wqhelper_translate('Settings')."</option>";
    1110                 } else {echo "<option value='settings' selected='selected'>".wqhelper_translate('Settings')."</option>";}
     1209                echo '<td><select name="' . esc_attr( $pluginslug ) . '-action" id="' . esc_attr( $pluginslug ) . '-action" style="font-size:8pt;">';
     1210                if ( in_array( $pluginslug, $pluginupdates ) ) {
     1211                    echo '<option value="update" selected="selected">' . esc_html( wqhelper_translate( 'Update' ) ) . '</option>';
     1212                    echo '<option value="settings">' . esc_html( wqhelper_translate( 'Settings' ) ) . '</option>';
     1213                } else {
     1214                    echo '<option value="settings" selected="selected">' . esc_html( wqhelper_translate( 'Settings' ) ) . '</option>';
     1215                }
    11111216
    11121217                // --- donate / testimonial / support / development options ---
    1113                 echo "<option value='donate'>".wqhelper_translate('Donate')."</option>";
    1114                 // echo "<option value='testimonial'>".wqhelper_translate('Testimonial')."</option>";
    1115                 echo "<option value='support'>".wqhelper_translate('Support')."</option>";
    1116                 echo "<option value='development'>".wqhelper_translate('Development')."</option>";
    1117                 if (isset($plugin['wporgslug'])) {echo "<option value='Rate'>".wqhelper_translate('Rate')."</option>";}
     1218                echo '<option value="donate">' . esc_html( wqhelper_translate( 'Donate' ) ) . '</option>';
     1219                // echo '<option value="testimonial">' . esc_html( wqhelper_translate( 'Testimonial' ) . '</option>';
     1220                echo '<option value="support">' . esc_html( wqhelper_translate( 'Support' ) ) . '</option>';
     1221                echo '<option value="development">' . esc_html( wqhelper_translate( 'Development' ) ) . '</option>';
     1222                if ( isset( $plugin['wporgslug'] ) ) {
     1223                    echo '<option value="Rate">' . esc_html( wqhelper_translate( 'Rate' ) ) . '</option>';
     1224                }
    11181225
    11191226                // --- check for Pro Plan availability ---
     
    11211228                // TODO: check for Pro add-ons ?
    11221229                // if ($plugin['plan'] == 'premium') {echo "<option value='contact'>".wqhelper_translate('Contact')."</option>";}
    1123                 if (isset($wordquestplugins[$pluginslug]['hasplans']) && $wordquestplugins[$pluginslug]['hasplans']) {
     1230                if ( isset( $wordquestplugins[$pluginslug]['hasplans'] ) && $wordquestplugins[$pluginslug]['hasplans'] ) {
    11241231                    // 1.7.7: add isset check for plugin plan for back-compat
    11251232                    if ( !isset( $plugin['plan'] ) || ( 'premium' != $plugin['plan'] ) ) {
    1126                         echo "<option style='font-weight:bold;' value='upgrade'>".wqhelper_translate('Go PRO!')."</option>";
     1233                        echo '<option style="font-weight:bold;" value="upgrade">' . esc_html( wqhelper_translate( 'Go PRO' ) ) . '</option>';
    11271234                    } else {
    1128                         echo "<option value='account'>".wqhelper_translate('Account')."</option>";
     1235                        echo '<option value="account">' . esc_html( wqhelper_translate( 'Account' ) ) . '</option>';
    11291236                    }
    11301237                }
    11311238
    1132                 // --- close select ---
    1133                 echo "</select></td><td width='20'></td>";
     1239                // --- close action select ---
     1240                echo '</select></td><td width="20"></td>';
    11341241
    11351242                // --- do selected action button ---
    1136                 echo "<td><a href='javascript:void(0);' target=_blank id='".$pluginslug."-link' onclick='dopluginaction(\"".$pluginslug."\");'>";
    1137                 echo "<input class='button-secondary' type='button' value='".wqhelper_translate('Go')."'></a></td></tr>";
     1243                echo '<td>';
     1244                    echo '<a href="javascript:void(0);" target="_blank" id="' . esc_attr( $pluginslug ) . '-link" onclick="wq_plugin_action(\'' . esc_attr( $pluginslug ) . '\');">';
     1245                    echo '<input class="button-secondary" type="button" value="' . esc_attr( wqhelper_translate( 'Go' ) ) . '"></a>';
     1246                echo '</td></tr>';
    11381247            }
    11391248        }
     
    11421251        // Inactive Plugin Panel
    11431252        // ---------------------
    1144         if (count($inactiveplugins) > 0) {
    1145             $boxid = 'wordquestinactive'; $boxtitle = wqhelper_translate('Inactive WordQuest Plugins');
    1146             echo '<div id="'.$boxid.'" class="postbox">';
    1147             echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1148             echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;"><table>';
    1149             foreach ($inactiveplugins as $inactiveplugin) {
     1253        if ( count( $inactiveplugins ) > 0 ) {
     1254            $boxid = 'wordquestinactive';
     1255            $boxtitle = wqhelper_translate( 'Inactive WordQuest Plugins' );
     1256            echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1257            echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1258            echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1259            echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside" style="margin-bottom:0;"><table>';
     1260            foreach ( $inactiveplugins as $inactiveplugin ) {
    11501261
    11511262                // --- set activate link ---
    1152                 $activatelink = admin_url('plugins.php').'?action=activate&plugin='.$pluginfiles[$inactiveplugin];
    1153                 $activatelink = wp_nonce_url($activatelink, 'activate-plugin_'.$pluginfiles[$inactiveplugin]);
    1154                 echo "<input type='hidden' id='".$inactiveplugin."-activate-link' value='".$activatelink."'>";
     1263                $activatelink = admin_url( 'plugins.php' ) . '?action=activate&plugin=' . $pluginfiles[$inactiveplugin];
     1264                $activatelink = wp_nonce_url( $activatelink, 'activate-plugin_' . $pluginfiles[$inactiveplugin] );
     1265                echo "<input type='hidden' id='" . esc_attr( $inactiveplugin ) . "-activate-link' value='" . esc_url( $activatelink ) . "'>";
    11551266
    11561267                // --- set update link ---
    1157                 if (in_array($inactiveplugin, $pluginupdates)) {
    1158                     $updatelink = admin_url('update.php').'?action=upgrade-plugin&plugin='.$pluginfiles[$inactiveplugin];
    1159                     $updatelink = wp_nonce_url($updatelink, 'upgrade-plugin_'.$pluginfiles[$inactiveplugins]);
    1160                     echo "<input type='hidden' id='".$inactiveplugin."-update-link' value='".$updatelink."'>";
     1268                if ( in_array( $inactiveplugin, $pluginupdates ) ) {
     1269                    $updatelink = admin_url( 'update.php' ) . '?action=upgrade-plugin&plugin=' . $pluginfiles[$inactiveplugin];
     1270                    // 1.8.0: fix to incorrect plural key usage, should be singular
     1271                    $updatelink = wp_nonce_url( $updatelink, 'upgrade-plugin_' . $pluginfiles[$inactiveplugin] );
     1272                    echo "<input type='hidden' id='" . esc_attr( $inactiveplugin ) . "-update-link' value='" . esc_url( $updatelink ) . "'>";
    11611273                }
    11621274
    11631275                // --- linked title and version ---
    1164                 echo "<tr><td><a href='".$wqplugins[$inactiveplugin]['home']."' class='pluginlink' target=_blank>";
    1165                 echo $wqplugins[$inactiveplugin]['title']."</a></td><td width='20'></td>";
    1166                 echo "<td>".$inactiveversions[$inactiveplugin]."</td><td width='20'></td>";
     1276                echo '<tr><td>';
     1277                    echo '<a href="' . esc_url( $wqplugins[$inactiveplugin]['home'] ) . '" class="pluginlink" target="_blank">';
     1278                    echo esc_html( $wqplugins[$inactiveplugin]['title'] ) . '</a>';
     1279                echo '</td><td width="20"></td><td>';
     1280                    echo esc_html( $inactiveversions[$inactiveplugin] );
     1281                echo '</td><td width="20"></td>';
    11671282
    11681283                // --- select plugin action ---
    1169                 echo "<td><select name='".$inactiveplugin."-action' id='".$inactiveplugin."-action' style='font-size:8pt;'>";
    1170                 if (in_array($inactiveplugin, $pluginupdates)) {
    1171                     echo "<option value='update' selected='selected'>".wqhelper_translate('Update')."</option>";
    1172                     echo "<option value='activate'>".wqhelper_translate('Activate')."</option>";
    1173                 } else {echo "<option value='activate' selected='selected'>".wqhelper_translate('Activate')."</option>";}
    1174                 echo "</select></td><td width='20'></td>";
     1284                echo '<td><select name="' . esc_attr( $inactiveplugin ) . '-action" id="' . esc_attr( $inactiveplugin ) . '-action" style="font-size:8pt;">';
     1285                if ( in_array( $inactiveplugin, $pluginupdates ) ) {
     1286                    echo '<option value="update" selected="selected">' . esc_html( wqhelper_translate( 'Update' ) ) . '</option>';
     1287                    echo '<option value="activate">' . esc_html( wqhelper_translate( 'Activate' ) ) . '</option>';
     1288                } else {
     1289                    echo '<option value="activate" selected="selected">' . esc_html( wqhelper_translate( 'Activate' ) ) . '</option>';
     1290                }
     1291                echo '</select></td><td width="20"></td>';
    11751292
    11761293                // --- plugin action button ---
    1177                 echo "<td><a href='javascript:void(0);' target=_blank id='".$inactiveplugin."-link' onclick='dopluginaction(\"".$inactiveplugin."\");'>";
    1178                 echo "<input class='button-secondary' type='button' value='".wqhelper_translate('Go')."'></a></td>";
    1179                 echo "</tr>";
     1294                echo '<td>';
     1295                    echo '<a href="javascript:void(0);" target="_blank" id="' . esc_attr( $inactiveplugin ) . '-link" onclick="wq_plugin_action(\'' . esc_attr( $inactiveplugin ) . '\');">';
     1296                    echo '<input class="button-secondary" type="button" value="' . esc_html( wqhelper_translate( 'Go' ) ) . '"></a>';
     1297                echo '</td></tr>';
    11801298            }
    11811299            echo '</table></div></div>';
     
    11831301
    11841302        $releasedplugins = $unreleasedplugins = array();
    1185         if ( count($wqplugins) > count($wordquestplugins) ) {
    1186             foreach ($wqplugins as $pluginslug => $wqplugin) {
    1187                 if (!in_array($pluginslug, $installedslugs) && !in_array($pluginslug, $inactiveplugins)) {
    1188                     if ($wqplugin['releasestatus'] == 'Released') {$releasedplugins[$pluginslug] = $wqplugin;}
    1189                     else {
    1190                         $releasetime = strtotime($wqplugin['releasedate']);
     1303        if ( count( $wqplugins ) > count( $wordquestplugins ) ) {
     1304            foreach ( $wqplugins as $pluginslug => $wqplugin ) {
     1305                if ( !in_array( $pluginslug, $installedslugs ) && !in_array( $pluginslug, $inactiveplugins ) ) {
     1306                    if ( 'Released' == $wqplugin['releasestatus'] ) {
     1307                        $releasedplugins[$pluginslug] = $wqplugin;
     1308                    } else {
     1309                        $releasetime = strtotime( $wqplugin['releasedate'] );
    11911310                        $wqplugin['slug'] = $pluginslug;
    11921311                        $unreleasedplugins[$releasetime] = $wqplugin;
     
    11981317        // Available Plugin Panel
    11991318        // ----------------------
    1200         if (count($releasedplugins) > 0) {
    1201             if ($wqdebug) {echo "<!-- Released Plugins: "; print_r($releasedplugins); echo " -->";}
    1202             $boxid = 'wordquestavailable'; $boxtitle = wqhelper_translate('Available WordQuest Plugins');
    1203             echo '<div id="'.$boxid.'" class="postbox">';
    1204             echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1205             echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;"><table>';
    1206 
    1207             foreach ($releasedplugins as $pluginslug => $wqplugin) {
     1319        if ( count( $releasedplugins ) > 0 ) {
     1320
     1321            if ( $wqdebug ) {
     1322                // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     1323                echo "<!-- Released Plugins: " . esc_html( print_r( $releasedplugins, true ) ) . " -->";
     1324            }
     1325
     1326            $boxid = 'wordquestavailable';
     1327            $boxtitle = wqhelper_translate( 'Available WordQuest Plugins' );
     1328            echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1329            echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1330            echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1331            echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside" style="margin-bottom:0;"><table>';
     1332
     1333            foreach ( $releasedplugins as $pluginslug => $wqplugin ) {
    12081334
    12091335                // --- set install plugin link ---
    12101336                // 1.6.5: add separate install link URL for each plugin for nonce checking
    12111337                // 1.6.6: use wordpress.org link if all plugins are from wordpress.org
    1212                 if ($wordpressorgonly && $wqplugin['wporgslug']) {
    1213                     $installlink = self_admin_url('update.php')."?action=install-plugin&plugin=".$wqplugin['wporgslug'];
    1214                     $installlink = wp_nonce_url($installlink, 'install-plugin_'.$wqplugin['wporgslug']);
    1215                     echo "<input type='hidden' name='".$pluginslug."-install-link' value='".$installlink."'>";
    1216                 } elseif (!$wordpressorgonly && is_array($wqplugin['package'])) {
    1217                     $installlink = admin_url('update.php')."?action=wordquest_plugin_install&plugin=".$pluginslug;
    1218                     $installlink = wp_nonce_url($installlink, 'plugin-upload');
    1219                     echo "<input type='hidden' name='".$pluginslug."-install-link' value='".$installlink."'>";
     1338                if ( $wq_wordpress_org && $wqplugin['wporgslug'] ) {
     1339                    $installlink = self_admin_url( 'update.php' ) . '?action=install-plugin&plugin=' . $wqplugin['wporgslug'];
     1340                    $installlink = wp_nonce_url( $installlink, 'install-plugin_' . $wqplugin['wporgslug'] );
     1341                    echo '<input type="hidden" name="' . esc_attr( $pluginslug ) . '-install-link" value="' . esc_url( $installlink ) . '">';
     1342                } elseif ( !$wq_wordpress_org && is_array( $wqplugin['package'] ) ) {
     1343                    $installlink = admin_url( 'update.php' ) . '?action=wordquest_plugin_install&plugin=' . $pluginslug;
     1344                    $installlink = wp_nonce_url( $installlink, 'plugin-upload' );
     1345                    echo '<input type="hidden" name="' . esc_attr( $pluginslug ) . '-install-link" value="' . esc_url( $installlink ) . '">';
    12201346                }
    12211347
    12221348                // --- linked plugin title ---
    1223                 echo "<tr><td><a href='".$wqplugin['home']."' class='pluginlink' target=_blank>";
    1224                 echo $wqplugin['title']."</a></td><td width='20'></td>";
    1225                 // echo "<td>".$wqplugin['version']."</td><td width='20'></td>";
     1349                echo '<tr><td>';
     1350                    echo '<a href="' . esc_url( $wqplugin['home'] ) . '" class="pluginlink" target="_blank">';
     1351                    echo esc_html( $wqplugin['title'] ) . '</a>';
     1352                echo '</td><td width="20"></td>';
     1353                // echo '<td>' . esc_html( $wqplugin['version'] ) . '</td><td width="20"></td>';
    12261354
    12271355                // --- plugin action select ---
    1228                 echo "<td><select name='".$pluginslug."-action' id='".$pluginslug."-action' style='font-size:8pt;'>";
     1356                echo '<td><select name="' . esc_attr( $pluginslug ) . '-action" id="' . esc_attr( $pluginslug ) . '-action" style="font-size:8pt;">';
    12291357
    12301358                // 1.6.6: check if only wp.org plugins installable
    1231                 if ($wordpressorgonly && $wqplugin['wporgslug']) {
     1359                if ( $wq_wordpress_org && $wqplugin['wporgslug'] ) {
    12321360                    // --- has a wordpress.org slug so installable from repository ---
    1233                     echo "<option value='install' selected='selected'>".wqhelper_translate('Install Now')."</option>";
    1234                     echo "<option value='home'>".wqhelper_translate('Plugin Home')."</option>";
    1235                 } elseif (!$wordpressorgonly && is_array($wqplugin['package'])) {
     1361                    echo '<option value="install" selected="selected">' . esc_html( wqhelper_translate( 'Install Now' ) ) . '</option>';
     1362                } elseif ( !$wq_wordpress_org && is_array( $wqplugin['package'] ) ) {
    12361363                    // --- not all plugins are from wordpress.org, use the install package ---
    1237                     echo "<option value='install' selected='selected'>".wqhelper_translate('Install Now')."</option>";
    1238                     echo "<option value='home'>".wqhelper_translate('Plugin Home')."</option>";
     1364                    echo '<option value="install" selected="selected">' . esc_html( wqhelper_translate( 'Install Now' ) ) . '</option>';
    12391365                } else {
    12401366                    // oops, installation package currently unavailable (404)
    1241                     echo "<option value='home' selected='selected'>".wqhelper_translate('Plugin Home')."</option>";
    1242                 }
     1367                    echo '';
     1368                }
     1369                echo '<option value="home" selected="selected">' . esc_html( wqhelper_translate( 'Plugin Home' ) ) . '</option>';
    12431370                echo "</select></td><td width='20'></td>";
    12441371
    12451372                // --- plugin action button ---
    1246                 echo "<td><a href='javascript:void(0);' target=_blank id='".$pluginslug."-link' onclick='dopluginaction(\"".$pluginslug."\");'>";
    1247                 echo "<input class='button-secondary' type='button' value='".wqhelper_translate('Go')."'></a></td></tr>";
    1248             }
    1249             echo "</table></div></div>";
     1373                echo '<td>';
     1374                    echo '<a href="javascript:void(0);" target="_blank" id="' . esc_attr( $pluginslug ) . '-link" onclick="wq_plugin_action(\'' . esc_attr( $pluginslug ) . '\');">';
     1375                    echo '<input class="button-secondary" type="button" value="' . esc_attr( wqhelper_translate( 'Go' ) ) . '"></a>';
     1376                echo '</td></tr>';
     1377            }
     1378            echo '</table></div></div>';
    12501379        }
    12511380
    12521381        // Upcoming Plugin Panel
    12531382        // ---------------------
    1254         if (count($unreleasedplugins) > 0) {
    1255             ksort($unreleasedplugins);
    1256             if ($wqdebug) {echo "<!-- Unreleased Plugins: "; print_r($unreleasedplugins); echo " -->";}
    1257             $boxid = 'wordquestupcoming'; $boxtitle = wqhelper_translate('Upcoming WordQuest Plugins');
    1258             echo '<div id="'.$boxid.'" class="postbox">';
    1259             echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1260             echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;"><table>';
    1261             foreach ($unreleasedplugins as $releasetime => $wqplugin) {
     1383        if ( count( $unreleasedplugins ) > 0 ) {
     1384            ksort( $unreleasedplugins );
     1385            if ( $wqdebug ) {
     1386                // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     1387                echo "<!-- Unreleased Plugins: " . esc_html( print_r( $unreleasedplugins, true ) ) . " -->";
     1388            }
     1389
     1390            $boxid = 'wordquestupcoming';
     1391            $boxtitle = wqhelper_translate( 'Upcoming WordQuest Plugins' );
     1392            echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1393            echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1394            echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1395            echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside" style="margin-bottom:0;"><table>';
     1396            foreach ( $unreleasedplugins as $releasetime => $wqplugin ) {
    12621397                // $pluginslug = $wqplugin['slug'];
    1263                 echo "<tr><td><a href='".$wqplugin['home']."' class='pluginlink' target=_blank>";
    1264                 echo $wqplugin['title']."</a></td>";
    1265                 echo "<td><span style='font-size:9pt;'>";
    1266                 echo wqhelper_translate('Expected').': '.date('jS F Y', $releasetime);
    1267                 echo "</span></td></tr>";
    1268             }
    1269             echo "</table></div></div>";
     1398                echo '<tr><td>';
     1399                    echo '<a href="' . esc_url( $wqplugin['home'] ) . '" class="pluginlink" target="_blank">';
     1400                    echo esc_html( $wqplugin['title'] ) . '</a>';
     1401                echo '</td><td>';
     1402                    echo '<span style="font-size:9pt;">';
     1403                    echo esc_html( wqhelper_translate( 'Expected' ) ) . ': ' . esc_html( date( 'jS F Y', $releasetime ) );
     1404                    echo '</span>';
     1405                echo '</td></tr>';
     1406            }
     1407            echo '</table></div></div>';
    12701408        }
    12711409
    12721410        // BioShip Theme Panel
    12731411        // -------------------
    1274         $boxid = 'bioship'; $boxtitle = wqhelper_translate('BioShip Theme Framework');
    1275         echo '<div id="'.$boxid.'" class="postbox">';
    1276         echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1277         echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;"><table><tr><td><center>';
    1278 
    1279         if ($bioshipinstalled) {
     1412        $boxid = 'bioship';
     1413        $boxtitle = wqhelper_translate( 'BioShip Theme Framework' );
     1414        echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1415        echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1416        echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1417        echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside" style="margin-bottom:0;">';
     1418        echo '<table><tr><td><center>';
     1419
     1420        if ( $bioshipinstalled ) {
    12801421
    12811422            // --- check if BioShip Theme is active ---
    12821423            $theme = wp_get_theme();
    1283             if ($theme->stylesheet == 'bioship') {
    1284 
    1285                 echo wqhelper_translate('Sweet! You are using').' <b>';
    1286                 echo wqhelper_translate('BioShip Theme Framework').'</b>.<br>';
    1287                 echo wqhelper_translate('Great choice!').' ';
     1424            // 1.8.0: use public get_stylesheet method
     1425            if ( 'bioship' == $theme->get_stylesheet() ) {
     1426
     1427                echo esc_html( wqhelper_translate( 'Sweet! You are using' ) ) . ' <b>';
     1428                echo esc_html( wqhelper_translate( 'BioShip Theme Framework' ) ) . '</b>.<br>';
     1429                echo esc_html( wqhelper_translate( 'Great choice!' ) ) . ' ';
    12881430
    12891431                // 1.6.7: added BioShip Theme Options link here
    1290                 if (THEMETITAN) {$optionsurl = admin_url('admin.php').'?page=bioship-options';}
    1291                 elseif (THEMEOPT) {$optionsurl = admin_url('admin.php').'?page=options-framework';}
    1292                 else {$optionsurl = admin_url('customize.php');}
    1293                 echo '<a href="'.$optionsurl.'">'.wqhelper_translate('Theme Options').'</a>';
    1294 
    1295             } elseif (is_child_theme() && ($theme->template == 'bioship')) {
    1296 
    1297                 echo wqhelper_translate('Groovy. You are using').' <b>';
    1298                 echo wqhelper_translate('BioShip Framework').'</b>!<br>';
    1299                 echo wqhelper_translate('Your Child Theme is').' <b>'.$theme->Name.'</b><br><br>';
     1432                if ( THEMETITAN ) {
     1433                    $optionsurl = admin_url( 'admin.php' ) . '?page=bioship-options';
     1434                } elseif ( THEMEOPT ) {
     1435                    $optionsurl = admin_url( 'admin.php' ) . '?page=options-framework';
     1436                } else {
     1437                    $optionsurl = admin_url( 'customize.php' );
     1438                }
     1439                echo '<a href="' . esc_url( $optionsurl ) . '">' . esc_html( wqhelper_translate( 'Theme Options' ) ) . '</a>';
     1440
     1441            } elseif ( is_child_theme() && ( 'bioship' == $theme->get_template() ) ) {
     1442                // 1.8.0: use public get_template method
     1443
     1444                echo esc_html( wqhelper_translate( 'Groovy. You are using' ) ) . ' <b>';
     1445                echo esc_html( wqhelper_translate( 'BioShip Framework' ) ) . '</b>!<br>';
     1446                echo esc_html( wqhelper_translate( 'Your Child Theme is' ) ) . ' <b>' . esc_html( $theme->Name ) . '</b><br><br>';
    13001447
    13011448                // 1.6.7: add Child Theme Options link here
    1302                 if (THEMETITAN) {$optionsurl = admin_url('admin.php').'?page=bioship-options';}
    1303                 elseif (THEMEOPT) {$optionsurl = admin_url('admin.php').'?page=options-framework';}
    1304                 else {$optionsurl = admin_url('customize.php');}
    1305                 echo '<a href="'.$optionsurl.'">'.wqhelper_translate('Theme Options').'</a>';
     1449                if ( THEMETITAN ) {
     1450                    $optionsurl = admin_url( 'admin.php' ) . '?page=bioship-options';
     1451                } elseif ( THEMEOPT ) {
     1452                    $optionsurl = admin_url( 'admin.php' ) . '?page=options-framework';
     1453                } else {
     1454                    $optionsurl = admin_url( 'customize.php' );
     1455                }
     1456                echo '<a href="' . esc_url( $optionsurl ) . '">' . esc_html( wqhelper_translate( 'Theme Options' ) ) . '</a>';
    13061457
    13071458            } else {
    13081459
    1309                 echo wqhelper_translate('Looks like you have BioShip installed!').'<br>';
    1310                 echo '...'.wqhelper_translate('but it is not yet your active theme.').'<br><br>';
     1460                echo esc_html( wqhelper_translate( 'Looks like you have BioShip installed!' ) ) . '<br>';
     1461                echo '...' . esc_html( wqhelper_translate( 'but it is not yet your active theme.' ) ) . '<br><br>';
    13111462
    13121463                // --- BioShip Theme activation link ---
    1313                 $activatelink = admin_url('themes.php').'?action=activate&stylesheet=bioship';
    1314                 $activatelink = wp_nonce_url($activatelink, 'switch-theme_bioship');
    1315                 echo '<a href="'.$activatelink.'">'.wqhelper_translate('Click here to activate it now').'</a>.<br><br>';
    1316 
    1317                 // Check for Theme Test Drive
    1318                 echo "<div id='testdriveoptions'>";
    1319                 if (function_exists('themedrive_determine_theme')) {
     1464                $activatelink = admin_url( 'themes.php' ) . '?action=activate&stylesheet=bioship';
     1465                $activatelink = wp_nonce_url( $activatelink, 'switch-theme_bioship' );
     1466                echo '<a href="' . esc_url( $activatelink ) . '">' . esc_html( wqhelper_translate( 'Click here to activate it now' ) ) . '</a>.<br><br>';
     1467
     1468                // --- Check for Theme Test Drive ---
     1469                echo '<div id="testdriveoptions">';
     1470                if ( function_exists( 'themedrive_determine_theme' ) ) {
    13201471
    13211472                    // TODO: a better check here? this actually makes no sense
    1322                     if (class_exists('TitanFramework')) {
    1323                         $testdrivelink = admin_url('admin.php').'?page=bioship-options&theme=bioship';
    1324                     } elseif (function_exists('OptionsFramework_Init')) {
    1325                         $testdrivelink = admin_url('themes.php').'?page=options-framework&theme=bioship';
    1326                     } else {$testdrivelink = admin_url('customize.php').'?theme=bioship';}
    1327                     echo wqhelper_translate('or').', <a href="'.$testdrivelink.'">';
    1328                     echo wqhelper_translate('take it for a Theme Test Drive').'</a>.';
    1329 
    1330                 } elseif (in_array('theme-test-drive', $installedplugins)) {
     1473                    // ...as should be using an options page redirect link instead
     1474                    if ( class_exists( 'TitanFramework' ) ) {
     1475                        $testdrivelink = admin_url( 'admin.php' ) . '?page=bioship-options&theme=bioship';
     1476                    } elseif ( function_exists( 'OptionsFramework_Init' ) ) {
     1477                        $testdrivelink = admin_url( 'themes.php' ) . '?page=options-framework&theme=bioship';
     1478                    } else {
     1479                        $testdrivelink = admin_url( 'customize.php' ) . '?theme=bioship';
     1480                    }
     1481                    echo esc_html( wqhelper_translate( 'or' ) ) . ', <a href="' . esc_url( $testdrivelink ) . '">';
     1482                    echo esc_html( wqhelper_translate( 'take it for a Theme Test Drive' ) ) . '</a>.';
     1483
     1484                } elseif ( in_array( 'theme-test-drive', $installedplugins ) ) {
    13311485
    13321486                    // --- Theme Test Drive plugin activation link ---
    1333                     $activatelink = admin_url('plugins.php').'?action=activate&plugin='.urlencode('theme-test-drive/themedrive.php');
    1334                     $activatelink = wp_nonce_url($activatelink,'activate-plugin_theme-test-drive/themedrive.php');
    1335                     echo wqhelper_translate('or').', <a href="'.$activatelink.'">';
    1336                     echo wqhelper_translate('activate Theme Test Drive plugin').'</a><br>';
    1337                     echo wqhelper_translate('to test BioShip without affecting your current site.');
     1487                    $activatelink = admin_url( 'plugins.php' ) . '?action=activate&plugin=' . rawurlencode( 'theme-test-drive/themedrive.php' );
     1488                    $activatelink = wp_nonce_url( $activatelink, 'activate-plugin_theme-test-drive/themedrive.php' );
     1489                    echo esc_html( wqhelper_translate( 'or' ) ) . ', <a href="' . esc_url( $activatelink ) . '">';
     1490                    echo esc_html( wqhelper_translate( 'activate Theme Test Drive plugin' ) ) . '</a><br>';
     1491                    echo esc_html( wqhelper_translate( 'to test BioShip without affecting your current site.' ) );
    13381492
    13391493                } else {
    13401494
    13411495                    // --- Theme Test Drive plugin installation link ---
    1342                     $installlink = admin_url('update.php').'?action=install-plugin&plugin=theme-test-drive';
    1343                     $installlink = wp_nonce_url($installlink, 'install-plugin');
    1344                     echo wqhelper_translate('or').', <a href="'.$installlink.'">';
    1345                     echo wqhelper_translate('install Theme Test Drive plugin').'</a><br>';
    1346                     echo wqhelper_translate('to test BioShip without affecting your current site.');
    1347 
    1348                 }
    1349                 echo "</div>";
    1350             }
    1351 
    1352         } else {
    1353 
    1354             echo wqhelper_translate('Also from').' <b>WordQuest Alliance</b>, '.wqhelper_translate('check out the').'<br>';
    1355             echo "<a href='".$wqurls['bio']."' target=_blank><b>BioShip Theme Framework</b></a><br>";
    1356             echo wqhelper_translate('A highly flexible and responsive starter theme').'<br>'.wqhelper_translate('for users, designers and developers.');
    1357 
    1358         }
    1359 
    1360         if ( ($theme->template == 'bioship') || ($theme->stylesheet == 'bioship') ) {
    1361             // 1.7.3: addded missing function prefix
    1362             if (function_exists('bioship_admin_theme_updates_available')) {
    1363                 $themeupdates = bioship_admin_theme_updates_available();
    1364                 if ($themeupdates != '') {
    1365                     echo '<div class="update-nag" style="padding:3px 10px;margin:0 0 10px 0;text-align:center;">'.$themeupdates.'</div></font><br>';
    1366                 }
    1367             }
    1368 
    1369             // TODO: future link for rating BioShip on wordpress.org theme repository ?
    1370             // $ratelink = 'https://wordpress.org/support/theme/bioship/reviews/#new-post';
    1371             // echo '<br><a href="'.$ratelink.'" target=_blank>'.wqhelper_translate('Rate BioShip on WordPress.Org').'</a><br>';
     1496                    $installlink = admin_url( 'update.php' ) . '?action=install-plugin&plugin=theme-test-drive';
     1497                    $installlink = wp_nonce_url( $installlink, 'install-plugin' );
     1498                    echo esc_html( wqhelper_translate( 'or' ) ) . ', <a href="' . esc_url( $installlink ) . '">';
     1499                    echo esc_html( wqhelper_translate( 'install Theme Test Drive plugin' ) ) . '</a><br>';
     1500                    echo esc_html( wqhelper_translate( 'to test BioShip without affecting your current site.' ) );
     1501
     1502                }
     1503                echo '</div>';
     1504            }
     1505
     1506        } else {
     1507
     1508            // --- BioShip not installed, just provide a link ---
     1509            echo esc_html( wqhelper_translate( 'Also from' ) ) . ' <b>WordQuest Alliance</b>, ' . esc_html( wqhelper_translate( 'check out the' ) ) . '<br>';
     1510            echo '<a href="' . esc_url( $wqurls['bio'] ) . '" target="_blank"><b>BioShip Theme Framework</b></a><br>';
     1511            echo esc_html( wqhelper_translate( 'A highly flexible and responsive starter theme' ) ) . '<br>';
     1512            echo esc_html( wqhelper_translate( 'for users, designers and developers.' ) );
     1513
     1514        }
     1515
     1516        // 1.8.0: added missing bioship installed check
     1517        if ( $bioshipinstalled && isset( $theme ) && is_object( $theme ) ) {
     1518            if ( ( 'bioship' == $theme->get_template() ) || ( 'bioship' == $theme->get_stylesheet() ) ) {
     1519                // 1.8.0: use public get_template and get_stylesheet methods
     1520                // 1.7.3: addded missing function prefix
     1521                if ( function_exists( 'bioship_admin_theme_updates_available' ) ) {
     1522                    $themeupdates = bioship_admin_theme_updates_available();
     1523                    if ( '' != $themeupdates ) {
     1524                        echo '<div class="update-nag" style="padding:3px 10px;margin:0 0 10px 0;text-align:center;">';
     1525                        echo wp_kses_post( $themeupdates );
     1526                        echo '</div></font><br>';
     1527                    }
     1528                }
     1529
     1530                // TODO: future link for rating BioShip on wordpress.org theme repository ?
     1531                // $ratelink = 'https://wordpress.org/support/theme/bioship/reviews/#new-post';
     1532                // echo '<br><a href="' . esc_url( $ratelink ) . '" target="_blank">' . esc_html( wqhelper_translate( 'Rate BioShip on WordPress.Org' ) ) . '</a><br>';
     1533            }
    13721534        }
    13731535
     
    13761538        // (only displays if Bioship theme is active)
    13771539        // 1.7.3: added missing bioship function prefix
    1378         if (function_exists('bioship_muscle_bioship_dashboard_feed_widget')) {
     1540        if ( function_exists( 'bioship_muscle_bioship_dashboard_feed_widget' ) ) {
    13791541            // $boxid = 'bioshipfeed'; $boxtitle = wphelper_translate('BioShip News');
    13801542            // echo '<div id="'.$boxid.'" class="postbox">';
    1381             // echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
     1543            // echo '<h2 class="hndle" onclick="wq_togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    13821544            // echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;">';
    1383                 bioship_muscle_bioship_dashboard_feed_widget(false);
     1545                bioship_muscle_bioship_dashboard_feed_widget( false );
    13841546            // echo '</div></div>';
    13851547        }
     
    13881550        echo '</div></div>';
    13891551
    1390     // end column
     1552    // --- end column ---
    13911553    echo '</div>';
    13921554 };
     
    13961558// Version Specific Feed Column
    13971559// ----------------------------
    1398 $funcname = 'wqhelper_admin_feeds_column_'.$wqhv;
    1399 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    1400  $wqfunctions[$funcname] = function($args) {
     1560$funcname = 'wqhelper_admin_feeds_column_' . $wqhv;
     1561if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     1562 $wqfunctions[$funcname] = function( $args ) {
     1563
     1564    // 1.8.0: set missing global
     1565    global $wqurls;
    14011566
    14021567    // --- open feeds column ---
     
    14051570        // Latest / Next Release
    14061571        // ---------------------
    1407         global $wqreleases; $latestrelease = $nextrelease = '';
    1408         if (isset($wqreleases['latest'])) {$latestrelease = $wqreleases['latest'];}
    1409         if (isset($wqreleases['next'])) {$nextrelease = $wqreleases['next'];}
    1410 
    1411         if (isset($latestrelease) && is_array($latestrelease)) {
    1412             if ($latestrelease['installed'] == 'no') {
    1413                 $release = $latestrelease; $boxid = 'wordquestlatest'; $boxtitle = wqhelper_translate('Latest Release');
    1414             } else {$release = $nextrelease; $boxid = 'wordquestupcoming'; $boxtitle = wqhelper_translate('Upcoming Release');}
    1415         } elseif (isset($nextrelease) && is_array($nextrelease)) {
    1416             $release = $nextrelease; $boxid = 'wordquestupcoming'; $boxtitle = wqhelper_translate('Upcoming Release');
    1417         }
    1418 
    1419         if (isset($release) && is_array($release)) {
    1420 
    1421             echo '<div id="'.$boxid.'" class="postbox">';
    1422             echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1423             echo '<div class="inside" id="'.$boxid.'-inside"><table>';
    1424             echo "<table><tr><td align='center'><img src='".$release['icon']."' width='100' height='100'><br>";
    1425             echo "<a href='".$latestrelease['home']."' target=_blank><b>".$release['title']."</b></a></td><td width='10'></td>";
    1426             echo "<td><span style='font-size:9pt;'>".$release['description']."</span><br><br>";
    1427 
    1428             if (isset($release['package']) && is_array($release['package'])) {
    1429                 // 1.6.6: check for wordpress.org only installs
    1430                 global $wordpressorgonly; $installlink = false;
    1431                 if ($wordpressorgonly && $release['wporgslug']) {
    1432                     $installlink = self_admin_url('update.php')."?action=install-plugin&plugin=".$release['wporgslug'];
    1433                     $installlink = wp_nonce_url($installlink, 'install-plugin_'.$release['wporgslug']);
    1434                 } else {
    1435                     $installlink = admin_url('update.php')."?action=wordquest_plugin_install&plugin=".$release['slug'];
    1436                     $installlink = wp_nonce_url($installlink, 'plugin-upload');
    1437                 }
    1438 
    1439                 if ($installlink) {
    1440                     echo "<input type='hidden' name='".$release['slug']."-install-link' value='".$installlink."'>";
    1441                     echo "<center><a href='".$installlink."' class='button-primary'>".wqhelper_translate('Install Now')."</a></center>";
    1442                 } else {
    1443                     $pluginlink = $wqurls['wq'].'/plugins/'.$release['slug'];
    1444                     echo "<center><a href='".$pluginlink."' class='button-primary' target=_blank>&rarr; ".wqhelper_translate('Plugin Home')."</a></center>";
    1445                 }
    1446             } else {echo "<center>".wqhelper_translate('Expected').": ".date('jS F Y',strtotime($release['releasedate']));}
    1447             echo "</td></tr></table>";
     1572        global $wqreleases;
     1573        $latestrelease = $nextrelease = '';
     1574        if ( isset( $wqreleases['latest'] ) ) {
     1575            $latestrelease = $wqreleases['latest'];
     1576        }
     1577        if ( isset( $wqreleases['next'] ) ) {
     1578            $nextrelease = $wqreleases['next'];
     1579        }
     1580
     1581        if ( isset( $latestrelease ) && is_array( $latestrelease ) ) {
     1582            if ( 'no' == $latestrelease['installed'] ) {
     1583                $release = $latestrelease;
     1584                $boxid = 'wordquestlatest';
     1585                $boxtitle = wqhelper_translate( 'Latest Release' );
     1586            } else {
     1587                $release = $nextrelease;
     1588                $boxid = 'wordquestupcoming';
     1589                $boxtitle = wqhelper_translate( 'Upcoming Release' );
     1590            }
     1591        } elseif ( isset( $nextrelease ) && is_array( $nextrelease ) ) {
     1592            $release = $nextrelease;
     1593            $boxid = 'wordquestupcoming';
     1594            $boxtitle = wqhelper_translate( 'Upcoming Release' );
     1595        }
     1596
     1597        if ( isset( $release ) && is_array( $release ) ) {
     1598
     1599            echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1600            echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1601            echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1602            echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside"><table>';
     1603
     1604                echo '<table><tr><td align="center">';
     1605                    echo '<img src="' . esc_url( $release['icon'] ) . '" width="100" height="100" alt="' . esc_attr( wqhelper_translate( 'Latest Release Icon' ) ) . '"><br>';
     1606                    echo '<a href="' . esc_url( $latestrelease['home'] ) . '" target="_blank"><b>' . esc_html( $release['title'] ) . '</b></a>';
     1607                echo '</td><td width="10"></td><td>';
     1608                    echo '<span style="font-size:9pt;">' . esc_html( $release['description'] ) . '</span><br><br>';
     1609
     1610                    if ( isset( $release['package'] ) && is_array( $release['package'] ) ) {
     1611                        // 1.6.6: check for wordpress.org only installs
     1612                        global $wq_wordpress_org;
     1613                        $installlink = false;
     1614                        if ( $wq_wordpress_org && $release['wporgslug'] ) {
     1615                            $installlink = self_admin_url( 'update.php' ) . '?action=install-plugin&plugin=' . $release['wporgslug'];
     1616                            $installlink = wp_nonce_url( $installlink, 'install-plugin_' . $release['wporgslug'] );
     1617                        } else {
     1618                            $installlink = admin_url( 'update.php' ) . '?action=wordquest_plugin_install&plugin=' . $release['slug'];
     1619                            $installlink = wp_nonce_url( $installlink, 'plugin-upload' );
     1620                        }
     1621
     1622                        if ( $installlink ) {
     1623                            echo '<input type="hidden" name="' . esc_attr( $release['slug'] ) . '-install-link" value="' . esc_url( $installlink ) . '">';
     1624                            echo '<center><a href="' . esc_url( $installlink ) . '" class="button-primary">' . esc_html( wqhelper_translate( 'Install Now' ) ) . '</a></center>';
     1625                        } else {
     1626                            $pluginlink = $wqurls['wq'] . '/plugins/' . $release['slug'];
     1627                            echo '<center><a href="' . esc_url( $pluginlink ) . '" class="button-primary" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Plugin Home' ) ) . '</a></center>';
     1628                        }
     1629                    } else {
     1630                        echo '<center>' . esc_html( wqhelper_translate( 'Expected' ) ) . ': ' . esc_html( date( 'jS F Y', strtotime( $release['releasedate'] ) ) );
     1631                    }
     1632                echo '</td></tr></table>';
    14481633            echo '</table></div></div>';
    14491634        }
     
    14511636        // WordQuest Feed
    14521637        // --------------
    1453         $boxid = 'wordquestfeed'; $boxtitle = wqhelper_translate('WordQuest News');
    1454         if (function_exists('wqhelper_dashboard_feed_widget')) {
    1455             echo '<div id="'.$boxid.'" class="postbox">';
    1456             echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1457             echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;">';
     1638        $boxid = 'wordquestfeed';
     1639        $boxtitle = wqhelper_translate( 'WordQuest News' );
     1640        if ( function_exists( 'wqhelper_dashboard_feed_widget' ) ) {
     1641            echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1642            echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1643            echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1644            echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside" style="margin-bottom:0;">';
    14581645                wqhelper_dashboard_feed_widget();
    14591646            echo '</div></div>';
     
    14621649        // Editors Picks
    14631650        // -------------
    1464         $boxid = 'recommendations'; $boxtitle = wqhelper_translate('Editor Picks');
     1651        $boxid = 'recommendations';
     1652        $boxtitle = wqhelper_translate( 'Editor Picks' );
    14651653        // TODO: Recommended Plugins via Plugin Review?
    14661654        // echo '<div id="'.$boxid.'" class="postbox">';
    1467         // echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
     1655        // echo '<h2 class="hndle" onclick="wq_togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    14681656        // echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;"><table>';
    14691657        //  echo "Recommended Plugins...";
     
    14731661        // PluginReview Feed
    14741662        // -----------------
    1475         $boxid = 'pluginreviewfeed'; $boxtitle = wqhelper_translate('Plugin Reviews');
    1476         if (function_exists('wqhelper_pluginreview_feed_widget')) {
    1477             echo '<div id="'.$boxid.'" class="postbox">';
    1478             echo '<h2 class="hndle" onclick="togglemetabox(\''.$boxid.'\');"><span>'.$boxtitle.'</span></h2>';
    1479             echo '<div class="inside" id="'.$boxid.'-inside" style="margin-bottom:0;">';
     1663        $boxid = 'pluginreviewfeed';
     1664        $boxtitle = wqhelper_translate( 'Plugin Reviews' );
     1665        if ( function_exists( 'wqhelper_pluginreview_feed_widget' ) ) {
     1666            echo '<div id="' . esc_attr( $boxid ) . '" class="postbox">';
     1667            echo '<h2 class="hndle" onclick="wq_togglemetabox(\'' . esc_attr( $boxid ) . '\');">';
     1668            echo '<span>' . esc_html( $boxtitle ) . '</span></h2>';
     1669            echo '<div class="inside" id="' . esc_attr( $boxid ) . '-inside" style="margin-bottom:0;">';
    14801670                wqhelper_pluginreview_feed_widget();
    14811671            echo '</div></div>';
     
    14831673
    14841674    // --- close column ---
    1485     echo "</div>";
     1675    echo '</div>';
    14861676
    14871677    // --- enqueue feed javascript ---
    1488     if (!has_action('admin_footer', 'wqhelper_dashboard_feed_javascript')) {
    1489         add_action('admin_footer', 'wqhelper_dashboard_feed_javascript');
     1678    if ( !has_action( 'admin_footer', 'wqhelper_dashboard_feed_javascript' ) ) {
     1679        add_action( 'admin_footer', 'wqhelper_dashboard_feed_javascript' );
    14901680    }
    14911681
     
    14961686// Version Specific Admin Styles
    14971687// -----------------------------
    1498 $funcname = 'wqhelper_admin_styles_'.$wqhv;
    1499 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     1688$funcname = 'wqhelper_admin_styles_' . $wqhv;
     1689if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    15001690 $wqfunctions[$funcname] = function() {
    15011691
    15021692    // --- hide Wordquest plugin freemius submenu items if top level admin menu not open ---
    15031693    echo "<style>#toplevel_page_wordquest a.wp-first-item:after {content: ' Alliance';}
    1504         #toplevel_page_wordquest.wp-not-current-submenu .fs-submenu-item
    1505             {display: none; line-height: 0px; height: 0px;}
    1506     #toplevel_page_wordquest li.wp-first-item {margin-bottom: 5px; margin-left: -10px;}
    1507     span.fs-submenu-item.fs-sub {display: none;}
    1508         .current span.fs-submenu-item.fs-sub {display: block;}
    1509         #wpfooter {display:none !important;}
    1510     </style>";
     1694    #toplevel_page_wordquest.wp-not-current-submenu .fs-submenu-item {display: none; line-height: 0px; height: 0px;}
     1695    #toplevel_page_wordquest li.wp-first-item {margin-bottom: 5px; margin-left: -10px;}
     1696    span.fs-submenu-item.fs-sub {display: none;}
     1697    .current span.fs-submenu-item.fs-sub {display: block;}
     1698    #wpfooter {display:none !important;}</style>";
    15111699 };
    15121700}
     
    15151703// Version Specific Admin Script
    15161704// -----------------------------
    1517 $funcname = 'wqhelper_admin_scripts_'.$wqhv;
    1518 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     1705$funcname = 'wqhelper_admin_scripts_' . $wqhv;
     1706if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    15191707 $wqfunctions[$funcname] = function() {
    15201708
    1521     // --- wordquest admin submenu icon and styling fixes ---
     1709    // --- wordquest admin submenu icon and styling fixes ---
     1710    // 1.7.9: change margin-left to padding-left on link
     1711    // 1.7.9: added margin left and top to icon
     1712    // 1.8.0: fix insertBefore(this) to insertBefore(jQuery(this))
    15221713    echo "<script>function wordquestsubmenufix(slug,iconurl,current) {
    15231714        jQuery('li a').each(function() {
     
    15251716            if (position > -1) {
    15261717                linkref = this.href.substr(position);
    1527                 jQuery(this).css('margin-left','10px');
     1718                jQuery(this).css('padding-left','10px');
    15281719                if (linkref == 'admin.php?page='+slug) {
    1529                     jQuery('<img src=\"'+iconurl+'\" style=\"float:left;\">').insertBefore(this);
     1720                    jQuery('<img src=\"'+iconurl+'\" style=\"float:left;margin-left:3px;margin-top:3px;\">').insertBefore(jQuery(this));
    15301721                    jQuery(this).css('margin-top','-3px');
    15311722                } else {if (current == 1) {
     
    15461737// --------------------------
    15471738// 1.6.5: hook to update.php update-custom_{ACTION} where ACTION = 'wordquest_plugin_install'
    1548 add_action('update-custom_wordquest_plugin_install', 'wqhelper_install_plugin');
    1549 
    1550 $funcname = 'wqhelper_install_plugin_'.$wqhv;
    1551 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     1739add_action( 'update-custom_wordquest_plugin_install', 'wqhelper_install_plugin' );
     1740
     1741$funcname = 'wqhelper_install_plugin_' . $wqhv;
     1742if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    15521743 $wqfunctions[$funcname] = function() {
    15531744
     
    15551746
    15561747    // --- check permissions and nonce ---
    1557     if (!current_user_can('upload_plugins')) {
    1558         wp_die( wqhelper_translate('Sorry, you are not allowed to install plugins on this site.') );
    1559     }
    1560     check_admin_referer('plugin-upload');
     1748    if ( !current_user_can( 'upload_plugins' ) ) {
     1749        wp_die( esc_html( wqhelper_translate( 'Sorry, you are not allowed to install plugins on this site.' ) ) );
     1750    }
     1751    check_admin_referer( 'plugin-upload' );
    15611752
    15621753    // --- get the package info from download server ---
    1563     if (!isset($_REQUEST['plugin'])) {wp_die( wqhelper_translate('Error: No Plugin specified.') );}
    1564     $pluginslug = $_REQUEST['plugin'];
     1754    if ( !isset( $_REQUEST['plugin'] ) ) {
     1755        wp_die( esc_html( wqhelper_translate( 'Error: No Plugin specified.' ) ) );
     1756    }
    15651757    // 1.5.9: sanitize plugin slug
    1566     $pluginslug = sanitize_title($pluginslug);
    1567     if ($pluginslug == '') {wp_dir( wqhelper_translate('Error: Invalid Plugin slug specified.') );}
     1758    // 1.8.1: combined sanitize_title on same line
     1759    $pluginslug = sanitize_title( $_REQUEST['plugin'] );
     1760    if ( '' == $pluginslug ) {
     1761        wp_die( esc_html( wqhelper_translate( 'Error: Invalid Plugin slug specified.' ) ) );
     1762    }
    15681763
    15691764    // --- get the plugin package data ---
    1570     $url = $wqurls['wq'].'/downloads/?action=get_metadata&slug='.$pluginslug;
    1571     $response = wp_remote_get($url, array('timeout' => 30));
    1572     if (!is_wp_error($response)) {
    1573         if ($response['response']['code'] == '404') {
     1765    $url = $wqurls['wq'] . '/downloads/?action=get_metadata&slug=' . $pluginslug;
     1766    $response = wp_remote_get( $url, array( 'timeout' => 30 ) );
     1767    if ( !is_wp_error( $response ) ) {
     1768        if ( '404' == $response['response']['code'] ) {
    15741769            // --- on failure try to get package info from stored transient data ---
    1575             $plugininfo = get_transient('wordquest_plugin_info');
    1576             if (is_array($pluginfo)) {
    1577                 foreach ($plugininfo as $plugin) {
    1578                     if ($plugin['slug'] == $pluginslug) {$pluginpackage = $plugin['package'];}
    1579                 }
    1580             }
    1581         } else {$pluginpackage = json_decode($response['body'], true);}
    1582     }
    1583 
    1584     if (!isset($pluginpackage)) {
    1585         if (is_ssl()) {$tryagainurl = 'https://';} else {$tryagainurl = 'http://';}
    1586         $tryagainurl .= $_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];
    1587         $message = wqhelper_translate('Failed to retrieve download package information.');
    1588         $message .= ' <a href="'.$tryagainurl.'">'.wqhelper_translate('Click here to try again.').'</a>';
    1589         wp_die($message);
    1590     }
    1591 
    1592     // 1.6.5: pass the package download URL to Wordpress to do the rest
     1770            $plugininfo = get_transient( 'wordquest_plugin_info' );
     1771            // 1.8.0: fix to variable typo pluginfo
     1772            if ( is_array( $plugininfo ) ) {
     1773                foreach ( $plugininfo as $plugin ) {
     1774                    if ( $plugin['slug'] == $pluginslug ) {
     1775                        $pluginpackage = $plugin['package'];
     1776                    }
     1777                }
     1778            }
     1779        } else {
     1780            $pluginpackage = json_decode( $response['body'], true );
     1781        }
     1782    }
     1783
     1784    if ( !isset( $pluginpackage ) ) {
     1785        $protocol = is_ssl() ? 'https://' : 'http://';
     1786        // 1.8.2: add sanitize_text_field to $_SERVER['HTTP_HOST']
     1787        $tryagainurl = $protocol . sanitize_text_field( $_SERVER['HTTP_HOST'] ) . $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];
     1788        $message = esc_html( wqhelper_translate( 'Failed to retrieve download package information.' ) );
     1789        $message .= ' <a href="' . esc_url( $tryagainurl ) . '">';
     1790        $message .= esc_html( wqhelper_translate( 'Click here to try again.' ) ) . '</a>';
     1791        // 1.8.1: use wp_kses_post on message
     1792        wp_die( wp_kses_post( $message ) );
     1793    }
     1794
     1795    // 1.6.5: pass the package download URL to WordPress to do the rest
    15931796
    15941797    // --- set the Plugin_Installer_Skin arguments ---
    15951798    $url = $pluginpackage['download_url'];
    1596     $title = sprintf( wqhelper_translate('Installing Plugin from URL: %s'), esc_html($url) );
     1799    $title = sprintf( wqhelper_translate( 'Installing Plugin from URL: %s' ), esc_html( $url ) );
    15971800    $nonce = 'plugin-upload';
    15981801    $type = 'web';
    1599     $args = compact('type', 'title', 'nonce', 'url');
     1802    // 1.8.0: disuse compact function
     1803    // $args = compact( 'type', 'title', 'nonce', 'url' );
     1804    $args = array(
     1805        'type' => 'web',
     1806        'title' => $title,
     1807        'nonce' => 'plugin-upload',
     1808        'url' => $url,
     1809    );
    16001810
    16011811    // --- custom Plugin_Upgrader (via /wp-admin/upgrade.php) ---
    1602     $title = wqhelper_translage('Upload Plugin');
    1603     $parent_file = 'plugins.php'; $submenu_file = 'plugin-install.php';
    1604     require_once(ABSPATH . 'wp-admin/admin-header.php');
     1812    // 1.8.0: fix to function typo wqhelper_translate
     1813    $title = wqhelper_translate( 'Upload Plugin' );
     1814    $parent_file = 'plugins.php';
     1815    $submenu_file = 'plugin-install.php';
     1816    require_once ABSPATH . 'wp-admin/admin-header.php';
    16051817    $upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( $args ) );
    1606     $result = $upgrader->install($url);
    1607     include(ABSPATH . 'wp-admin/admin-footer.php');
     1818    $result = $upgrader->install( $url );
     1819    include ABSPATH . 'wp-admin/admin-footer.php';
    16081820
    16091821 };
     
    16181830// Main Floatbox Function
    16191831// ----------------------
    1620 $funcname = 'wqhelper_sidebar_floatbox_'.$wqhv;
    1621 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    1622  $wqfunctions[$funcname] = function($args) {
     1832$funcname = 'wqhelper_sidebar_floatbox_' . $wqhv;
     1833if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     1834 $wqfunctions[$funcname] = function( $args ) {
    16231835
    16241836    global $wqdebug, $wqurls;
    1625     if ($wqdebug) {echo "<!-- Sidebar Args: "; print_r($args); echo " -->";}
    1626 
    1627     if (count($args) == 7) {
     1837    if ( $wqdebug ) {
     1838        // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     1839        echo "<!-- Sidebar Args: " . esc_html( print_r( $args, true ) ) . " -->";
     1840    }
     1841
     1842    if ( count( $args ) == 7 ) {
     1843
    16281844        // --- the old way, sending all args individually ---
    1629         $prefix = $args[0]; $pluginslug = $args[1]; $freepremium = $args[2];
    1630         $wporgslug = $args[3]; $savebutton = $args[4];
    1631         $plugintitle = $args[5]; $pluginversion = $args[6];
     1845        $prefix = $args[0];
     1846        $pluginslug = $slug = $args[1];
     1847        $freepremium = $args[2];
     1848        $wporgslug = $args[3];
     1849        $savebutton = $args[4];
     1850        $plugintitle = $args[5];
     1851        $pluginversion = $args[6];
     1852
    16321853    } else {
     1854
    16331855        // --- the new way, just sending two args ---
    16341856        $pluginslug = $slug = $args[0];
     
    16411863        $prefix = $wordquestplugins[$slug]['settings'];
    16421864        // 1.7.7: added isset check for plan key for back-compat
    1643         if (isset($wordquestplugins[$slug]['plan'])) {
     1865        if ( isset( $wordquestplugins[$slug]['plan'] ) ) {
    16441866            $freepremium = $wordquestplugins[$slug]['plan'];
    16451867        } else {
     
    16481870        $wporg = $wordquestplugins[$slug]['wporg'];
    16491871
    1650         if (isset($wordquestplugins[$slug]['wporgslug'])) {
     1872        if ( isset( $wordquestplugins[$slug]['wporgslug'] ) ) {
    16511873            $wporgslug = $wordquestplugins[$slug]['wporgslug'];
    1652         } else {$wporgslug = '';}
    1653 
    1654         // --- get donate link ---
    1655         // 1.7.4: get donate link and set author
    1656         // 1.7.6: fix to check if donate key is defined
     1874        } else {
     1875            $wporgslug = '';
     1876        }
     1877
     1878        // --- get donate link ---
     1879        // 1.7.4: get donate link and set author
     1880        // 1.7.6: fix to check if donate key is defined
    16571881        $author = 'wordquest';
    1658         if (isset($wordquestplugins[$slug]['donate'])) {
    1659             $donatelink = $wordquestplugins[$slug]['donate'];
    1660             echo "<!-- Donate Link: ".$donatelink." -->";
    1661             if (strstr($donatelink, 'wpmedic')) {$author = 'wpmedic';}
    1662         }
    1663 
    1664         if ($wqdebug) {echo "<!-- Sidebar Plugin Info: "; print_r($wordquestplugins[$slug]); echo "-->";}
     1882        if ( isset( $wordquestplugins[$slug]['donate'] ) ) {
     1883                $donatelink = $wordquestplugins[$slug]['donate'];
     1884            if ( strstr( $donatelink, 'wpmedic' ) ) {
     1885                $author = 'wpmedic';
     1886            }
     1887        }
     1888
     1889        if ( $wqdebug ) {
     1890            echo "<!-- Sidebar Plugin Info: " . esc_html( $wordquestplugins[$slug] ) . "-->";
     1891        }
     1892    }
     1893
     1894    // --- set which boxes to show ---
     1895    $boxes = array( 'donate', 'subscribe', 'recommend' ); // 'report', 'testimonials'
     1896    $boxes = apply_filters( $prefix . '_display_sidebar_boxes', $boxes );
     1897    if ( $wqdebug ) {
     1898        // phpcs:ignore WordPress.PHP.DevelopmentFunctions
     1899        echo "<!-- Sidebar Boxes: " . esc_html( print_r( $boxes, true ) ) . " -->";
    16651900    }
    16661901
    16671902    // 1.5.0: get/convert to single array of plugin sidebar options
    16681903    // 1.6.0: fix to sidebar options variable
    1669     $sidebaroptions = get_option($prefix.'_sidebar_options');
    1670     if ( ($sidebaroptions == '') || !is_array($sidebaroptions) ) {
    1671         $sidebaroptions['installdate'] = date('Y-m-d');
    1672         $sidebaroptions['adsboxoff'] = get_option($prefix.'_ads_box_off');
    1673         $sidebaroptions['donationboxoff'] = get_option($prefix.'_donation_box_off');
    1674         $sidebaroptions['reportboxoff'] = get_option($prefix.'_report_box_off');
    1675         delete_option($prefix.'_ads_box_off'); delete_option($prefix.'_donation_box_off'); delete_option($prefix.'_report_box_off');
    1676         add_option($prefix.'_sidebar_options', $sidebaroptions);
     1904    $sidebaroptions = get_option( $prefix . '_sidebar_options' );
     1905    if ( !$sidebaroptions || ( '' == $sidebaroptions ) || !is_array( $sidebaroptions ) ) {
     1906        $sidebaroptions = array(
     1907            'installdate'       => date( 'Y-m-d' ),
     1908            'adsboxoff'     => get_option( $prefix . '_ads_box_off' ),
     1909            'donationboxoff'    => get_option( $prefix . '_donation_box_off' ),
     1910            'reportboxoff'      => get_option( $prefix . '_report_box_off' ),
     1911            'subscribeboxoff'   => '',
     1912            // 'testimonialboxoff'  => '',
     1913        );
     1914        delete_option( $prefix . '_ads_box_off' );
     1915        delete_option( $prefix . '_donation_box_off' );
     1916        delete_option( $prefix . '_report_box_off' );
     1917        update_option( $prefix . '_sidebar_options', $sidebaroptions );
    16771918    }
    16781919    // 1.6.9: fix to possible undefined keys
    1679     if (!isset($sidebaroptions['installdate'])) {$sidebaroptions['installdate'] = date('Y-m-d');}
    1680     if (!isset($sidebaroptions['adsboxoff'])) {$sidebaroptions['adsboxoff'] = '';}
    1681     if (!isset($sidebaroptions['donationboxoff'])) {$sidebaroptions['donationboxoff'] = '';}
    1682     if (!isset($sidebaroptions['reportboxoff'])) {$sidebaroptions['reportboxoff'] = '';}
     1920    $changed = false;
     1921    if ( !isset( $sidebaroptions['installdate'] ) ) {
     1922        $sidebaroptions['installdate'] = date( 'Y-m-d' );
     1923        $changed = true;
     1924    }
     1925    if ( !isset( $sidebaroptions['donationboxoff'] ) ) {
     1926        $sidebaroptions['donationboxoff'] = '';
     1927        $changed = true;
     1928    }
     1929    if ( !isset( $sidebaroptions['subscribeboxoff'] ) ) {
     1930        $sidebaroptions['subscribeboxoff'] = '';
     1931        $changed = true;
     1932    }
     1933    // if ( !isset( $sidebaroptions['testimonialboxoff' ) ) {
     1934    //  $sidebaroptions['testimonialboxoff'] = '';
     1935    //  $changed = true;
     1936    // }
     1937    if ( !isset( $sidebaroptions['reportboxoff'] ) ) {
     1938        $sidebaroptions['reportboxoff'] = '';
     1939        $changed = true;
     1940    }
     1941    if ( !isset( $sidebaroptions['adsboxoff'] ) ) {
     1942        $sidebaroptions['adsboxoff'] = '';
     1943        $changed = true;
     1944    }
     1945    update_option( $prefix, '_sidebar_options', $sidebaroptions );
    16831946
    16841947    // --- sidebar scripts ---
    1685     echo "<script language='javascript' type='text/javascript'>
    1686     function hidesidebarsaved() {document.getElementById('sidebarsaved').style.display = 'none';}
    1687     function doshowhidediv(divname) {
     1948    // 1.7.8: fix to sticky kit recalc function check (sticky_in_parent)
     1949    echo "<script>
     1950    function wq_hide_sidebar_saved() {document.getElementById('sidebarsaved').style.display = 'none';}
     1951    function wq_showhide_div(divname) {
    16881952        if (document.getElementById(divname).style.display == 'none') {document.getElementById(divname).style.display = '';}
    16891953        else {document.getElementById(divname).style.display = 'none';}
    1690         if (typeof sticky_in_parent === 'function') {jQuery(document.body).trigger('sticky_kit:recalc');}
     1954        if (typeof stick_in_parent === 'function') {jQuery(document.body).trigger('sticky_kit:recalc');}
    16911955    }</script>";
    16921956
     
    17001964    // --- open sidebar div --
    17011965    echo '<div id="floatdiv" class="floatbox">';
    1702     if ($wqdebug) {echo '<!-- WQ Helper Loaded From: '.dirname(__FILE__).' -->';}
     1966    if ( $wqdebug ) {
     1967        echo '<!-- WQ Helper Loaded From: ' . esc_html( dirname( __FILE__ ) ) . ' -->';
     1968    }
    17031969
    17041970    // --- call (optional) Plugin Sidebar Header ---
    1705     $funcname = $prefix.'_sidebar_plugin_header';
    1706     if (function_exists($funcname)) {call_user_func($funcname);}
     1971    $funcname = $prefix . '_sidebar_plugin_header';
     1972    if ( function_exists( $funcname ) ) {
     1973        call_user_func( $funcname );
     1974    }
    17071975
    17081976    // Save Settings Button
    17091977    // --------------------
    1710     if ($savebutton != 'replace') {
     1978    if ( 'replace' != $savebutton ) {
    17111979
    17121980        echo '<div id="savechanges"><div class="stuffbox" style="width:250px;background-color:#ffffff;">';
    1713         echo '<h3>'.wqhelper_translate('Update Settings').'</h3><div class="inside"><center>';
    1714 
    1715         if ($savebutton == 'yes') {
    1716             $buttonoutput = "<script>function sidebarsavepluginsettings() {jQuery('#plugin-settings-save').trigger('click');}</script>";
    1717             $buttonoutput .= "<table><tr>";
    1718             $buttonoutput .= "<td align='center'><input id='sidebarsavebutton' onclick='sidebarsavepluginsettings();' type='button' class='button-primary' value='Save Settings'></td>";
    1719             $buttonoutput .= "<td width='30'></td>";
    1720             $buttonoutput .= "<td><div style='line-height:1em;'><font style='font-size:8pt;'><a href='javascript:void(0);' style='text-decoration:none;' onclick='doshowhidediv(\"sidebarsettings\");hidesidebarsaved();'>".wqhelper_translate('Sidebar')."<br>";
    1721             $buttonoutput .= wqhelper_translate('Options')."</a></font></div></td>";
    1722             $buttonoutput .= "</tr></table>";
    1723             $buttonoutput = apply_filters('wordquest_sidebar_save_button', $buttonoutput);
    1724             echo $buttonoutput;
    1725         }   elseif ($savebutton == 'no') {echo "";}
    1726         else {echo "<div style='line-height:1em;text-align:center;'><font style='font-size:8pt;'><a href='javascript:void(0);' style='text-decoration:none;' onclick='doshowhidediv(\"sidebarsettings\");hidesidebarsaved();'>".wqhelper_translate('Sidebar Options')."</a></font></div>";}
     1981        echo '<h3>' . esc_html( wqhelper_translate( 'Update Settings' ) ) . '</h3>';
     1982        echo '<div class="inside"><center>';
     1983
     1984        $savebuttontrigger = $sidebaroptionsbutton = false;
     1985        if ( 'yes' == $savebutton ) {
     1986
     1987            $savebuttontrigger = $sidebaroptionsbutton = true;
     1988
     1989            // --- set button output ---
     1990            // 1.8.1: remove onclick attributes from buttons to script
     1991            $button = '<table><tr>';
     1992                $button .= '<td align="center">';
     1993                    $button .= '<input id="sidebarsavebutton" type="button" class="button-primary" value="Save Settings">';
     1994                $button .= '</td><td width="30"></td><td>';
     1995                    $button .= '<div style="line-height:1em;"><font style="font-size:8pt;"><a href="javascript:void(0);" id="sidebaroptionsbutton" style="text-decoration:none;">' . esc_html( wqhelper_translate( 'Sidebar' ) ) . '<br>';
     1996                    $button .= esc_html( wqhelper_translate( 'Options' ) ) . '</a></font></div>';
     1997                $button .= '</td>';
     1998            $button .= '</tr></table>';
     1999            $button = apply_filters( 'wordquest_sidebar_save_button', $button, $pluginslug );
     2000            // 1.8.1: use wp_kses_post on button
     2001            echo wp_kses_post( $button );
     2002
     2003        } elseif ( 'no' == $savebutton ) {
     2004
     2005            echo '';
     2006
     2007        } else {
     2008
     2009            // --- show sidebar save options only ---
     2010            $sidebaroptionsbutton = true;
     2011            echo '<div style="line-height:1em;text-align:center;">';
     2012                echo '<font style="font-size:8pt;"><a href="javascript:void(0);" id="sidebaroptionsbutton" style="text-decoration:none;">' . esc_html( wqhelper_translate( 'Sidebar Options' ) ) . '</a></font>';
     2013            echo '</div>';
     2014
     2015        }
     2016
     2017        if ( $savebuttontrigger || $sidebaroptionsbutton ) {
     2018            // 1.8.1: output script function directly
     2019            // echo "<script>function wq_sidebar_save_settings() {jQuery('#plugin-settings-save').trigger('click');}</script>";
     2020            echo "<script>";
     2021                if ( $savebuttontrigger ) {
     2022                    echo "jQuery('#sidebarsavebutton').on('click', function() {" . PHP_EOL;
     2023                    echo "  jQuery('#plugin-settings-save').trigger('click');" . PHP_EOL;
     2024                    echo "});" . PHP_EOL;
     2025                }
     2026                if ( $sidebaroptionsbutton ) {
     2027                    echo "jQuery('#sidebaroptionsbutton').on('click', function() {" . PHP_EOL;
     2028                    echo "wq_showhide_div('sidebarsettings'); wq_hide_sidebar_saved();" . PHP_EOL;
     2029                    echo "});" . PHP_EOL;
     2030                }
     2031            echo "</script>";
     2032        }
    17272033
    17282034        // --- sidebar settings box ---
    1729         echo "<div id='sidebarsettings' style='display:none;'><br>";
    1730 
     2035        echo '<div id="sidebarsettings" style="display:none;"><br>';
     2036
     2037            // 1.6.0: added version matching form field
     2038            // 1.6.5: added nonce field
    17312039            global $wordquesthelper;
    1732             echo "<form action='".admin_url('admin-ajax.php')."' target='savesidebar' method='post'>";
    1733             // 1.6.5: added nonce field
    1734             wp_nonce_field($prefix.'_sidebar');
    1735             echo "<input type='hidden' name='action' value='wqhelper_update_sidebar_boxes'>";
    1736             // 1.6.0: added version matching form field
    1737             echo "<input type='hidden' name='wqhv' value='".$wordquesthelper."'>";
    1738             echo "<input type='hidden' name='sidebarprefix' value='".$prefix."'>";
    1739             echo "<table><tr><td align='center'>";
    1740             echo "<b>".wqhelper_translate('I rock! I have made a donation.')."</b><br>(".wqhelper_translate('hides donation box').")</td><td width='10'></td>";
    1741             echo "<td align='center'><input type='checkbox' name='".$prefix."_donation_box_off' value='checked'";
    1742             if ($sidebaroptions['donationboxoff'] == 'checked') {echo " checked>";} else {echo ">";}
    1743             echo "</td></tr>";
    1744 
    1745             echo "<tr><td align='center'>";
    1746             echo "<b>".wqhelper_translate("I've got your report, you")."<br>".wqhelper_translate('can stop bugging me now.')." :-)</b><br>(".wqhelper_translate('hides report box').")</td><td width='10'></td>";
    1747             echo "<td align='center'><input type='checkbox' name='".$prefix."_report_box_off' value='checked'";
    1748             if ($sidebaroptions['reportboxoff'] == 'checked') {echo " checked>";} else {echo ">";}
    1749             echo "</td></tr>";
    1750 
    1751             echo "<tr><td align='center'>";
    1752             echo "<b>".wqhelper_translate('My site is so awesome it')."<br>"._("doesn't need any more quality")."<br>".wqhelper_translate('plugin recommendations').".</b><br>(".wqhelper_translate('hides sidebar ads.').")</td><td width='10'></td>";
    1753             echo "<td align='center'><input type='checkbox' name='".$prefix."_ads_box_off' value='checked'";
    1754             // 1.6.5: fix to undefined index warning
    1755             if ($sidebaroptions['adsboxoff'] == 'checked') {echo " checked>";} else {echo ">";}
    1756             echo "</td></tr></table><br>";
    1757 
    1758             echo "<center><input type='submit' class='button-secondary' value='".wqhelper_translate('Save Sidebar Options')."'></center></form><br>";
    1759             echo "<iframe src='javascript:void(0);' name='savesidebar' id='savesidebar' width='200' height='200' style='display:none;'></iframe>";
    1760 
    1761             echo "<div id='sidebarsaved' style='display:none;'>";
    1762             echo "<table style='background-color: lightYellow; border-style:solid; border-width:1px; border-color: #E6DB55; text-align:center;'>";
    1763             echo "<tr><td><div class='message' style='margin:0.25em;'><font style='font-weight:bold;'>";
    1764             echo wqhelper_translate('Sidebar Options Saved.')."</font></div></td></tr></table></div>";
    1765 
    1766         echo "</div></center>";
     2040            echo '<form action="' . esc_url( admin_url( 'admin-ajax.php' ) ) . '" target="savesidebar" method="post">';
     2041            wp_nonce_field( $prefix . '_sidebar' );
     2042            echo '<input type="hidden" name="action" value="wqhelper_update_sidebar_boxes">';
     2043            echo '<input type="hidden" name="wqhv" value="' . esc_attr( $wordquesthelper ) . '">';
     2044            echo '<input type="hidden" name="sidebarprefix" value="' . esc_attr( $prefix ) . '">';
     2045
     2046            // --- donation box option ---
     2047            if ( in_array( 'donate', $boxes ) ) {
     2048                echo '<table><tr><td align="center">';
     2049                    echo '<b>' . esc_html( wqhelper_translate( 'Hide Support Offer' ) ) . '</b></td>';
     2050                echo '<td width="10"></td><td align="center">';
     2051                    echo '<input type="checkbox" name="' . esc_attr( $prefix ) . '_donation_box_off" value="checked"';
     2052                    if ( 'checked' == $sidebaroptions['donationboxoff'] ) {
     2053                        echo ' checked="checked">';
     2054                    }
     2055                    echo '>';
     2056                echo '</td></tr>';
     2057            }
     2058
     2059            // --- report box option ---
     2060            if ( in_array( 'report', $boxes ) ) {
     2061                echo '<tr><td align="center">';
     2062                    echo '<b>' . esc_html( wqhelper_translate( 'Hide Report Offer' ) ) . '</b>';
     2063                echo '</td><td width="10"></td><td align="center">';
     2064                    echo '<input type="checkbox" name="' . esc_attr( $prefix ) . '_report_box_off" value="checked"';
     2065                    if ( 'checked' == $sidebaroptions['reportboxoff'] ) {
     2066                        echo ' checked="checked">';
     2067                    }
     2068                    echo '>';
     2069                echo '</td></tr>';
     2070            }
     2071
     2072            // --- subscribe box option ---
     2073            if ( in_array( 'subscribe', $boxes ) ) {
     2074                echo '<tr><td align="center">';
     2075                    echo '<b>' . esc_html( wqhelper_translate( 'Hide Subscribe Offer' ) ) . '</b>';
     2076                echo '</td><td width="10"></td><td align="center">';
     2077                    echo '<input type="checkbox" name="' . esc_attr( $prefix ) . '_subscribe_box_off" value="checked"';
     2078                    if ( 'checked' == $sidebaroptions['subscribeboxoff'] ) {
     2079                        echo ' checked="checked">';
     2080                    }
     2081                    echo '>';
     2082                echo '</td></tr>';
     2083            }
     2084
     2085            // --- ads box option ---
     2086            if ( in_array( 'recommend', $boxes ) ) {
     2087                echo '<tr><td align="center">';
     2088                    echo '<b>' . esc_html( wqhelper_translate( 'Hide Recommendations' ) ) . '</b>';
     2089                    echo '</td><td width="10"></td><td align="center">';
     2090                echo '<input type="checkbox" name="' . esc_attr( $prefix ) . '_ads_box_off" value="checked"';
     2091                    // 1.6.5: fix to undefined index warning
     2092                    if ( 'checked' == $sidebaroptions['adsboxoff'] ) {
     2093                        echo ' checked="checked">';
     2094                    }
     2095                    echo '>';
     2096                echo '</td></tr>';
     2097            }
     2098
     2099            echo '</table><br>';
     2100
     2101            // --- save sidebar options button ---
     2102            echo '<center><input type="submit" class="button-secondary" value="' . esc_attr( wqhelper_translate( 'Save Sidebar Options' ) ) . '"></center></form><br>';
     2103            echo '<iframe src="javascript:void(0);" name="savesidebar" id="savesidebar" width="200" height="200" style="display:none;"></iframe>';
     2104
     2105            // --- sidebar options saved message ---
     2106            echo '<div id="sidebarsaved" style="display:none;">';
     2107            echo '<table style="background-color: lightYellow; border-style:solid; border-width:1px; border-color: #E6DB55; text-align:center;">';
     2108            echo '<tr><td><div class="message" style="margin:0.25em;"><font style="font-weight:bold;">';
     2109            echo esc_html( wqhelper_translate( 'Sidebar Options Saved.' ) ) . '</font></div></td></tr></table></div>';
     2110
     2111        echo '</div></center>';
    17672112
    17682113        echo '</div></div></div>';
     
    17712116    // Donation Box
    17722117    // ------------
    1773     // TODO: Go Pro Link if has Pro plans ?
    1774     $args = array($prefix, $pluginslug);
    1775     if ($sidebaroptions['donationboxoff'] == 'checked') {$hide = " style='display:none;'>";} else {echo $hide = '';}
    1776     echo '<div id="donate"'.$hide.'>';
    1777 
    1778     if ($freepremium == 'free') {
    1779 
    1780         echo '<div class="stuffbox" style="width:250px;background-color:#ffffff;">';
    1781 
    1782         // --- box title ---
    1783         // 1.7.4: different title for patreon/paypal
    1784         // 1.7.6: fix to check if donate link defined
    1785         $boxtitle = wqhelper_translate('Support Subscription');
    1786         if (isset($donatelink) && strstr($donatelink, 'patreon')) {
    1787             $boxtitle = wqhelper_translate('Become a Supporter');
    1788         }
    1789         echo '<h3>'.$boxtitle.'</h3><div class="inside">';
    1790 
    1791         // --- maybe call special top ---
    1792         if (function_exists($prefix.'_donations_special_top')) {
    1793             $funcname = $prefix.'_donations_special_top';
    1794             call_user_func($funcname);
    1795         }
    1796 
    1797         // --- patreon support or paypal donations ---
    1798         // 1.7.4: different title for patreon/paypal
    1799         // 1.7.6: fix to check if donate link is defined
    1800         if (isset($donatelink) && strstr($donatelink, 'patreon')) {
    1801             wqhelper_sidebar_patreon_button($args);
    1802         } else {wqhelper_sidebar_paypal_donations($args);}
    1803 
    1804         // --- call donations special bottom ---
    1805         if (function_exists($prefix.'_donations_special_bottom')) {
    1806             $funcname = $prefix.'_donations_special_bottom';
    1807             call_user_func($funcname);
    1808         }
     2118    // 1.7.8: check if donation box is on
     2119    $args = array( $prefix, $pluginslug );
     2120    if ( in_array( 'donate', $boxes ) ) {
     2121
     2122        // --- open donate box ---
     2123        echo '<div id="donate-box" class="sidebar-box"';
     2124        if ( 'checked' == $sidebaroptions['donationboxoff'] ) {
     2125            echo ' style="display:none;">';
     2126        }
     2127        echo '>';
     2128
     2129        if ( 'free' == $freepremium ) {
     2130
     2131            echo '<div class="stuffbox" style="width:250px;background-color:#ffffff;">';
     2132
     2133            // --- box title ---
     2134            // 1.7.4: different title for patreon/paypal
     2135            // 1.7.6: fix to check if donate link defined
     2136            $boxtitle = wqhelper_translate( 'Support Subscription' );
     2137            if ( isset( $donatelink ) && strstr( $donatelink, 'patreon' ) ) {
     2138                $boxtitle = wqhelper_translate( 'Become a Supporter' );
     2139            }
     2140            echo '<h3>' . esc_html( $boxtitle ) . '</h3><div class="inside">';
     2141
     2142            // --- maybe call special top ---
     2143            if ( function_exists( $prefix . '_donations_special_top' ) ) {
     2144                $funcname = $prefix . '_donations_special_top';
     2145                call_user_func( $funcname );
     2146            }
     2147
     2148            // --- patreon support or paypal donations ---
     2149            // 1.7.4: different title for patreon/paypal
     2150            // 1.7.6: fix to check if donate link is defined
     2151            if ( isset( $donatelink ) && strstr( $donatelink, 'patreon' ) ) {
     2152                wqhelper_sidebar_patreon_button( $args );
     2153            } else {
     2154                wqhelper_sidebar_paypal_donations( $args );
     2155            }
     2156
     2157            // --- call donations special bottom ---
     2158            if ( function_exists( $prefix . '_donations_special_bottom' ) ) {
     2159                $funcname = $prefix . '_donations_special_bottom';
     2160                call_user_func( $funcname );
     2161            }
     2162
     2163            // 1.7.2: remove rate link from sidebar (now in plugin header)
     2164            // TODO: maybe re-add theme rating when in repository ?
     2165            // if ($wporgslug != '') {
     2166                // echo "<a href='".$wqurls['wp']."/plugins/'".$wporgslug."'/reviews/#new-post' target='_blank'>";
     2167                // echo "&#9733; ".wqhelper_translate('Rate this Plugin on Wordpress.Org')."</a></center>";
     2168            // } elseif ($pluginslug == 'bioship') {
     2169                // 1.5.0: add star rating for theme
     2170                // echo "<a href='".$wqurls['wp']."/support/theme/bioship/reviews/#new-post' target='_blank'>";
     2171                // echo "&#9733; ".wqhelper_translate('Rate this Theme on Wordpress.Org')."</a></center>";
     2172            // }
     2173
     2174            echo '</div></div>';
     2175
     2176        } elseif ( 'premium' == $freepremium ) {
     2177
     2178            // TODO: Go Pro Link if has Pro plans ?
     2179            echo '';
     2180
     2181        }
     2182
     2183        // --- close donate box
     2184        echo '</div>';
     2185    }
     2186
     2187    // Subscriber Form Box
     2188    // -------------------
     2189    // 1.7.8: added subscriber form box
     2190    if ( in_array( 'subscribe', $boxes ) ) {
     2191
     2192        // --- open donate box ---
     2193        echo '<div id="subscribe-box" class="sidebar-box"';
     2194        if ( 'checked' == $sidebaroptions['subscribeboxoff'] ) {
     2195            echo ' style="display:none;">';
     2196        }
     2197        echo '>';
     2198
     2199        // --- output subscribe box ---
     2200        $funcname = $prefix . '_sidebar_subscribe_box';
     2201        if ( function_exists( $funcname ) ) {
     2202            call_user_func( $funcname );
     2203        } else {
     2204
     2205            // --- populated form for current user ---
     2206            global $current_user;
     2207            $current_user = wp_get_current_user();
     2208            $useremail = $current_user->user_email;
     2209            if ( strstr( $useremail, '@localhost' ) ) {
     2210                $useremail = '';
     2211            }
     2212            $userid = $current_user->ID;
     2213            $userdata = get_userdata( $userid );
     2214            $username = $userdata->first_name;
     2215            $lastname = $userdata->last_name;
     2216            if ( '' != $lastname ) {
     2217                $username .= ' ' . $lastname;
     2218            }
     2219            $timestamp = time();
     2220
     2221            // --- set report image URL ---
     2222            if ( 'bioship' == $pluginslug ) {
     2223                $image = get_template_directory_uri() . '/images/bioship.png';
     2224                $image_alt = wqhelper_translate( 'BioShip Theme Icon' );
     2225                $action_url = $wqurls['bio'];
     2226                $leadin = wqhelper_translate( 'Subscribe to BioShip Updates' );
     2227                $headline = wqhelper_translate( 'and New Feature Releases' );
     2228                $button = wqhelper_translate( 'Subscribe' );
     2229            } elseif ( 'wordquest' == $author ) {
     2230                $image = plugins_url( 'images/wordquest.png', __FILE__ );
     2231                $image_alt = wqhelper_translate( 'WordQuest Icon' );
     2232                $action_url = $wqurls['wq'];
     2233                $leadin = wqhelper_translate( 'Join WordQuest for Updates' );
     2234                $headline = wqhelper_translate( 'and New Plugin Releases' );
     2235                $button = wqhelper_translate( 'Join' );
     2236            } elseif ( 'wpmedic' == $author ) {
     2237                $image = plugins_url( 'images/wpmedic.png', __FILE__ );
     2238                $image_alt = wqhelper_translate( 'WP Medic Icon' );
     2239                $action_url = $wqurls['wpm'];
     2240                $leadin = wqhelper_translate( 'Join WP Medic for Updates' );
     2241                $headline = wqhelper_translate( 'and New Tool Releases' );
     2242                $button = wqhelper_translate( 'Join' );
     2243            }
     2244
     2245            echo '<div class="stuffbox" style="width:250px;background-color:#ffffff;">';
     2246            echo '<h3>' . esc_html( wqhelper_translate( 'Stay Up to Date' ) ) . '</h3>';
     2247            echo '<div class="inside"><center>';
     2248                echo '<table cellpadding="0" cellspacing="0"><tr><td align="center">';
     2249                    echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( wqhelper_translate( $image_alt ) ) . '"><br>';
     2250                echo '</td><td width="7"></td><td align="center">';
     2251                    echo '<b><font style="color:#0000EE;font-size:11px;">' . esc_html( $leadin ) . '</font><br>';
     2252                    echo '<font style="color:#EE0000;font-size:13px;">' . esc_html( $headline ) . '</font></b><br>';
     2253                    echo '<form style="margin-top:7px;" action="' . esc_url( $action_url ) . '/" target="_blank" method="get">';
     2254                    echo '<input type="hidden" name="visitor-vortex" value="join">';
     2255                    echo '<input type="hidden" name="timestamp" value="' . esc_attr( $timestamp ) . '">';
     2256                    echo '<input type="hidden" name="source" value="' . esc_attr( $pluginslug ) . '-sidebar">';
     2257                    echo '<input placeholder="' . esc_attr( wqhelper_translate( 'Your Email' ) ) . '..." type="text" style="width:140px;font-size:12px;" name="subemail" value="' . esc_attr( $useremail ) . '"><br>';
     2258                    echo '<table><tr><td>';
     2259                        echo '<input placeholder="' . esc_attr( wqhelper_translate( 'Your Name' ) ) . '..." type="text" style="width:90px;font-size:12px;margin-top:5px;" name="subname" value="' . esc_attr( $username ) . '">';
     2260                    echo '</td><td>';
     2261                        echo '<input type="submit" class="button-primary" value="' . esc_attr( $button ) . '">';
     2262                    echo '</td></tr></table>';
     2263                echo '</td></tr></table></form>';
     2264            echo '</center></div></div>';
     2265        }
     2266
     2267        // --- close subscribe box ---
     2268        echo '</div>';
     2269    }
     2270
     2271    // Testimonials Form Box
     2272    // ---------------------
     2273    if ( in_array( 'testimonial', $boxes ) ) {
     2274
     2275        // --- open donate box ---
     2276        echo '<div id="testimonial"';
     2277        if ( 'checked' == $sidebaroptions['testimonialboxoff'] ) {
     2278            echo ' style="display:none;">';
     2279        }
     2280        echo '>';
    18092281
    18102282        // 1.7.2: remove testimonial box from sidebar
    1811         // wqhelper_sidebar_testimonial_box($args);
    1812 
    1813         // 1.7.2: remove rate link from sidebar (now in plugin header)
    1814         // TODO: re-add theme rating when in repository ?
    1815         // if ($wporgslug != '') {
    1816             // echo "<a href='".$wqurls['wp']."/plugins/'".$wporgslug."'/reviews/#new-post' target='_blank'>";
    1817             // echo "&#9733; ".wqhelper_translate('Rate this Plugin on Wordpress.Org')."</a></center>";
    1818         // } elseif ($pluginslug == 'bioship') {
    1819             // 1.5.0: add star rating for theme
    1820             // echo "<a href='".$wqurls['wp']."/support/theme/bioship/reviews/#new-post' target='_blank'>";
    1821             // echo "&#9733; ".wqhelper_translate('Rate this Theme on Wordpress.Org')."</a></center>";
    1822         // }
    1823 
    1824         echo '</div></div>';
    1825 
    1826     } elseif ($freepremium == 'premium') {
    1827 
    1828         // 1.7.3: temp: remove other testimonial box also
    1829         // echo '<div class="stuffbox" style="width:250px;background-color:#ffffff;">';
    1830         // echo '<h3>'.wqhelper_translate('Testimonials').'</h3><div class="inside">';
    1831         //  wqhelper_sidebar_testimonial_box($args);
    1832         // echo '</div></div>';
    1833 
    1834     }
    1835     echo '</div>';
    1836 
    1837     // Bonus Subscription Form
    1838     // -----------------------
     2283        // wqhelper_sidebar_testimonial_box( $args );
     2284
     2285        echo '</div>';
     2286    }
     2287
     2288    // Bonus Report Subscription Form
     2289    // ------------------------------
    18392290    // 1.7.2: allow for bonus offer box override
    1840     $funcname = $prefix.'_sidebar_bonus_offer';
    1841     if (function_exists($funcname)) {call_user_func($funcname);}
    1842     else {
    1843 
    1844         // --- populated form for current user ---
    1845         global $current_user; $current_user = wp_get_current_user();
    1846         $useremail = $current_user->user_email;
    1847         if (strstr($useremail, '@localhost')) {$useremail = '';}
    1848         $userid = $current_user->ID; $userdata = get_userdata($userid);
    1849         $username = $userdata->first_name; $lastname = $userdata->last_name;
    1850         if ($lastname != '') {$username .= ' '.$lastname;}
    1851 
    1852         // --- set report image URL ---
    1853         if ($pluginslug == 'bioship') {$reportimage = get_template_directory_uri().'/images/rv-report.jpg';}
    1854         else {$reportimage = plugins_url('images/rv-report.jpg', __FILE__);}
    1855 
    1856         echo '<div id="bonusoffer"';
    1857         if (get_option($prefix.'_report_box_off') == 'checked') {echo " style='display:none;'>";} else {echo ">";}
    1858         echo '<div class="stuffbox" style="width:250px;background-color:#ffffff;">';
    1859         echo '<h3>'.wqhelper_translate('Bonus Offer').'</h3><div class="inside">';
    1860         echo "<center><table cellpadding='0' cellspacing='0'><tr><td align='center'><img src='".$reportimage."' width='60' height='80'><br>";
    1861         echo "<font style='font-size:6pt;'><a href='".$wqurls['prn']."/return-visitors-report/' target=_blank>".wqhelper_translate('learn more')."...</a></font></td><td width='7'></td>";
    1862         echo "<td align='center'><b><font style='color:#ee0000;font-size:9pt;'>Maximize Sales Conversions:</font><br><font style='color:#0000ee;font-size:10pt;'>The Return Visitors Report</font></b><br>";
    1863         echo "<form style='margin-top:7px;' action='".$wqurls['prn']."/?visitorfunnel=join' target='_blank' method='post'>";
    1864         echo "<input type='hidden' name='source' value='".$pluginslug."-sidebar'>";
    1865         echo "<input placeholder='".wqhelper_translate('Your Email')."...' type='text' style='width:150px;font-size:9pt;' name='subemail' value='".$useremail."'><br>";
    1866         echo "<table><tr><td><input placeholder='".wqhelper_translate('Your Name')."...' type='text' style='width:90px;font-size:9pt;' name='subname' value='".$username."'></td>";
    1867         echo "<td><input type='submit' class='button-secondary' value='".wqhelper_translate('Get it!')."'></td></tr></table>";
    1868         echo "</td></tr></table></form></center>";
    1869         echo '</div></div></div>';
     2291    if ( in_array( 'report', $boxes ) ) {
     2292
     2293        echo '<div id="report-box"';
     2294        if ( 'checked' == $sidebaroptions['reportboxoff'] ) {
     2295            echo ' style="display:none;">';
     2296        }
     2297        echo '>';
     2298
     2299        $funcname = $prefix . '_sidebar_bonus_offer';
     2300        if ( function_exists( $funcname ) ) {
     2301            call_user_func( $funcname );
     2302        } else {
     2303
     2304            // --- populated form for current user ---
     2305            global $current_user;
     2306            $current_user = wp_get_current_user();
     2307            $useremail = $current_user->user_email;
     2308            if ( strstr( $useremail, '@localhost' ) ) {
     2309                $useremail = '';
     2310            }
     2311            $userid = $current_user->ID;
     2312            $userdata = get_userdata( $userid );
     2313            $username = $userdata->first_name;
     2314            $lastname = $userdata->last_name;
     2315            if ( '' != $lastname ) {
     2316                $username .= ' ' . $lastname;
     2317            }
     2318
     2319            // --- set report image URL ---
     2320            if ( 'bioship' == $pluginslug ) {
     2321                $reportimage = get_template_directory_uri() . '/images/rv-report.jpg';
     2322            } else {
     2323                $reportimage = plugins_url( 'images/rv-report.jpg', __FILE__ );
     2324            }
     2325
     2326            echo '<div class="stuffbox" style="width:250px;background-color:#ffffff;">';
     2327            echo '<h3>' . esc_html( wqhelper_translate( 'Bonus Offer' ) ) . '</h3>';
     2328            echo '<div class="inside"><center>';
     2329                echo '<table cellpadding="0" cellspacing="0"><tr><td align="center">';
     2330                    echo '<img src="' . esc_url( $reportimage ) . '" width="60" height="80" alt="' . esc_attr( wqhelper_translate( 'Report Image' ) ) . '"><br>';
     2331                    echo '<font style="font-size:6pt;"><a href="' . esc_url( $wqurls['prn'] ) . '/return-visitors-report/" target="_blank">' . esc_html( wqhelper_translate( 'learn more' ) ) . '...</a></font>';
     2332                echo '</td><td width="7"></td><td align="center">';
     2333                    echo '<b><font style="color:#ee0000;font-size:9pt;">Maximize Sales Conversions:</font><br>';
     2334                    echo '<font style="color:#0000ee;font-size:10pt;">The Return Visitors Report</font></b><br>';
     2335                    echo '<form style="margin-top:7px;" action="' . esc_url( $wqurls['prn'] ) . '" target="_blank" method="post">';
     2336                    echo '<input type="hidden" name="visitor-vortex" value="join">';
     2337                    echo '<input type="hidden" name="source" value="' . esc_attr( $pluginslug ) . '-sidebar">';
     2338                    echo '<input placeholder="' . esc_attr( wqhelper_translate( 'Your Email' ) ) . '..." type="text" style="width:150px;font-size:9pt;" name="subemail" value="' . esc_attr( $useremail ) . '"><br>';
     2339                    echo '<table><tr><td>';
     2340                        echo '<input placeholder="' . esc_attr( wqhelper_translate( 'Your Name' ) ) . '..." type="text" style="width:90px;font-size:9pt;" name="subname" value="' . esc_attr( $username ) . '">';
     2341                    echo '</td><td>';
     2342                        echo '<input type="submit" class="button-secondary" value="' . esc_attr( wqhelper_translate( 'Get it!' ) ) . '">';
     2343                    echo '</td></tr></table>';
     2344                echo '</td></tr></table></form>';
     2345            echo '</center></div></div>';
     2346        }
     2347        echo '</div>';
    18702348    }
    18712349
    18722350    // PluginReview.Net Plugin Recommendations
    18732351    // ---------------------------------------
    1874     if ($sidebaroptions['adsboxoff'] != 'checked') {
     2352    if ( in_array( 'recommend', $boxes ) ) {
     2353
     2354        echo '<div id="recommend-box"';
     2355        if ( 'checked' == $sidebaroptions['adsboxoff'] ) {
     2356            echo ' style="display:none;"';
     2357        }
     2358        echo '>';
     2359
    18752360        // 1.7.2: allow for recommendation box override
    1876         $funcname = $prefix.'_sidebar_plugin_recommendation';
    1877         if (function_exists($funcname)) {call_user_func($funcname);}
    1878         else {
    1879             echo '<div id="pluginads">';
    1880             echo '<div class="stuffbox" style="width:250px;">';
    1881             echo '<h3>'.wqhelper_translate('Recommended').'</h3><div class="inside">';
    1882             echo "<script language='javascript' src='".$wqurls['prn']."/recommends/?s=yes&a=majick&c=".$pluginslug."&t=sidebar'></script>";
    1883             echo '</div></div></div>';
    1884         }
     2361        $funcname = $prefix . '_sidebar_plugin_recommendation';
     2362        if ( function_exists( $funcname ) ) {
     2363            call_user_func( $funcname );
     2364        } else {
     2365            // 1.8.0: check for contents before box output
     2366            $feedad = wqhelper_get_feed_ad( $pluginslug );
     2367            if ( $feedad ) {
     2368                echo '<div class="stuffbox" style="width:250px;">';
     2369                echo '<h3>' . esc_html( wqhelper_translate( 'Recommended' ) ) . '</h3>';
     2370                echo '<div class="inside">';
     2371                if ( 'checked' != $sidebaroptions['adsboxoff'] ) {
     2372                    // 1.8.0: replaced script with RSS feed ad
     2373                    // echo '<script src="' . esc_url( $wqurls['prn'] ) . '/recommends/?s=yes&a=majick&c=' . esc_attr( $pluginslug ) . '&t=sidebar"></script>';
     2374                    // 1.8.1: use wp_kses_post on feed ad
     2375                    echo wp_kses_post( $feedad );
     2376                }
     2377                // 1.8.2: fix to move close divs back inside condition
     2378                echo '</div></div>';
     2379            }
     2380        }
     2381
     2382        echo '</div>';
    18852383    }
    18862384
    18872385    // Call Plugin Footer Function
    18882386    // ---------------------------
    1889     $funcname = $prefix.'_sidebar_plugin_footer';
    1890     if (function_exists($funcname)) {call_user_func($funcname);}
    1891     else {
     2387    $funcname = $prefix . '_sidebar_plugin_footer';
     2388    echo '<div id="pluginfooter">';
     2389    if ( function_exists( $funcname ) ) {
     2390        call_user_func( $funcname );
     2391    } else {
    18922392
    18932393        // Default Sidebar Plugin Footer
    1894         // -----------------------------
    1895 
    1896         // 1.7.4: link display depending on author
    1897         if ($author == 'wpmedic') {
    1898             $authordisplay = 'WP Medic';
    1899             $authorurl = $wqurls['wpm'];
    1900             $wqanchor = wqhelper_translate('WordQuest Plugins');
    1901             $pluginurl = $wqurls['wpm'].'/'.$pluginslug."/";
    1902         } else {
    1903             $authordisplay = 'WordQuest Alliance';
    1904             $authorurl = $wqurls['wq'];
    1905             $wqanchor = wqhelper_translate('More Cool Plugins');
    1906             $pluginurl = $wqurls['wq'].'/plugins/'.$pluginslug."/";
    1907         }
     2394        // -----------------------------
     2395
     2396        // 1.7.4: link display depending on author
     2397        $wqanchor = wqhelper_translate( 'WordQuest Plugins' );
     2398        $wpmanchor = wqhelper_translate( 'WP Medic Tools' );
     2399        if ( 'wordquest' == $author ) {
     2400           $authordisplay = 'WordQuest Alliance';
     2401           $authorurl = $wqurls['wq'];
     2402           $wqanchor = wqhelper_translate( 'More WordQuest Plugins' );
     2403           $pluginurl = $wqurls['wq'] . '/plugins/' . $pluginslug . '/';
     2404        } elseif ( 'wpmedic' == $author ) {
     2405           $authordisplay = 'WP Medic';
     2406           $authorurl = $wqurls['wpm'];
     2407           $wpmanchor = wqhelper_translate( 'More WP Medic Tools' );
     2408           $pluginurl = $wqurls['wpm'] . '/' . $pluginslug . '/';
     2409        }
     2410        // $wqlink = '<a href="' . esc_url( $wqurls['wq'] ) . '/plugins/" target="_blank"><b>&rarr; ' . esc_html( $wqanchor ) . '</b></a><br>';
     2411        // $wpmlink = '<a href="' . esc_url( $wqurls['wpm'] ) . '" target="_blank"><b>&rarr; ' . esc_html( $wpmanchor ) . '</b></a><br>';
    19082412
    19092413        // --- set values for theme or plugin ---
    1910         if ($pluginslug == 'bioship') {
    1911             $iconurl = get_template_directory_uri().'/images/'.$author.'.png';
     2414        $footertitle = wqhelper_translate( 'Plugin Info' );
     2415        $bioanchor = wqhelper_translate( 'BioShip Framework' );
     2416        if ( 'bioship' == $pluginslug ) {
     2417            // $iconurl = get_template_directory_uri() . '/images/' . $author . '.png';
    19122418            $pluginurl = $wqurls['bio'];
    1913             $pluginfootertitle = wqhelper_translate('Theme Info');
    1914         } else {
    1915             $iconurl = plugins_url('images/'.$author.'.png', __FILE__);
    1916             $pluginfootertitle = wqhelper_translate('Plugin Info');
    1917             $bioanchor = wqhelper_translate('BioShip Framework');
    1918         }
    1919 
    1920         // --- output plugin footer ---
    1921         echo '<div id="pluginfooter"><div class="stuffbox" style="width:250px;background-color:#ffffff;"><h3>'.$pluginfootertitle.'</h3><div class="inside">';
    1922         echo "<center><table><tr>";
    1923         echo "<td><a href='".$wqurls['wq']."/' target='_blank'><img src='".$iconurl."' border=0></a></td></td>";
    1924         echo "<td width='14'></td>";
    1925         echo "<td><a href='".$pluginurl."' target='_blank'>".$plugintitle."</a> <i>v".$pluginversion."</i><br>";
    1926         echo "by <a href='".$authorurl."/' target='_blank'>".$authordisplay."</a><br>";
    1927         echo "<a href='".$wqurls['wq']."/plugins/' target='_blank'><b>&rarr; ".$wqanchor."</b></a><br>";
    1928         if ($pluginslug != 'bioship') {
    1929             echo "<a href='".$wqurls['bio']."' target='_blank'>&rarr; ".$bioanchor."</a></td>";
    1930         }
    1931         // echo "<a href='".$wqurls['prn']."/directory/' target='_blank'>&rarr; ".wqhelper_translate('Plugin Directory')."</a></td>";
    1932         echo "</tr></table></center>";
    1933         echo '</div></div></div>';
    1934     }
     2419            $footertitle = wqhelper_translate( 'Theme Info' );
     2420        } // else {
     2421            // $iconurl = plugins_url( 'images/' . $author . '.png', __FILE__ );
     2422        // }
     2423
     2424        // --- output plugin footer ---
     2425        echo '<div class="stuffbox" style="width:250px;background-color:#ffffff;">';
     2426        echo '<h3>' . esc_html( $footertitle ) . '</h3><div class="inside"><center>';
     2427        // echo '<table><tr><td>';
     2428            // echo '<a href="' . esc_url( $wqurls['wq'] ) . '" target="_blank"><img src="' . esc_url( $iconurl ) . '" border="0"></a>';
     2429            // echo '</td><td width="14"></td><td>';
     2430
     2431            echo '<table><tr><td>';
     2432                echo '<a href="' . esc_url( $pluginurl ) . '" target="_blank">' . esc_html( $plugintitle ) . '</a> &nbsp; <i>v' . esc_html( $pluginversion ) . '</i><br>';
     2433                echo esc_html( wqhelper_translate( 'by' ) ) . ' <a href="' . esc_url( $authorurl ) . '" target="_blank">' . esc_html( $authordisplay ) . '</a><br><br></center>';
     2434
     2435                // 1.8.1: output links direct instead of storing
     2436                if ( 'wpmedic' == $author ) {
     2437                    echo '<a href="' . esc_url( $wqurls['wpm'] ) . '" target="_blank"><b>&rarr; ' . esc_html( $wpmanchor ) . '</b></a><br>';
     2438                    echo '<a href="' . esc_url( $wqurls['wq'] ) . '/plugins/" target="_blank"><b>&rarr; ' . esc_html( $wqanchor ) . '</b></a><br>';
     2439                } else {
     2440                    echo '<a href="' . esc_url( $wqurls['wq'] ) . '/plugins/" target="_blank"><b>&rarr; ' . esc_html( $wqanchor ) . '</b></a><br>';
     2441                    echo '<a href="' . esc_url( $wqurls['wpm'] ) . '" target="_blank"><b>&rarr; ' . esc_html( $wpmanchor ) . '</b></a><br>';
     2442                }
     2443                if ( 'bioship' != $pluginslug ) {
     2444                    echo '<a href="' . esc_url( $wqurls['bio'] ) . '" target="_blank"><b>&rarr; ' . esc_html( $bioanchor ) . '</a></b><br>';
     2445                }
     2446                echo '<a href="' . esc_url( $wqurls['prn'] ) . '/directory/" target="_blank"><b>&rarr; ' . esc_html( wqhelper_translate( 'Sorted Plugin Directory' ) ) . '</b></a>';
     2447            echo '</td></tr></table>';
     2448
     2449        // echo '</td>';
     2450        // echo '</tr></table>';
     2451        echo '</div></div>';
     2452    }
     2453    echo '</div>';
    19352454
    19362455    // --- close sidebar float div ---
     
    19442463// ------------------------
    19452464// 1.7.4: added Patreon Supporter Button
    1946 $funcname = 'wqhelper_sidebar_patreon_button_'.$wqhv;
    1947 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    1948  $wqfunctions[$funcname] = function($args) {
     2465$funcname = 'wqhelper_sidebar_patreon_button_' . $wqhv;
     2466if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     2467 $wqfunctions[$funcname] = function( $args ) {
    19492468
    19502469    global $wordquestplugins;
    1951     $prefix = $args[0]; $pluginslug = $args[1];
    1952     $settings = $wordquestplugins[$pluginslug];
    1953     $donatelink = apply_filters('wqhelper_donate_link', $settings['donate'], $pluginslug);
    1954     $message = apply_filters('wqhelper_donate_message', $settings['donatetext'], $pluginslug);
    1955 
    1956     // --- set button image URL ---
    1957     if ($pluginslug == 'bioship') {$imageurl = get_template_directory_uri().'/images/patreon-button.jpg';}
    1958     else {
    1959         // 1.7.5: check/fix for Patreon button URL (cross-versions)
    1960         if (file_exists(dirname(__FILE__).'/images/patreon-button.jpg')) {
    1961             $imageurl = plugins_url('images/patreon-button.jpg', __FILE__);
    1962         } else {
    1963             // --- try to reliably get actual plugin path/URL ---
    1964             $realslug = sanitize_title($wordquestplugins[$pluginslug]['title']);
    1965             if (file_exists(WP_PLUGIN_DIR.'/'.$realslug.'/images/patreon-button.jpg')) {
    1966                 $imageurl = WP_PLUGIN_URL.'/'.$realslug.'/images/patreon-button.jpg';
    1967             }
    1968         }
    1969     }
    1970     $imageurl = apply_filters('wqhelper_donate_image', $imageurl, $pluginslug);
    1971 
    1972     // --- output Patreon button ---
    1973     echo "<center><div class='supporter-message'>".$message."</div>".PHP_EOL;
    1974     echo "<a href='".$donatelink."' target=_blank>";
    1975         if ($imageurl) {echo "<img id='patreon-button' src='".$imageurl."'>";}
    1976         else {echo __('Become a Patron','forcefield');}
    1977     echo "</a><center>".PHP_EOL;
    1978 
    1979     // --- image hover styling ---
    1980     echo "<style>.supporter-message {font-size:15px; margin-bottom:5px;}
    1981     #patreon-button {opacity: 0.9;} #patreon-button:hover {opacity: 1;}</style>".PHP_EOL;
     2470    $prefix = $args[0];
     2471    $pluginslug = $args[1];
     2472    $settings = $wordquestplugins[$pluginslug];
     2473    $donatelink = apply_filters( 'wqhelper_donate_link', $settings['donate'], $pluginslug );
     2474    $message = apply_filters( 'wqhelper_donate_message', $settings['donatetext'], $pluginslug );
     2475
     2476    // --- set button image URL ---
     2477    if ( 'bioship' == $pluginslug ) {
     2478        $imageurl = get_template_directory_uri() . '/images/patreon-button.jpg';
     2479    } else {
     2480        // 1.7.5: check/fix for Patreon button URL (cross-versions)
     2481        if ( file_exists( dirname( __FILE__ ) . '/images/patreon-button.jpg' ) ) {
     2482            $imageurl = plugins_url( 'images/patreon-button.jpg', __FILE__ );
     2483        } else {
     2484            // --- try to reliably get actual plugin path/URL ---
     2485            $realslug = sanitize_title( $wordquestplugins[$pluginslug]['title'] );
     2486            if ( file_exists( WP_PLUGIN_DIR . '/' . $realslug . '/images/patreon-button.jpg' ) ) {
     2487                $imageurl = WP_PLUGIN_URL . '/' . $realslug . '/images/patreon-button.jpg';
     2488            }
     2489        }
     2490    }
     2491    $imageurl = apply_filters( 'wqhelper_donate_image', $imageurl, $pluginslug );
     2492
     2493    // --- output Patreon button ---
     2494    echo '<center><div class="supporter-message">' . esc_html( $message ) . '</div>';
     2495    echo '<a href="' . esc_url( $donatelink ) . '" target="_blank">';
     2496    if ( $imageurl ) {
     2497        echo '<img id="patreon-button" src="' . esc_url( $imageurl ) . '">';
     2498    } else {
     2499        echo esc_html( wqhelper_translate( 'Become a Patron' ) );
     2500    }
     2501    echo '</a><center>';
     2502
     2503    // --- image hover styling ---
     2504    echo '<style>.supporter-message {font-size:15px; margin-bottom:5px;}
     2505    #patreon-button {opacity: 0.9;} #patreon-button:hover {opacity: 1;}</style>';
    19822506
    19832507 };
     
    19872511// Paypal Donations
    19882512// ----------------
    1989 $funcname = 'wqhelper_sidebar_paypal_donations_'.$wqhv;
    1990 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    1991  $wqfunctions[$funcname] = function($args) {
     2513$funcname = 'wqhelper_sidebar_paypal_donations_' . $wqhv;
     2514if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     2515 $wqfunctions[$funcname] = function( $args ) {
    19922516
    19932517    global $wqurls;
    1994     $prefix = $args[0]; $pluginslug = $args[1];
    1995 
    1996     // --- make display name from the plugin slug ---
    1997     if (strstr($pluginslug, '-')) {
    1998         $parts = explode('-', $pluginslug);
     2518    $prefix = $args[0];
     2519    $pluginslug = $args[1];
     2520
     2521    // --- make display name from the plugin slug ---
     2522    if ( strstr( $pluginslug, '-' ) ) {
     2523        $parts = explode( '-', $pluginslug );
    19992524        $i = 0;
    2000         foreach ($parts as $part) {
    2001             if ($part == 'wp') {$parts[$i] = 'WP';}
    2002             else {$parts[$i] = strtoupper(substr($part, 0, 1)).substr($part, 1, (strlen($part)-1));}
     2525        foreach ( $parts as $part ) {
     2526            if ( 'wp' == $part ) {
     2527                $parts[$i] = 'WP';
     2528            } else {
     2529                $parts[$i] = strtoupper( substr( $part, 0, 1 ) ) . substr( $part, 1, ( strlen( $part ) - 1 ) );
     2530            }
    20032531            $i++;
    20042532        }
    2005         $pluginname = implode(' ', $parts);
     2533        $pluginname = implode( ' ', $parts );
    20062534    } else {
    2007         $pluginname = strtoupper(substr($pluginslug, 0, 1)).substr($pluginslug, 1, (strlen($pluginslug)-1));
     2535        $pluginname = strtoupper( substr( $pluginslug, 0, 1 ) ) . substr( $pluginslug, 1, ( strlen( $pluginslug ) - 1 ) );
    20082536    }
    20092537
    20102538    // --- donations scripts ---
    2011     echo "<script language='javascript' type='text/javascript'>
    2012     function showrecurringform() {
     2539    echo "<script>
     2540    function wq_show_recurring_form() {
    20132541        document.getElementById('recurradio').checked = true;
    20142542        document.getElementById('onetimedonation').style.display = 'none';
    20152543        document.getElementById('recurringdonation').style.display = '';
    20162544    }
    2017     function showonetimeform() {
     2545    function wq_show_one_time_form() {
    20182546        document.getElementById('onetimeradio').checked = true;
    20192547        document.getElementById('recurringdonation').style.display = 'none';
    20202548        document.getElementById('onetimedonation').style.display = '';
    20212549    }
    2022     function switchperiodoptions() {
    2023         var selectelement = document.getElementById('recurperiod');
    2024         var recurperiod = selectelement.options[selectelement.selectedIndex].value;
     2550    function wq_switch_period_options() {
     2551        selectelement = document.getElementById('recurperiod');
     2552        recurperiod = selectelement.options[selectelement.selectedIndex].value;
    20252553        if ( (recurperiod == 'Weekly') || (recurperiod == 'W') ) {
    20262554            document.getElementById('periodoptions').innerHTML = document.getElementById('weeklyamounts').innerHTML;
    2027             var monthlyselected = document.getElementById('monthlyselected').value;
    2028             var weeklyselected = monthlyselected++;
    2029             var selectelement = document.getElementById('periodoptions');
     2555            monthlyselected = document.getElementById('monthlyselected').value;
     2556            weeklyselected = monthlyselected++;
     2557            selectelement = document.getElementById('periodoptions');
    20302558            selectelement.selectedIndex = weeklyselected;
    20312559        }
    20322560        if ( (recurperiod == 'Monthly') || (recurperiod == 'M') ) {
    20332561            document.getElementById('periodoptions').innerHTML = document.getElementById('monthlyamounts').innerHTML;
    2034             var weeklyselected = document.getElementById('weeklyselected').value;
    2035             var monthlyselected = weeklyselected--;
    2036             var selectelement = document.getElementById('periodoptions')
     2562            weeklyselected = document.getElementById('weeklyselected').value;
     2563            monthlyselected = weeklyselected--;
     2564            selectelement = document.getElementById('periodoptions');
    20372565            selectelement.selectedIndex = monthlyselected;
    20382566        }
    20392567    }
    2040     function storeamount() {
    2041         var selectelement = document.getElementById('recurperiod');
    2042         var recurperiod = selectelement.options[selectelement.selectedIndex].value;
    2043         var selectelement = document.getElementById('periodoptions');
    2044         var selected = selectelement.selectedIndex;
     2568    function wq_store_amount() {
     2569        selectelement = document.getElementById('recurperiod');
     2570        recurperiod = selectelement.options[selectelement.selectedIndex].value;
     2571        selectelement = document.getElementById('periodoptions');
     2572        selected = selectelement.selectedIndex;
    20452573        if ( (recurperiod == 'Weekly') || (recurperiod == 'W') ) {
    20462574            document.getElementById('weeklyselected').value = selected;
     
    20492577            document.getElementById('monthlyselected').value = selected;
    20502578        }
    2051     }
    2052     </script>";
     2579    }</script>";
    20532580
    20542581    // --- set Paypal notification URL ---
    2055     $notifyurl = $wqurls['wq'].'/?estore_pp_ipn=process';
     2582    $notifyurl = $wqurls['wq'] . '/?estore_pp_ipn=process';
    20562583    $sandbox = ''; // $sandbox = 'sandbox.';
    20572584
    20582585    // --- recurring / one-time switcher ---
    2059     echo "<center><table cellpadding='0' cellspacing='0'><tr><td>";
    2060     echo "<input name='donatetype' id='recurradio' type='radio' onclick='showrecurringform();' checked> <a href='javascript:void(0);' onclick='showrecurringform();' style='text-decoration:none;'>".wqhelper_translate('Supporter')."</a> ";
    2061     echo "</td><td width='10'></td><td>";
    2062     echo "<input name='donatetype' id='onetimeradio' type='radio' onclick='showonetimeform();'> <a href-'javascript:void(0);' onclick='showonetimeform();' style='text-decoration:none;'>".wqhelper_translate('One Time')."</a>";
    2063     echo "</td></tr></table></center>";
     2586    echo '<center><table cellpadding="0" cellspacing="0"><tr><td>';
     2587        echo '<input name="donatetype" id="recurradio" type="radio" onclick="wq_show_recurring_form();" checked="checked">';
     2588        echo ' <a href="javascript:void(0);" onclick="wq_show_recurring_form();" style="text-decoration:none;">' . esc_html( wqhelper_translate( 'Supporter' ) ) . '</a> ';
     2589    echo '</td><td width="10"></td><td>';
     2590        echo '<input name="donatetype" id="onetimeradio" type="radio" onclick="wq_show_one_time_form();"> ';
     2591        echo '<a href="javascript:void(0);" onclick="wq_show_one_time_form();" style="text-decoration:none;">' . esc_html( wqhelper_translate( 'One Time' ) ) . '</a>';
     2592    echo '</td></tr></table></center>';
    20642593
    20652594    // --- set weekly amount options ---
    20662595    // 1.5.0: added weekly amounts
    2067     echo '<div style="display:none;"><input type="hidden" id="weeklyselected" value="3">
    2068     <select name="wp_eStore_subscribe" id="weeklyamounts" style="font-size:8pt;" size="1">
    2069     <optgroup label="'.wqhelper_translate('Supporter Amount').'">
    2070     <option value="1">'.wqhelper_translate('Copper').': $1 </option>
    2071     <option value="3">'.wqhelper_translate('Bronze').': $2</option>
    2072     <option value="5">'.wqhelper_translate('Silver').': $4</option>
    2073     <option value="7">'.wqhelper_translate('Gold').': $5</option>
    2074     <option value="9">'.wqhelper_translate('Platinum').': $7.50</option>
    2075     <option value="11">'.wqhelper_translate('Titanium').': $10</option>
    2076     <option value="13">'.wqhelper_translate('Star Ruby').': $12.50</option>
    2077     <option value="15">'.wqhelper_translate('Star Topaz').': $15</option>
    2078     <option value="17">'.wqhelper_translate('Star Emerald').': $17.50</option>
    2079     <option value="19">'.wqhelper_translate('Star Sapphire').': $20</option>
    2080     <option value="21">'.wqhelper_translate('Star Diamond').': $25</option>
    2081     </select></div>';
     2596    echo '<div style="display:none;">';
     2597    echo '<input type="hidden" id="weeklyselected" value="3">';
     2598    echo '<select name="wp_eStore_subscribe" id="weeklyamounts" style="font-size:8pt;" size="1">';
     2599    echo '<optgroup label="' . esc_attr( wqhelper_translate( 'Supporter Amount' ) ) . '">';
     2600    echo '<option value="1">' . esc_html( wqhelper_translate( 'Copper' ) ) . ': $1 </option>';
     2601    echo '<option value="3">' . esc_html( wqhelper_translate( 'Bronze' ) ) . ': $2</option>';
     2602    echo '<option value="5">' . esc_html( wqhelper_translate( 'Silver' ) ) . ': $4</option>';
     2603    echo '<option value="7" selected="selected">' . esc_html( wqhelper_translate( 'Gold' ) ) . ': $5</option>';
     2604    echo '<option value="9">' . esc_html( wqhelper_translate( 'Platinum' ) ) . ': $7.50</option>';
     2605    echo '<option value="11">' . esc_html( wqhelper_translate( 'Titanium' ) ) . ': $10</option>';
     2606    echo '<option value="13">' . esc_html( wqhelper_translate( 'Star Ruby' ) ) . ': $12.50</option>';
     2607    echo '<option value="15">' . esc_html( wqhelper_translate( 'Star Topaz' ) ) . ': $15</option>';
     2608    echo '<option value="17">' . esc_html( wqhelper_translate( 'Star Emerald' ) ) . ': $17.50</option>';
     2609    echo '<option value="19">' . esc_html( wqhelper_translate( 'Star Sapphire' ) ) . ': $20</option>';
     2610    echo '<option value="21">' . esc_html( wqhelper_translate( 'Star Diamond' ) ) . ': $25</option>';
     2611    echo '</select></div>';
    20822612
    20832613    // --- set monthly amount options ---
    20842614    // 1.5.0: added monthly amounts
    2085     echo '<div style="display:none;"><input type="hidden" id="monthlyselected" value="3">
    2086     <select name="wp_eStore_subscribe" id="monthlyamounts" style="font-size:8pt;" size="1">
    2087     <optgroup label="'.wqhelper_translate('Supporter Amount').'">
    2088     <option value="2">'.wqhelper_translate('Copper').': $5</option>
    2089     <option value="4">'.wqhelper_translate('Bronze').': $10</option>
    2090     <option value="6">'.wqhelper_translate('Silver').': $15</option>
    2091     <option value="9" selected="selected">'.wqhelper_translate('Gold').': $20</option>
    2092     <option value="10">'.wqhelper_translate('Platinum').': $30</option>
    2093     <option value="12">'.wqhelper_translate('Titanium').': $40</option>
    2094     <option value="14">'.wqhelper_translate('Star Ruby').': $50</option>
    2095     <option value="16">'.wqhelper_translate('Star Topaz').': $60</option>
    2096     <option value="18">'.wqhelper_translate('Star Emerald').': $70</option>
    2097     <option value="20">'.wqhelper_translate('Star Sapphire').': $80</option>
    2098     <option value="22">'.wqhelper_translate('Star Diamond').': $100</option>
    2099     </select></div>';
     2615    echo '<div style="display:none;">';
     2616    echo '<input type="hidden" id="monthlyselected" value="3">';
     2617    echo '<select name="wp_eStore_subscribe" id="monthlyamounts" style="font-size:8pt;" size="1">';
     2618    echo '<optgroup label="' . esc_attr( wqhelper_translate( 'Supporter Amount' ) ) . '">';
     2619    echo '<option value="2">' . esc_html( wqhelper_translate( 'Copper' ) ) . ': $5</option>';
     2620    echo '<option value="4">' . esc_html( wqhelper_translate( 'Bronze' ) ) . ': $10</option>';
     2621    echo '<option value="6">' . esc_html( wqhelper_translate( 'Silver' ) ) . ': $15</option>';
     2622    echo '<option value="9" selected="selected">' . esc_html( wqhelper_translate( 'Gold' ) ) . ': $20</option>';
     2623    echo '<option value="10">' . esc_html( wqhelper_translate( 'Platinum' ) ) . ': $30</option>';
     2624    echo '<option value="12">' . esc_html( wqhelper_translate( 'Titanium' ) ) . ': $40</option>';
     2625    echo '<option value="14">' . esc_html( wqhelper_translate( 'Star Ruby' ) ) . ': $50</option>';
     2626    echo '<option value="16">' . esc_html( wqhelper_translate( 'Star Topaz' ) ) . ': $60</option>';
     2627    echo '<option value="18">' . esc_html( wqhelper_translate( 'Star Emerald' ) ) . ': $70</option>';
     2628    echo '<option value="20">' . esc_html( wqhelper_translate( 'Star Sapphire' ) ) . ': $80</option>';
     2629    echo '<option value="22">' . esc_html( wqhelper_translate( 'Star Diamond' ) ) . ': $100</option>';
     2630    echo '</select></div>';
    21002631
    21012632    // note: eStore recurring subscription form
     
    21032634
    21042635    // --- set donate image URL ---
    2105     if ($pluginslug == 'bioship') {$donateimage = get_template_directory_uri().'/images/pp-donate.jpg';}
    2106     else {$donateimage = plugins_url('/images/pp-donate.jpg', __FILE__);}
     2636    if ( 'bioship' == $pluginslug ) {
     2637        $donateimage = get_template_directory_uri() . '/images/pp-donate.jpg';
     2638    } else {
     2639        $donateimage = plugins_url( '/images/pp-donate.jpg', __FILE__ );
     2640    }
    21072641
    21082642    // --- recurring donation form ---
    2109     echo '
    2110         <center><form id="recurringdonation" method="GET" action="'.$wqurls['wq'].'" target="_blank">
    2111         <input type="hidden" name="c_input" value="'.$pluginslug.'">
    2112         <select name="wp_eStore_subscribe" style="font-size:10pt;" size="1" id="periodoptions" onchange="storeamount();">
    2113         <optgroup label="'.wqhelper_translate('Supporter Amount').'">
    2114         <option value="1">'.wqhelper_translate('Copper').': $1 </option>
    2115         <option value="3">'.wqhelper_translate('Bronze').': $2</option>
    2116         <option value="5">'.wqhelper_translate('Silver').': $4</option>
    2117         <option value="7" selected="selected">'.wqhelper_translate('Gold').': $5</option>
    2118         <option value="9">'.wqhelper_translate('Platinum').': $7.50</option>
    2119         <option value="11">'.wqhelper_translate('Titanium').': $10</option>
    2120         <option value="13">'.wqhelper_translate('Ruby').': $12.50</option>
    2121         <option value="15">'.wqhelper_translate('Topaz').': $15</option>
    2122         <option value="17">'.wqhelper_translate('Emerald').': $17.50</option>
    2123         <option value="19">'.wqhelper_translate('Sapphire').': $20</option>
    2124         <option value="21">'.wqhelper_translate('Diamond').': $25</option>
    2125         </select>
    2126         </td><td width="5"></td><td>
    2127         <select name="t3" style="font-size:10pt;" id="recurperiod" onchange="switchperiodoptions()">
    2128         <option selected="selected" value="W">'.wqhelper_translate('Weekly').'</option>
    2129         <option value-"M">'.wqhelper_translate('Monthly').'</option>
    2130         </select></tr></table>
    2131         <input type="image" src="'.$donateimage.'" border="0" name="I1">
    2132         </center></form>';
     2643    echo '<center><form id="recurringdonation" method="GET" action="' . esc_url( $wqurls['wq'] ) . '" target="_blank">';
     2644        echo '<input type="hidden" name="c_input" value="' . esc_attr( $pluginslug ) . '">';
     2645        echo '<select name="wp_eStore_subscribe" style="font-size:10pt;" size="1" id="periodoptions" onchange="wq_store_amount();">';
     2646        echo '<optgroup label="' . esc_attr( wqhelper_translate( 'Supporter Amount' ) ) . '">';
     2647        echo '<option value="1">' . esc_html( wqhelper_translate( 'Copper' ) ) . ': $1 </option>';
     2648        echo '<option value="3">' . esc_html( wqhelper_translate( 'Bronze' ) ) . ': $2</option>';
     2649        echo '<option value="5">' . esc_html( wqhelper_translate( 'Silver' ) ) . ': $4</option>';
     2650        echo '<option value="7" selected="selected">' . esc_html( wqhelper_translate( 'Gold' ) ) . ': $5</option>';
     2651        echo '<option value="9">' . esc_html( wqhelper_translate( 'Platinum' ) ) . ': $7.50</option>';
     2652        echo '<option value="11">' . esc_html( wqhelper_translate( 'Titanium' ) ) . ': $10</option>';
     2653        echo '<option value="13">' . esc_html( wqhelper_translate( 'Ruby' ) ) . ': $12.50</option>';
     2654        echo '<option value="15">' . esc_html( wqhelper_translate( 'Topaz' ) ) . ': $15</option>';
     2655        echo '<option value="17">' . esc_html( wqhelper_translate( 'Emerald' ) ) . ': $17.50</option>';
     2656        echo '<option value="19">' . esc_html( wqhelper_translate( 'Sapphire' ) ) . ': $20</option>';
     2657        echo '<option value="21">' . esc_html( wqhelper_translate( 'Diamond' ) ) . ': $25</option>';
     2658        echo '</select>';
     2659
     2660    echo '</td><td width="5"></td><td>';
     2661    echo '<select name="t3" style="font-size:10pt;" id="recurperiod" onchange="wq_switch_period_options()">';
     2662    echo '<option selected="selected" value="W">' . esc_html( wqhelper_translate( 'Weekly' ) ) . '</option>';
     2663    echo '<option value="M">' . esc_html( wqhelper_translate( 'Monthly' ) ) . '</option>';
     2664    echo '</select></tr></table>';
     2665
     2666    echo '<input type="image" src="' . esc_url( $donateimage ) . '" border="0" name="I1">';
     2667    echo '</center></form>';
    21332668
    21342669    /// --- one time donation form ---
    21352670    // $wqurls['wq'].'/?wp_eStore_donation=23&var1_price=AMOUNT&c_input='.$pluginslug;
    2136     echo '
    2137     <center><form id="onetimedonation" style="display:none;" method="GET" action="'.$wqurls['wq'].'" target="_blank">
    2138         <input type="hidden" name="wp_eStore_donation" value="23">
    2139         <input type="hidden" name="c_input" value="'.$pluginslug.'">
    2140         <select name="var1_price" style="font-size:10pt;" size="1">
    2141         <option selected value="">'.wqhelper_translate('Select Gift Amount').'</option>
    2142         <option value="5">$5 - '.wqhelper_translate('Buy me a Cuppa').'</option>
    2143         <option value="10">$10 - '.wqhelper_translate('Log a Feature Request').'</option>
    2144         <option value="20">$20 - '.wqhelper_translate('Support a Minor Bugfix').'</option>
    2145         <option value="50">$50 - '.wqhelper_translate('Support a Minor Update').'</option>
    2146         <option value="100">$100 - '.wqhelper_translate('Support a Major Bugfix/Update').'</option>
    2147         <option value="250">$250 - '.wqhelper_translate('Support a Minor Feature').'</option>
    2148         <option value="500">$500 - '.wqhelper_translate('Support a Major Feature').'</option>
    2149         <option value="1000">$1000 - '.wqhelper_translate('Support a New Module').'</option>
    2150         <option value="2000">$1000 - '.wqhelper_translate('Support a New Plugin').'</option>
    2151         <option value="">'.wqhelper_translate('Be Unique: Enter Custom Amount').'</option>
    2152         </select>
    2153         <input type="image" src="'.$donateimage.'" border="0" name="I1">
    2154         </center></form>
    2155     ';
     2671    echo '<center><form id="onetimedonation" style="display:none;" method="GET" action="' . esc_url( $wqurls['wq'] ) . '" target="_blank">';
     2672        echo '<input type="hidden" name="wp_eStore_donation" value="23">';
     2673        echo '<input type="hidden" name="c_input" value="' . esc_attr( $pluginslug ) . '">';
     2674        echo '<select name="var1_price" style="font-size:10pt;" size="1">';
     2675            echo '<option selected value="">' . esc_html( wqhelper_translate( 'Select Gift Amount' ) ) . '</option>';
     2676            echo '<option value="5">$5 - ' . esc_html( wqhelper_translate( 'Buy me a Cuppa' ) ) . '</option>';
     2677            echo '<option value="10">$10 - ' . esc_html( wqhelper_translate( 'Log a Feature Request' ) ) . '</option>';
     2678            echo '<option value="20">$20 - ' . esc_html( wqhelper_translate( 'Support a Minor Bugfix' ) ) . '</option>';
     2679            echo '<option value="50">$50 - ' . esc_html( wqhelper_translate( 'Support a Minor Update' ) ) . '</option>';
     2680            echo '<option value="100">$100 - ' . esc_html( wqhelper_translate( 'Support a Major Update' ) ) . '</option>';
     2681            echo '<option value="250">$250 - ' . esc_html( wqhelper_translate( 'Support a Minor Feature' ) ) . '</option>';
     2682            echo '<option value="500">$500 - ' . esc_html( wqhelper_translate( 'Support a Major Feature' ) ) . '</option>';
     2683            echo '<option value="1000">$1000 - ' . esc_html( wqhelper_translate( 'Support a New Module' ) ) . '</option>';
     2684            echo '<option value="2000">$1000 - ' . esc_html( wqhelper_translate( 'Support a New Plugin' ) ) . '</option>';
     2685            echo '<option value="">' . esc_html( wqhelper_translate( 'Be Unique: Enter Custom Amount' ) ) . '</option>';
     2686        echo '</select>';
     2687        echo '<input type="image" src="' . esc_url( $donateimage ) . '" border="0" name="I1">';
     2688    echo '</center></form>';
    21562689
    21572690 };
     
    21612694// Testimonial Box
    21622695// ---------------
    2163 $funcname = 'wqhelper_sidebar_testimonial_box_'.$wqhv;
    2164 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    2165  $wqfunctions[$funcname] = function($args) {
    2166 
    2167     global $wqurls, $current_user; $current_user = wp_get_current_user();
     2696$funcname = 'wqhelper_sidebar_testimonial_box_' . $wqhv;
     2697if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     2698 $wqfunctions[$funcname] = function( $args ) {
     2699
     2700    global $wqurls, $current_user;
     2701    $current_user = wp_get_current_user();
    21682702    $useremail = $current_user->user_email;
    2169     if (strstr($useremail, '@localhost')) {$useremail = '';}
    2170     $userid = $current_user->ID; $userdata = get_userdata($userid);
    2171     $username = $userdata->first_name; $lastname = $userdata->last_name;
    2172     if ($lastname != '') {$username .= ' '.$lastname;}
    2173 
    2174     $prefix = $args[0]; $pluginslug = $args[1];
    2175     $pluginslug = str_replace('-', '', $pluginslug);
     2703    if ( strstr( $useremail, '@localhost' ) ) {
     2704        $useremail = '';
     2705    }
     2706    $userid = $current_user->ID;
     2707    $userdata = get_userdata( $userid );
     2708    $username = $userdata->first_name;
     2709    $lastname = $userdata->last_name;
     2710    if ( '' != $lastname ) {
     2711        $username .= ' ' . $lastname;
     2712    }
     2713
     2714    $prefix = $args[0];
     2715    $pluginslug = $args[1];
     2716    $pluginslug = str_replace( '-', '', $pluginslug );
    21762717
    21772718    // --- testimonial script ---
    21782719    echo "<script>
    2179     function showhidetestimonialbox() {
     2720    function wq_showhide_testimonial_box() {
    21802721        if (document.getElementById('sendtestimonial').style.display == '') {
    21812722            document.getElementById('sendtestimonial').style.display = 'none';
    2182         }
    2183         else {
     2723        } else {
    21842724            document.getElementById('sendtestimonial').style.display = '';
    21852725            document.getElementById('testimonialbox').style.display = 'none';
    21862726        }
    21872727    }
    2188     function submittestimonial() {
     2728    function wq_submit_testimonial() {
    21892729        document.getElementById('testimonialbox').style.display='';
    21902730        document.getElementById('sendtestimonial').style.display='none';
     
    21922732
    21932733    // --- testimonial form ---
    2194     echo "<center><a href='javascript:void(0);' onclick='showhidetestimonialbox();'>".wqhelper_translate('Send me a thank you or testimonial.')."</a><br>";
    2195     echo "<div id='sendtestimonial' style='display:none;' align='center'>";
    2196     echo "<center><form action='".$wqurls['wq']."' method='post' target='testimonialbox' onsubmit='submittestimonial();'>";
    2197     echo "<b>".wqhelper_translate('Your Testimonial').":</b><br>";
    2198     echo "<textarea rows='5' cols='25' name='message'></textarea><br>";
    2199     echo "<label for='testimonial_sender'>".wqhelper_translate('Your Name').":</label> ";
    2200     echo "<input type='text' placeholder='".wqhelper_translate('Your Name')."... (".wqhelper_translate('optional').")' style='width:200px;' name='testimonial_sender' value='".$username."'><br>";
    2201     echo "<input type='text' placeholder='".wqhelper_translate('Your Website')."... (".wqhelper_translate('optional').")' style='width:200px;' name='testimonial_website' value=''><br>";
    2202     echo "<input type='hidden' name='sending_plugin_testimonial' value='yes'>";
    2203     echo "<input type='hidden' name='for_plugin' value='".$pluginslug."'>";
    2204     echo "<input type='submit' class='button-secondary' value='".wqhelper_translate('Send Testimonial')."'>";
    2205     echo "</form>";
    2206     echo "</div>";
    2207     echo "<iframe name='testimonialbox' id='testimonialbox' frameborder='0' src='javascript:void(0);' style='display:none;' width='250' height='50' scrolling='no'></iframe>";
     2734    echo '<center><a href="javascript:void(0);" onclick="wq_showhide_testimonial_box();">' . esc_html( wqhelper_translate( 'Send me a thank you or testimonial.' ) ) . '</a><br>';
     2735    echo '<div id="sendtestimonial" style="display:none;" align="center"><center>';
     2736        echo '<form action="' . esc_url( $wqurls['wq'] ) . '" method="post" target="testimonialbox" onsubmit="wq_submit_testimonial();">';
     2737        echo '<b>' . esc_html( wqhelper_translate( 'Your Testimonial' ) ) . ':</b><br>';
     2738        echo '<textarea rows="5" cols="25" name="message"></textarea><br>';
     2739        echo '<label for="testimonial_sender">' . esc_html( wqhelper_translate( 'Your Name' ) ) . ':</label> ';
     2740        echo '<input type="text" style="width:200px;" name="testimonial_sender" id="testimonial_sender" value="' . esc_attr( $username ) . '"><br>';
     2741        echo '<input type="text" placeholder="' . esc_attr( wqhelper_translate( 'Your Website' ) ) . '... (' . esc_html( wqhelper_translate( 'optional' ) ) . ')" style="width:200px;" name="testimonial_website" value=""><br>';
     2742        echo '<input type="hidden" name="sending_plugin_testimonial" value="yes">';
     2743        echo '<input type="hidden" name="for_plugin" value="' . esc_attr( $pluginslug ) . '">';
     2744        echo '<input type="submit" class="button-secondary" value="' . esc_attr( wqhelper_translate( 'Send Testimonial' ) ) . '">';
     2745    echo '</form></center></div>';
     2746    echo '<iframe name="testimonialbox" id="testimonialbox" frameborder="0" src="javascript:void(0);" style="display:none;" width="250" height="50" scrolling="no"></iframe>';
    22082747 };
    22092748}
     
    22132752// ---------------------
    22142753// !! caller exception !! uses form matching version function
    2215 $funcname = 'wqhelper_update_sidebar_options_'.$wqhv;
    2216 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     2754$funcname = 'wqhelper_update_sidebar_options_' . $wqhv;
     2755if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    22172756 $wqfunctions[$funcname] = function() {
    22182757
    2219     $pre = $_REQUEST['sidebarprefix'];
    2220     if (current_user_can('manage_options')) {
     2758    // 1.7.8: fix sidebar option saveing variable pre to prefix
     2759    // 1.8.1: use sanitize_title on request variable
     2760    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     2761    $prefix = sanitize_title( $_REQUEST['sidebarprefix'] );
     2762    if ( current_user_can( 'manage_options' ) ) {
    22212763
    22222764        // 1.6.5: check nonce field
    2223         check_admin_referer($prefix.'_sidebar');
     2765        check_admin_referer( $prefix . '_sidebar' );
    22242766
    22252767        // 1.5.0: convert to single array of plugin sidebar options
    2226         $sidebaroptions = get_option($prefix.'_sidebar_options');
    2227         if (!$sidebaroptions) {$sidebaroptions = array('installdate' => date('Y-m-d'));}
    2228         $sidebaroptions['adsboxoff'] = $sidebaroptions['donationboxoff'] = $sidebaroptions['reportboxoff'] = '';
    2229         if (isset($_POST[$prefix.'_ads_box_off']) && ($_POST[$prefix.'_ads_box_off'] == 'checked')) {$sidebaroptions['adsboxoff'] = 'checked';}
    2230         if (isset($_POST[$prefix.'_donation_box_off']) && ($_POST[$prefix.'_donation_box_off'] == 'checked')) {$sidebaroptions['donationboxoff'] = 'checked';}
    2231         if (isset($_POST[$prefix.'_report_box_off']) && ($_POST[$prefix.'_report_box_off'] == 'checked')) {$sidebaroptions['reportboxoff'] = 'checked';}
    2232         update_option($prefix.'_sidebar_options', $sidebaroptions);
     2768        $sidebaroptions = get_option( $prefix . '_sidebar_options' );
     2769        if ( !$sidebaroptions ) {
     2770            $sidebaroptions = array(
     2771                'installdate' => date( 'Y-m-d' ),
     2772            );
     2773        }
     2774        $sidebaroptions['adsboxoff'] = $sidebaroptions['subscribeboxoff'] = $sidebaroptions['donationboxoff'] = $sidebaroptions['reportboxoff'] = '';
     2775
     2776        // 1.8.0: reduce code by looping box options
     2777        $options = array(
     2778            '_donation_box_off' => 'donationboxoff',
     2779            // '_testimonial_box_off' => 'testimonialboxoff',
     2780            '_subscribe_box_off' => 'subscribeboxoff',
     2781            '_report_box_off' => 'reportboxoff',
     2782            '_ads_box_off' => 'adsboxoff',
     2783        );
     2784        foreach ( $options as $key => $option ) {
     2785            // phpcs:ignore WordPress.Security.NonceValidation.Recommended
     2786            if ( isset( $_POST[$prefix . $key] ) && ( 'checked' == sanitize_title( $_POST[$prefix . $key] ) ) ) {
     2787                $sidebaroptions[$option] = 'checked';
     2788            }
     2789        }
     2790        update_option( $prefix . '_sidebar_options', $sidebaroptions );
    22332791        // print_r($sidebaroptions); // debug point
    22342792
    22352793        // --- javascript response callbacks ---
    2236         echo "<script>";
    2237         echo PHP_EOL."if (parent.document.getElementById('donate')) {";
    2238         if ($sidebaroptions['donationboxoff'] == 'checked') {echo "parent.document.getElementById('donate').style.display = 'none';}";}
    2239         else {echo "parent.document.getElementById('donate').style.display = '';}";}
    2240         echo PHP_EOL."if (parent.document.getElementById('bonusoffer')) {";
    2241         if ($sidebaroptions['reportboxoff'] == 'checked') {echo "parent.document.getElementById('bonusoffer').style.display = 'none';}";}
    2242         else {echo "parent.document.getElementById('bonusoffer').style.display = '';}";}
    2243         echo PHP_EOL."if (parent.document.getElementById('pluginads')) {";
    2244         if ($sidebaroptions['adsboxoff'] == 'checked') {echo "parent.document.getElementById('pluginads').style.display = 'none';}";}
    2245         else {echo "parent.document.getElementById('pluginads').style.display = '';}";}
    2246         echo PHP_EOL."parent.document.getElementById('sidebarsaved').style.display = ''; ";
    2247         echo PHP_EOL."parent.document.getElementById('sidebarsettings').style.display = 'none'; ";
     2794        // 1.8.0: reduce code by looping box options
     2795        $boxes = array(
     2796            'donationboxoff' => 'donate-box',
     2797            'subscribeboxoff' => 'subscribe-box',
     2798            'reportboxoff' => 'report-box',
     2799            'adsboxoff' => 'recommend-box',
     2800        );
     2801        echo "<script>" . PHP_EOL;
     2802        foreach ( $boxes as $key => $id ) {
     2803            echo "if (parent.document.getElementById('" . esc_js( $id ) . "')) {";
     2804            if ( 'checked' == $sidebaroptions[$key] ) {
     2805                echo "parent.document.getElementById('" . esc_js( $id ) . "').style.display = 'none';}";
     2806            } else {
     2807                echo "parent.document.getElementById('" . esc_js( $id ) . "').style.display = '';}";
     2808            }
     2809            echo PHP_EOL;
     2810        }
     2811
     2812        echo PHP_EOL . "parent.document.getElementById('sidebarsaved').style.display = ''; ";
     2813        echo PHP_EOL . "parent.document.getElementById('sidebarsettings').style.display = 'none'; ";
    22482814        echo "</script>";
    22492815
    22502816        // --- maybe call Special Update Options ---
    2251         $funcname = $prefix.'_update_sidebar_options_special';
    2252         if (function_exists($funcname)) {call_user_func($funcname);}
     2817        $funcname = $prefix . '_update_sidebar_options_special';
     2818        if ( function_exists( $funcname ) ) {
     2819            call_user_func( $funcname );
     2820        }
    22532821    }
    22542822
     
    22602828// Sticky Kit Javascript
    22612829// ---------------------
    2262 $funcname = 'wqhelper_sidebar_stickykitscript_'.$wqhv;
    2263 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    2264  $wqfunctions[$funcname] = function() {
    2265 return '<script>/* Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net */
     2830// 1.8.1: added echo argument to function
     2831$funcname = 'wqhelper_sidebar_stickykitscript_' . $wqhv;
     2832if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     2833 $wqfunctions[$funcname] = function( $echo = false ) {
     2834
     2835    // 1.8.1: added for backwards compatibility
     2836    if ( !$echo ) {
     2837        ob_start();
     2838    }
     2839
     2840    echo '<script>/* Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net */
    22662841(function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k));
    22672842if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("<div />"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q,
     
    22702845a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize",
    22712846y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n<K;n++)d=this[n],J(b(d));return this}}).call(this);</script>';
     2847
     2848    // 1.8.1 added for backwards compatibility
     2849    if ( !$echo ) {
     2850        $stickykit = ob_get_contents();
     2851        ob_end_clean();
     2852        return $stickykit;
     2853    }
    22722854 };
    22732855} // '
     
    22762858// Float Menu Javascript
    22772859// ---------------------
    2278 $funcname = 'wqhelper_sidebar_floatmenuscript_'.$wqhv;
    2279 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    2280  $wqfunctions[$funcname] = function() {
    2281 
    2282     return "
     2860// 1.8.1: added echo argument to function
     2861$funcname = 'wqhelper_sidebar_floatmenuscript_' . $wqhv;
     2862if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     2863 $wqfunctions[$funcname] = function( $echo = false ) {
     2864
     2865    // 1.8.1: added for backwards compatibility
     2866    if ( !$echo ) {
     2867        ob_start();
     2868    }
     2869
     2870    echo "
    22832871    <style>.floatbox {position:absolute;width:250px;top:30px;right:15px;z-index:100;}</style>
    22842872
    2285     <script language='javascript' type='text/javascript'>
     2873    <script>
    22862874    /* Script by: www.jtricks.com
    22872875     * Version: 1.8 (20111103)
     
    25073095    }
    25083096    </script>";
     3097
     3098    // 1.8.1: added for backwards compatibility
     3099    if ( !$echo ) {
     3100        $floatbox = ob_get_contents();
     3101        ob_end_clean();
     3102        return $floatbox;
     3103    }
    25093104 };
    25103105}
     
    25183113// Add the Dashboard Feed Widget
    25193114// -----------------------------
     3115// 1.7.8: simplify dashboard detection
    25203116$requesturi = $_SERVER['REQUEST_URI'];
    2521 if ( (preg_match('|index.php|i', $requesturi))
    2522   || (substr($requesturi, -(strlen('/wp-admin/'))) == '/wp-admin/')
    2523   || (substr($requesturi, -(strlen('/wp-admin/network'))) == '/wp-admin/network/') ) {
    2524     if (!has_action('wp_dashboard_setup', 'wqhelper_add_dashboard_feed_widget')) {
    2525         add_action('wp_dashboard_setup', 'wqhelper_add_dashboard_feed_widget');
     3117if ( ( preg_match( '|index.php|i', $requesturi ) )
     3118    || ( stristr( $requesturi, '/wp-admin/' ) )
     3119    || ( stristr( $requesturi, '/wp-admin/network/' ) ) ) {
     3120    if ( !has_action( 'wp_dashboard_setup', 'wqhelper_add_dashboard_feed_widget' ) ) {
     3121        add_action( 'wp_dashboard_setup', 'wqhelper_add_dashboard_feed_widget' );
    25263122    }
    25273123}
     
    25303126// Load the Dashboard Feeds
    25313127// ------------------------
    2532 $funcname = 'wqhelper_add_dashboard_feed_widget_'.$wqhv;
    2533 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     3128$funcname = 'wqhelper_add_dashboard_feed_widget_' . $wqhv;
     3129if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    25343130 $wqfunctions[$funcname] = function() {
    25353131
    25363132    global $wp_meta_boxes, $current_user;
    2537     if (current_user_can('manage_options') || current_user_can('install_plugins')) {
     3133    if ( current_user_can( 'manage_options' ) || current_user_can( 'install_plugins' ) ) {
    25383134
    25393135        // --- check if already loaded ---
    25403136        // 1.6.1: fix to undefined index warning
    25413137        $wordquestloaded = $pluginreviewloaded = false;
    2542         foreach (array_keys($wp_meta_boxes['dashboard']['normal']['core']) as $name) {
    2543             if ($name == 'wordquest') {$wordquestloaded = true;}
    2544             if ($name == 'pluginreview') {$pluginreviewloaded = true;}
     3138        foreach ( array_keys( $wp_meta_boxes['dashboard']['normal']['core'] ) as $name ) {
     3139            if ( 'wordquest' == $name ) {
     3140                $wordquestloaded = true;
     3141            }
     3142            if ( 'pluginreview' == $name ) {
     3143                $pluginreviewloaded = true;
     3144            }
    25453145        }
    25463146
    25473147        // --- maybe add wordquest feed widget
    2548         if (!$wordquestloaded) {
    2549             wp_add_dashboard_widget('wordquest', 'WordQuest Alliance', 'wqhelper_dashboard_feed_widget');
     3148        if ( !$wordquestloaded ) {
     3149            wp_add_dashboard_widget( 'wordquest', 'WordQuest Alliance', 'wqhelper_dashboard_feed_widget' );
    25503150        }
    25513151
    25523152        // --- maybe add plugin review feed widget ---
    2553         if (!$pluginreviewloaded) {
    2554             wp_add_dashboard_widget('pluginreview', 'Plugin Review Network', 'wqhelper_pluginreview_feed_widget');
     3153        if ( !$pluginreviewloaded ) {
     3154            wp_add_dashboard_widget( 'pluginreview', 'Plugin Review Network', 'wqhelper_pluginreview_feed_widget' );
    25553155        }
    25563156
    25573157        // --- enqueue dashboard feed javascript ---
    2558         if (!has_action('admin_footer', 'wqhelper_dashboard_feed_javascript')) {
    2559             add_action('admin_footer', 'wqhelper_dashboard_feed_javascript');
     3158        if ( !has_action( 'admin_footer', 'wqhelper_dashboard_feed_javascript' ) ) {
     3159            add_action( 'admin_footer', 'wqhelper_dashboard_feed_javascript' );
    25603160        }
    25613161    }
     
    25663166// WordQuest Dashboard Feed Javascript
    25673167// -----------------------------------
    2568 $funcname = 'wqhelper_dashboard_feed_javascript_'.$wqhv;
    2569 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     3168$funcname = 'wqhelper_dashboard_feed_javascript_' . $wqhv;
     3169if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    25703170 $wqfunctions[$funcname] = function() {
    2571     echo "<script>
    2572     function doloadfeedcat(namespace,siteurl) {
    2573         var selectelement = document.getElementById(namespace+'catselector');
    2574         var catslug = selectelement.options[selectelement.selectedIndex].value;
    2575         var siteurl = encodeURIComponent(siteurl);
    2576         document.getElementById('feedcatloader').src='admin-ajax.php?action=wqhelper_load_feed_category&category='+catslug+'&namespace='+namespace+'&siteurl='+siteurl;
     3171    // 1.8.0: added get admin AJAX URL
     3172    $adminajax = admin_url( 'admin-ajax.php' );
     3173    // 1.8.0: removed siteurl from function for security
     3174    echo "<script>function wq_load_feed_cat(site) {
     3175        selectelement = document.getElementById(site+'catselector');
     3176        catslug = selectelement.options[selectelement.selectedIndex].value;
     3177        url = '" . esc_url( $adminajax ) . "?action=wqhelper_load_feed_category&category='+catslug+'&site='+site;
     3178        document.getElementById('feedcatloader').src = url;
     3179       
    25773180    }</script>";
    2578     echo "<iframe src='javascript:void(0);' id='feedcatloader' style='display:none;'></iframe>";
     3181    echo '<iframe src="javascript:void(0);" id="feedcatloader" style="display:none;"></iframe>';
    25793182 };
    25803183}
     
    25833186// WordQuest Dashboard Feed Widget
    25843187// -------------------------------
    2585 $funcname = 'wqhelper_dashboard_feed_widget_'.$wqhv;
    2586 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     3188$funcname = 'wqhelper_dashboard_feed_widget_' . $wqhv;
     3189if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    25873190 $wqfunctions[$funcname] = function() {
    25883191
     
    25913194    global $wqdebug, $wqreleases, $wqurls;
    25923195    $latestrelease = $nextrelease = '';
    2593     if (isset($wqreleases)) {
    2594         if (isset($wqreleases['latest'])) {$latestrelease = $wqreleases['latest'];}
    2595         if (isset($wqreleases['next'])) {$nextrelease = $wqreleases['next'];}
     3196
     3197    if ( isset( $wqreleases ) ) {
     3198        if ( isset( $wqreleases['latest'] ) ) {
     3199            $latestrelease = $wqreleases['latest'];
     3200        }
     3201        if ( isset( $wqreleases['next'] ) ) {
     3202            $nextrelease = $wqreleases['next'];
     3203        }
    25963204    } else {
    25973205        $pluginsinfo = wqhelper_get_plugin_info();
    2598         if (is_array($pluginsinfo)) {
    2599             foreach ($pluginsinfo as $plugin) {
    2600                 if (isset($plugin['slug'])) {
    2601                     if ( (isset($plugin['latestrelease']) && ($plugin['latestrelease'] == 'yes'))
    2602                       || (isset($plugin['nextrelease']) && ($plugin['nextrelease'] == 'yes')) ) {
    2603                         $plugininfo = $plugin; $plugins = get_plugins(); $plugininfo['installed'] = 'no';
    2604                         foreach ($plugins as $pluginfile => $values) {
    2605                             if ($plugininfo['slug'] == sanitize_title($values['Name'])) {$plugininfo['installed'] = 'yes';}
     3206        if ( is_array( $pluginsinfo ) ) {
     3207            foreach ( $pluginsinfo as $plugin ) {
     3208                if ( isset( $plugin['slug'] ) ) {
     3209                    if ( ( isset( $plugin['latestrelease'] ) && ( 'yes' == $plugin['latestrelease'] ) )
     3210                      || ( isset( $plugin['nextrelease'] ) && ( 'yes' == $plugin['nextrelease'] ) ) ) {
     3211                        $plugininfo = $plugin;
     3212                        $plugins = get_plugins();
     3213                        $plugininfo['installed'] = 'no';
     3214                        foreach ( $plugins as $pluginfile => $values ) {
     3215                            if ( sanitize_title( $values['Name'] ) == $plugininfo['slug'] ) {
     3216                                $plugininfo['installed'] = 'yes';
     3217                            }
    26063218                        }
    26073219                    }
    2608                     if (isset($plugin['latestrelease']) && ($plugin['latestrelease'] == 'yes')) {$latestrelease = $plugininfo;}
    2609                     if (isset($plugin['nextrelease']) && ($plugin['nextrelease'] == 'yes')) {$nextrelease = $plugininfo;}
    2610                 }
    2611             }
    2612         }
    2613     }
    2614     // echo "<!-- Latest Release: "; print_r($latestrelease); echo " -->";
    2615     // echo "<!-- Next Release: "; print_r($nextrelease); echo " -->";
     3220                    if ( isset( $plugin['latestrelease'] ) && ( 'yes' == $plugin['latestrelease'] ) ) {
     3221                        $latestrelease = $plugininfo;
     3222                    }
     3223                    if ( isset( $plugin['nextrelease'] ) && ( 'yes' == $plugin['nextrelease'] ) ) {
     3224                        $nextrelease = $plugininfo;
     3225                    }
     3226                }
     3227            }
     3228        }
     3229    }
     3230    // echo "<!-- Latest Release: " . print_r( $latestrelease, true ) . " -->";
     3231    // echo "<!-- Next Release: " . print_r( $nextrelease, true ) . " -->";
    26163232
    26173233    // maybe Display Latest Release Info
    26183234    // ---------------------------------
    2619     if (isset($_REQUEST['page']) && ($_REQUEST['page'] == 'wordquest')) {
     3235    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     3236    if ( isset( $_REQUEST['page'] ) && ( 'wordquest' == sanitize_title( $_REQUEST['page'] ) ) ) {
     3237
    26203238        // --- do not duplicate here as already output for wordquest page ---
    2621     } elseif (isset($latestrelease) && is_array($latestrelease) && ($latestrelease['installed'] == 'no')) {
    2622 
    2623         echo "<b>".wqhelper_translate('Latest Plugin Release')."</b><br>";
    2624         echo "<table><tr><td align='center'><img src='".$latestrelease['icon']."' width='75' height='75'><br>";
    2625         echo "<a href='".$latestrelease['home']."' target=_blank><b>".$latestrelease['title']."</b></a></td>";
    2626         echo "<td width='10'></td><td><span style='font-size:9pt;'>".$latestrelease['description']."</span><br><br>";
    2627 
    2628         if (isset($latestrelease['package']) && is_array($latestrelease['package'])) {
    2629 
    2630             // 1.6.6: check for wordpress.org only installs
    2631             global $wordpressorgonly; $installlink = false;
    2632             if ($wordpressorgonly && $wqplugin['wporgslug']) {
    2633                 $installlink = self_admin_url('update.php')."?action=install-plugin&plugin=".$latestrelease['wporgslug'];
    2634                 $installlink = wp_nonce_url($installlink, 'install-plugin_'.$latestrelease['wporgslug']);
    2635             } else {
    2636                 admin_url('update.php').'?action=wordquest_plugin_install&plugin='.$latestrelease['slug'];
    2637                 $installlink = wp_nonce_url($installlink, 'plugin-upload');
    2638             }
    2639             if ($installlink) {
    2640                 echo "<input type='hidden' name='".$latestrelease['slug']."-install-link' value='".$installlink."'>";
    2641                 echo "<center><a href='".$installlink."' class='button-primary'>".wqhelper_translate('Install Now')."</a></center>";
    2642             } else {
    2643                 $pluginlink = $wqurls['wq'].'/plugins/'.$latestrelease['slug'];
    2644                 echo "<center><a href='".$pluginlink."' class='button-primary' target=_blank>&rarr; ".wqhelper_translate('Plugin Home')."</a></center>";
    2645             }
    2646         }
    2647         echo "</td></tr></table><br>";
    2648 
    2649     } elseif (isset($nextrelease) && is_array($nextrelease)) {
    2650 
    2651         echo "<b>".wqhelper_translate('Upcoming Plugin Release')."</b><br>";
    2652         echo "<table><tr><td align='center'><img src='".$nextrelease['icon']."' width='75' height='75'><br>";
    2653         echo "<a href='".$nextrelease['home']."' target=_blank><b>".$nextrelease['title']."</b></a></td>";
    2654         echo "<td width='10'></td><td><span style='font-size:9pt;'>".$nextrelease['description']."</span><br><br>";
    2655         $releasetime = strtotime($nextrelease['releasedate']);
    2656         echo "<center><span style='font-size:9pt;'>".wqhelper_translate('Expected').": ".date('jS F Y', $releasetime)."</span></center>";
    2657         echo "</td></tr></table><br>";
     3239        echo '';
     3240
     3241    } elseif ( isset( $latestrelease ) && is_array( $latestrelease ) && ( 'no' == $latestrelease['installed'] ) ) {
     3242
     3243        echo '<b>' . esc_html( wqhelper_translate( 'Latest Plugin Release' ) ) . '</b><br>';
     3244        echo '<table><tr><td align="center">';
     3245            echo '<img src="' . esc_url( $latestrelease['icon'] ) . '" width="75" height="75" alt="' . esc_attr( wqhelper_translate( 'Latest Release Icon' ) ) . '"><br>';
     3246            echo '<a href="' . esc_url( $latestrelease['home'] ) . '" target="_blank"><b>' . esc_html( $latestrelease['title'] ) . '</b></a>';
     3247        echo '</td><td width="10"></td><td>';
     3248            echo '<span style="font-size:9pt;">' . esc_html( $latestrelease['description'] ) . '</span><br><br>';
     3249
     3250            if ( isset( $latestrelease['package'] ) && is_array( $latestrelease['package'] ) ) {
     3251
     3252                // 1.6.6: check for wordpress.org only installs
     3253                global $wq_wordpress_org;
     3254                $installlink = false;
     3255                // 1.8.0: fix to variable typo (wqplugin)
     3256                if ( $wq_wordpress_org && $latestrelease['wporgslug'] ) {
     3257                    $installlink = self_admin_url( 'update.php' ) . '?action=install-plugin&plugin=' . $latestrelease['wporgslug'];
     3258                    $installlink = wp_nonce_url( $installlink, 'install-plugin_' . $latestrelease['wporgslug'] );
     3259                } else {
     3260                    // 1.8.0: fix to missing left hand side variable installlink
     3261                    $installlink = admin_url( 'update.php' ) . '?action=wordquest_plugin_install&plugin=' . $latestrelease['slug'];
     3262                    $installlink = wp_nonce_url( $installlink, 'plugin-upload' );
     3263                }
     3264                if ( $installlink ) {
     3265                    echo '<input type="hidden" name="' . esc_attr( $latestrelease['slug'] ) . '-install-link" value="' . esc_url( $installlink ) . '">';
     3266                    echo '<center><a href="' . esc_url( $installlink ) . '" class="button-primary">' . esc_html( wqhelper_translate( 'Install Now' ) ) . '</a></center>';
     3267                } else {
     3268                    $pluginlink = $wqurls['wq'] . '/plugins/' . $latestrelease['slug'];
     3269                    echo '<center><a href="' . esc_url( $pluginlink ) . '" class="button-primary" target="_blank">&rarr; ' . esc_html( wqhelper_translate( 'Plugin Home' ) ) . '</a></center>';
     3270                }
     3271            }
     3272
     3273        echo '</td></tr></table><br>';
     3274
     3275    } elseif ( isset( $nextrelease ) && is_array( $nextrelease ) ) {
     3276
     3277        echo '<b>' . esc_html( wqhelper_translate( 'Upcoming Plugin Release' ) ) . '</b><br>';
     3278        echo '<table><tr><td align="center">';
     3279            echo '<img src="' . esc_url( $nextrelease['icon'] ) . '" width="75" height="75"alt="' . esc_attr( wqhelper_translate( 'Next Release Icon' ) ) . '"><br>';
     3280            echo '<a href="' . esc_url( $nextrelease['home'] ) . '" target="_blank"><b>' . esc_html( $nextrelease['title'] ) . '</b></a>';
     3281        echo '</td><td width="10"></td><td><span style="font-size:9pt;">' . esc_html( $nextrelease['description'] ) . '</span><br><br>';
     3282        $releasetime = strtotime( $nextrelease['releasedate'] );
     3283        echo '<center><span style="font-size:9pt;">' . esc_html( wqhelper_translate( 'Expected' ) ) . ': ' . esc_html( date( 'jS F Y', $releasetime ) ) . '</span></center>';
     3284        echo '</td></tr></table><br>';
    26583285
    26593286    }
     
    26643291    // WordQuest Posts Feed
    26653292    // --------------------
    2666     $rssurl = $wqurls['wq']."/category/guides/feed/";
    2667     if ($wqdebug) {$feed = ''; delete_transient('wordquest_guides_feed');}
    2668     else {$feed = trim(get_transient('wordquest_guides_feed'));}
     3293    $rssurl = $wqurls['wq'] . '/category/guides/feed/';
     3294    if ( $wqdebug ) {
     3295        $feed = '';
     3296        delete_transient( 'wordquest_guides_feed' );
     3297    } else {
     3298        $feed = trim( get_transient( 'wordquest_guides_feed' ) );
     3299    }
    26693300
    26703301    // --- fetch posts feed ---
    2671     if (!$feed || ($feed == '')) {
    2672         $rssfeed = fetch_feed($rssurl); $feeditems = 4;
    2673         $args = array($rssfeed, $feeditems);
    2674         $feed = wqhelper_process_rss_feed($args);
    2675         if ($feed != '') {set_transient('wordquest_guides_feed', $feed, (24*60*60));}
     3302    if ( !$feed || ( '' == $feed ) ) {
     3303        $rssfeed = fetch_feed( $rssurl );
     3304        $feeditems = 4;
     3305        $args = array( $rssfeed, $feeditems );
     3306        $feed = wqhelper_process_rss_feed( $args );
     3307        if ( '' != $feed ) {
     3308            set_transient( 'wordquest_guides_feed', $feed, ( 24 * 60 * 60 ) );
     3309        }
    26763310    }
    26773311
    26783312    // --- WordQuest Guides ----
    2679     echo "<div id='wordquestguides'>";
    2680     echo "<div style='float:right;'>&rarr;<a href='".$wqurls['wq']."/category/guides/' class='feedlink' target=_blank> ".wqhelper_translate('More')."...</a></div>";
    2681     echo "<b><a href='".$wqurls['wq']."/category/guides/' class='feedlink' target=_blank>".wqhelper_translate('Latest WordQuest Guides')."</a></b><br>";
    2682     if ($feed != '') {echo $feed;} else {echo wqhelper_translate('Feed Currently Unavailable.'); delete_transient('wordquest_guides_feed');}
    2683     echo "</div>";
     3313    echo '<div id="wordquestguides">';
     3314    echo '<div style="float:right;">&rarr;<a href="' . esc_url( $wqurls['wq'] ) . '/category/guides/" class="feedlink" target="_blank"> ' . esc_html( wqhelper_translate( 'More' ) ) . '...</a></div>';
     3315    echo '<b><a href="' . esc_url( $wqurls['wq'] ) . '/category/guides/" class="feedlink" target="_blank">' . esc_html( wqhelper_translate( 'Latest WordQuest Guides' ) ) . '</a></b><br>';
     3316    if ( '' != $feed ) {
     3317        // 1.8.1: use wp_kses_post on feed output
     3318        echo wp_kses_post( $feed );
     3319    } else {
     3320        echo esc_html( wqhelper_translate( 'Feed Currently Unavailable.' ) );
     3321        delete_transient( 'wordquest_guides_feed' );
     3322    }
     3323    echo '</div>';
    26843324
    26853325    // WordQuest Solutions Feed
    26863326    // ------------------------
    2687     $rssurl = $wqurls['wq']."/quest/feed/";
    2688     if ($wqdebug) {$feed = ''; delete_transient('wordquest_quest_feed');}
    2689     else {$feed = trim(get_transient('wordquest_quest_feed'));}
     3327    $rssurl = $wqurls['wq'] . '/quest/feed/';
     3328    if ( $wqdebug ) {
     3329        $feed = '';
     3330        delete_transient( 'wordquest_quest_feed' );
     3331    } else {
     3332        $feed = trim( get_transient( 'wordquest_quest_feed' ) );
     3333    }
    26903334
    26913335    // --- fetch solutions feed ---
    2692     if (!$feed || ($feed == '')) {
    2693         $rssfeed = fetch_feed($rssurl); $feeditems = 4;
    2694         $args = array($rssfeed, $feeditems);
    2695         $feed = wqhelper_process_rss_feed($args);
    2696         if ($feed != '') {set_transient('wordquest_quest_feed', $feed, (24*60*60));}
     3336    if ( !$feed || ( '' != $feed ) ) {
     3337        $rssfeed = fetch_feed( $rssurl );
     3338        $feeditems = 4;
     3339        $args = array( $rssfeed, $feeditems );
     3340        $feed = wqhelper_process_rss_feed( $args );
     3341        if ( '' != $feed ) {
     3342            set_transient( 'wordquest_quest_feed', $feed, ( 24 * 60 * 60 ) );
     3343        }
    26973344    }
    26983345
    26993346    // --- output solutions feed ---
    2700     echo "<div id='wordquestsolutions'>";
    2701     echo "<div style='float:right;'>&rarr;<a href='".$wqurls['wq']."/solutions/' class='feedlink' target=_blank> ".wqhelper_translate('More')."...</a></div>";
    2702     echo "<b><a href='".$wqurls['wq']."/solutions/' class='feedlink' target=_blank>".wqhelper_translate('Latest Solution Quests')."</a></b>";
    2703     if ($feed != '') {echo $feed;} else {echo wqhelper_translate('Feed Currently Unavailable.'); delete_transient('wordquest_quest_feed');}
    2704     echo "</div>";
     3347    echo '<div id="wordquestsolutions">';
     3348    echo '<div style="float:right;">&rarr;<a href="' . esc_url( $wqurls['wq'] ) . '/solutions/" class="feedlink" target="_blank"> ' . esc_html( wqhelper_translate( 'More' ) ) . '...</a></div>';
     3349    echo '<b><a href="' . esc_url( $wqurls['wq'] ) . '/solutions/" class="feedlink" target="_blank">' . esc_html( wqhelper_translate( 'Latest Solution Quests' ) ) . '</a></b><br>';
     3350    if ( '' != $feed ) {
     3351        // 1.8.1: use wp_kses_post on feed output
     3352        echo wp_kses_post( $feed );
     3353    } else {
     3354        echo esc_html( wqhelper_translate( 'Feed Currently Unavailable.' ) );
     3355        delete_transient( 'wordquest_quest_feed' );
     3356    }
     3357    echo '</div>';
    27053358
    27063359    return;
    27073360
    2708     // --------------------------
    2709     // currently not implented...
    2710 
     3361    // -----------------------
    27113362    // Category Feed Selection
    27123363    // -----------------------
    2713     $pluginsurl = $wqurls['wq']."/?get_post_categories=yes";
    2714 
    2715     if ($wqdebug) {$categorylist = ''; delete_transient('wordquest_feed_cats');}
    2716     else {$categorylist = trim(get_transient('wordquest_feed_cats'));}
    2717 
    2718     if (!$categorylist || ($categorylist == '')) {
    2719         $args = array('timeout' => 10);
    2720         $getcategorylist = wp_remote_get($pluginsurl, $args);
    2721         if (!is_wp_error($getcategorylist)) {
     3364    // [currently not implented...]
     3365
     3366    /* $pluginsurl = $wqurls['wq'] . '/?get_post_categories=yes';
     3367
     3368    if ( $wqdebug ) {
     3369        $categorylist = '';
     3370        delete_transient( 'wordquest_feed_cats' );
     3371    } else {
     3372        $categorylist = trim( get_transient( 'wordquest_feed_cats' ) );
     3373    }
     3374
     3375    if ( !$categorylist || ( '' == $categorylist ) ) {
     3376        $args = array( 'timeout' => 10 );
     3377        $getcategorylist = wp_remote_get( $pluginsurl, $args );
     3378        if ( !is_wp_error( $getcategorylist ) ) {
    27223379            $categorylist = $getcategorylist['body'];
    2723             if ($categorylist) {set_transient('wordquest_feed_cats', $categorylist, (24*60*60));}
    2724         }
    2725     }
    2726 
    2727     if (strstr($categorylist, "::::")) {
    2728         $categories = explode("::::", $categorylist);
    2729         if (count($categories) > 0) {
     3380            if ( $categorylist ) {
     3381                set_transient( 'wordquest_feed_cats', $categorylist, ( 24 * 60 * 60 ) );
     3382            }
     3383        }
     3384    }
     3385
     3386    if ( strstr( $categorylist, '::::' ) ) {
     3387        $categories = explode( '::::', $categorylist );
     3388        if ( count( $categories ) > 0 ) {
    27303389            $i = 0;
    2731             foreach ($categories as $category) {
    2732                 $catinfo = explode("::", $category);
     3390            foreach ( $categories as $category ) {
     3391                $catinfo = explode( '::', $category );
    27333392                $cats[$i]['name'] = $catinfo[0];
    27343393                $cats[$i]['slug'] = $catinfo[1];
     
    27373396            }
    27383397
    2739             if (count($cats) > 0) {
    2740                 echo "<table><tr><td><b>".wqhelper_translate('Category').":</b></td>";
    2741                 echo "<td width='7'></td>";
    2742                 echo "<td><select id='wqcatselector' onchange='doloadfeedcat(\"wq\",\"".$wqurls['wq']."\");'>";
    2743                 // echo "<option value='news' selected='selected'>WordQuest News</option>";
    2744                 foreach ($cats as $cat) {
    2745                     echo "<option value='".$cat['slug']."'";
    2746                         if ($cat['slug'] == 'news') {echo " selected='selected'";}
    2747                     echo ">".$cat['name']." (".$cat['count'].")</option>";
    2748                 }
    2749                 echo "</select></td></tr></table>";
    2750                 echo "<div id='wqfeeddisplay'></div>";
    2751             }
    2752         }
    2753     }
     3398            if ( count( $cats ) > 0 ) {
     3399                echo '<table><tr><td>';
     3400                    echo '<b>' . esc_html( wqhelper_translate( 'Category' ) ) . ':</b>';
     3401                    echo '</td><td width="7"></td><td>';
     3402                        echo '<select id="wqcatselector" onchange="wq_load_feed_cat(\'wq\',\'' . esc_url( $wqurls['wq'] ) . '\');">';
     3403                // echo '<option value="news" selected="selected">WordQuest News</option>';
     3404                foreach ( $cats as $cat ) {
     3405                    echo '<option value="' . esc_attr( $cat['slug'] ) . '"';
     3406                    if ( 'news' == $cat['slug'] ) {
     3407                        echo " selected='selected'";
     3408                    }
     3409                    echo '>' . esc_html( $cat['name'] ) . ' (' . esc_html( $cat['count'] ) . ')</option>';
     3410                }
     3411                echo '</select></td></tr></table>';
     3412                echo '<div id="wqfeeddisplay"></div>';
     3413            }
     3414        }
     3415    } */
    27543416 };
    27553417}
     
    27583420// Plugin Review Network Feed Widget
    27593421// ---------------------------------
    2760 $funcname = 'wqhelper_pluginreview_feed_widget_'.$wqhv;
    2761 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     3422$funcname = 'wqhelper_pluginreview_feed_widget_' . $wqhv;
     3423if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    27623424 $wqfunctions[$funcname] = function() {
    27633425
     
    27683430    // -------------------
    27693431    global $wqdebug, $wqurls;
    2770     $rssurl = $wqurls['prn']."/feed/";
    2771     if ($wqdebug) {$feed = ''; delete_transient('pluginreview_newest_feed');}
    2772     else {$feed = trim(get_transient('pluginreview_newest_feed'));}
     3432    $rssurl = $wqurls['prn'] . '/feed/';
     3433    if ( $wqdebug ) {
     3434        $feed = '';
     3435        delete_transient( 'pluginreview_newest_feed' );
     3436    } else {
     3437        $feed = trim( get_transient( 'pluginreview_newest_feed' ) );
     3438    }
    27733439
    27743440    // --- fetch new plugins feed ---
    2775     if (!$feed || ($feed == '')) {
    2776         $rssfeed = fetch_feed($rssurl); $feeditems = 4;
    2777         $args = array($rssfeed, $feeditems);
    2778         $feed = wqhelper_process_rss_feed($args);
    2779         if ($feed != '') {set_transient('pluginreview_newest_feed', $feed, (24*60*60));}
    2780     }
    2781 
    2782     echo "<center><b><a href='".$wqurls['prn']."/directory/' class='feedlink' style='font-size:11pt;' target=_blank>";
    2783     echo wqhelper_translate('NEW', 'bioship').' '.wqhelper_translate('Plugin Directory')." - ".wqhelper_translate('by Category')."!</a></b></center><br>";
    2784     echo "<div id='pluginslatest'>";
     3441    if ( !$feed || ( '' == $feed ) ) {
     3442        $rssfeed = fetch_feed( $rssurl );
     3443        $feeditems = 4;
     3444        $args = array( $rssfeed, $feeditems );
     3445        $feed = wqhelper_process_rss_feed( $args );
     3446        if ( '' != $feed ) {
     3447            set_transient( 'pluginreview_newest_feed', $feed, ( 24 * 60 * 60 ) );
     3448        }
     3449    }
     3450
     3451    echo '<center><b><a href="' . esc_url( $wqurls['prn'] ) . '/directory/" class="feedlink" style="font-size:11pt;" target="_blank">';
     3452    echo esc_html( wqhelper_translate( 'NEW' ) ) . ' ';
     3453    echo esc_html( wqhelper_translate( 'Plugin Directory' ) ) . ' - ';
     3454    echo esc_html( wqhelper_translate( 'by Category' ) ) . '!</a></b></center><br>';
     3455    echo '<div id="pluginslatest">';
    27853456
    27863457    // --- ouput latest plugins feed ---
    2787     echo "<div style='float:right;'>&rarr;<a href='".$wqurls['prn']."/directory/latest/' class='feedlink' target=_blank> ".wqhelper_translate('More')."...</a></div>";
    2788     if ($feed != '') {echo "<b>".wqhelper_translate('Latest Plugin Releases')."</b><br>".$feed;}
    2789     else {echo wqhelper_translate('Feed Currently Unavailable'); delete_transient('prn_feed');}
    2790     echo "</div>";
     3458    echo '<div style="float:right;">&rarr;<a href="' . esc_url( $wqurls['prn'] ) . '/directory/latest/" class="feedlink" target="_blank"> ' . esc_html( wqhelper_translate( 'More' ) ) . '...</a></div>';
     3459    if ( '' != $feed ) {
     3460        echo '<b>' . esc_html( wqhelper_translate( 'Latest Plugin Releases' ) ) . '</b><br>';
     3461        // 1.8.1: use wp_kses_post on feed output
     3462        echo wp_kses_post( $feed );
     3463    } else {
     3464        echo esc_html( wqhelper_translate( 'Feed Currently Unavailable' ) );
     3465        delete_transient( 'prn_feed' );
     3466    }
     3467    echo '</div>';
    27913468
    27923469    // Recently Updated Feed
    27933470    // ---------------------
    2794     $rssurl = $wqurls['prn']."/feed/?orderby=modified";
    2795     if ($wqdebug) {$feed = ''; delete_transient('pluginreview_updated_feed');}
    2796     else {$feed = trim(get_transient('pluginreview_updated_feed'));}
     3471    $rssurl = $wqurls['prn'] . '/feed/?orderby=modified';
     3472    if ( $wqdebug ) {
     3473        $feed = '';
     3474        delete_transient( 'pluginreview_updated_feed' );
     3475    } else {
     3476        $feed = trim( get_transient( 'pluginreview_updated_feed' ) );
     3477    }
    27973478
    27983479    // --- fetch recently updated feed ---
    2799     if (!$feed || ($feed == '')) {
    2800         $rssfeed = fetch_feed($rssurl); $feeditems = 4;
    2801         $args = array($rssfeed, $feeditems);
    2802         $feed = wqhelper_process_rss_feed($args);
    2803         if ($feed != '') {set_transient('pluginreview_updated_feed', $feed, (24*60*60));}
     3480    if ( !$feed || ( '' == $feed ) ) {
     3481        $rssfeed = fetch_feed( $rssurl );
     3482        $feeditems = 4;
     3483        $args = array( $rssfeed, $feeditems );
     3484        $feed = wqhelper_process_rss_feed( $args );
     3485        if ( '' != $feed ) {
     3486            set_transient( 'pluginreview_updated_feed', $feed, ( 24 * 60 * 60 ) );
     3487        }
    28043488    }
    28053489
    28063490    // --- output recently updated feed ---
    2807     echo "<div id='pluginsupdated'>";
    2808     echo "<div style='float:right;'>&rarr;<a href='".$wqurls['prn']."/directory/updated/' class='feedlink' target=_blank> ".wqhelper_translate('More')."...</a></div>";
    2809     if ($feed != '') {echo "<b>".wqhelper_translate('Recently Updated Plugins')."</b><br>".$feed;}
    2810     else {echo wqhelper_translate('Feed Currently Unavailable'); delete_transient('prn_feed');}
    2811     echo "</div>";
     3491    echo '<div id="pluginsupdated">';
     3492    echo '<div style="float:right;">&rarr;<a href="' . esc_url( $wqurls['prn'] ) . '/directory/updated/" class="feedlink" target="_blank"> ' . esc_html( wqhelper_translate( 'More' ) ) . '...</a></div>';
     3493    if ( '' != $feed ) {
     3494        echo '<b>' . esc_html( wqhelper_translate( 'Recently Updated Plugins' ) ) . '</b><br>';
     3495        // 1.8.1: use wp_kses_post on feed output
     3496        echo wp_kses_post( $feed );
     3497    } else {
     3498        echo esc_html( wqhelper_translate( 'Feed Currently Unavailable' ) );
     3499        delete_transient( 'prn_feed' );
     3500    }
     3501    echo '</div>';
    28123502
    28133503    return;
    28143504
    2815     // --------------------------
    2816     // currently not implented...
    2817 
     3505    // -----------------------
    28183506    // Category Feed Selection
    28193507    // -----------------------
    2820     $categoryurl = $wqurls['prn']."/?get_review_categories=yes";
     3508    // [currently not implented...]
     3509
     3510    /* $categoryurl = $wqurls['prn'] . '/?get_review_categories=yes';
    28213511
    28223512    // refresh once a day only to limit downloads
    2823     if ($wqdebug) {$categorylist = ''; delete_transient('prn_feed_cats');}
    2824     else {$categorylist = trim(get_transient('prn_feed_cats'));}
    2825 
    2826     if (!$categorylist || ($categorylist == '')) {
    2827         $args = array('timeout' => 10);
    2828         $getcategorylist = wp_remote_get($categoryurl, $args);
    2829         if (!is_wp_error($getcategorylist)) {
     3513    if ( $wqdebug ) {
     3514        $categorylist = '';
     3515        delete_transient('prn_feed_cats');
     3516    } else {
     3517        $categorylist = trim( get_transient( 'prn_feed_cats' ) );
     3518    }
     3519
     3520    if ( !$categorylist || ( '' == $categorylist ) ) {
     3521        $args = array( 'timeout' => 10 );
     3522        $getcategorylist = wp_remote_get( $categoryurl, $args );
     3523        if ( !is_wp_error( $getcategorylist ) ) {
    28303524            $categorylist = $getcategorylist['body'];
    2831             if ($categorylist) {set_transient('prn_feed_cats', $categorylist, (24*60*60));}
    2832         }
    2833     }
    2834 
    2835     if (strstr($categorylist, "::::")) {
    2836         $categories = explode("::::", $categorylist);
    2837         if (count($categories) > 0) {
     3525            if ( $categorylist ) {
     3526                set_transient( 'prn_feed_cats', $categorylist, ( 24 * 60 * 60 ) );
     3527            }
     3528        }
     3529    }
     3530
     3531    if ( strstr( $categorylist, '::::' ) ) {
     3532        $categories = explode( '::::', $categorylist );
     3533        if ( count( $categories) > 0 ) {
    28383534            $i = 0;
    2839             foreach ($categories as $category) {
    2840                 $catinfo = explode("::", $category);
     3535            foreach ( $categories as $category ) {
     3536                $catinfo = explode( '::', $category);
    28413537                $cats[$i]['name'] = $catinfo[0];
    28423538                $cats[$i]['slug'] = $catinfo[1];
     
    28453541            }
    28463542
    2847             if (count($cats) > 0) {
    2848                 echo "<table><tr><td><b>".wqhelper_translate('Category').":</b></td>";
    2849                 echo "<td width='7'></td>";
    2850                 echo "<td><select id='prncatselector' onchange='doloadfeedcat(\"prn\",\"".$wqurls['prn']."\");'>";
    2851                 // echo "<option value='reviews' selected='selected'>".wqhelper_translate('Plugin Reviews')."</option>";
    2852                 foreach ($cats as $cat) {
    2853                     echo "<option value='".$cat['slug']."'";
    2854                         if ($cat['slug'] == 'reviews') {echo " selected='selected'";}
    2855                     echo ">".$cat['name']." (".$cat['count'].")</option>";
    2856                 }
    2857                 echo "</select></td></tr></table>";
    2858                 echo "<div id='prnfeeddisplay'></div>";
    2859             }
    2860         }
    2861     }
     3543            if ( count( $cats ) > 0 ) {
     3544                echo '<table><tr><td>';
     3545                    echo '<b>' . esc_html( wqhelper_translate( 'Category' ) ) . ':</b>';
     3546                echo '</td><td width="7"></td><td>';
     3547                    echo "<select id='prncatselector' onchange='wq_load_feed_cat(\"prn\",\"".$wqurls['prn']."\");'>";
     3548                    // echo "<option value='reviews' selected='selected'>".wqhelper_translate('Plugin Reviews')."</option>";
     3549                    foreach ( $cats as $cat ) {
     3550                        echo '<option value="' . esc_attr( $cat['slug'] ) . '"';
     3551                        if ( 'reviews' == $cat['slug'] ) {
     3552                            echo ' selected="selected"';
     3553                        }
     3554                        echo '>' . esc_html( $cat['name'] ) . ' (' . esc_html( $cat['count'] ) . ')</option>';
     3555                    }
     3556                    echo '</select>';
     3557                echo '</td></tr></table>';
     3558                echo '<div id="prnfeeddisplay"></div>';
     3559            }
     3560        }
     3561    } */
    28623562 };
    28633563}
     
    28663566// Load a Category Feed
    28673567// --------------------
    2868 $funcname = 'wqhelper_load_feed_category_'.$wqhv;
    2869 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
     3568$funcname = 'wqhelper_load_feed_category_' . $wqhv;
     3569if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
    28703570 $wqfunctions[$funcname] = function() {
    28713571
    2872     $namespace = $_GET['namespace'];
    2873     $baseurl = $_GET['siteurl'];
    2874     $catslug = $_GET['category'];
    2875 
    2876     $categoryurl = $baseurl."/category/".$catslug."/feed/";
    2877     $morelink = "<div align='right'>&rarr; <a href='".$baseurl."/category/".$catslug."/' style='feedlink' target=_blank> More...</a></div>";
     3572    global $wqurls;
     3573    // 1.8.0: remove siteurl usage and validate site key instead
     3574    // 1.8.1: use sanitize_title on request value
     3575    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     3576    $site = sanitize_title( $_GET['site'] );
     3577    if ( !array_key_exists( $site, $wqurls ) ) {
     3578        return;
     3579    }
     3580    $baseurl = $wqurls[$site];
     3581
     3582    // 1.8.0: use sanitize_title_ on category slug
     3583    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     3584    $catslug = sanitize_title( $_GET['category'] );
     3585    $categoryurl = $baseurl . '/category/' . $catslug . '/feed/';
     3586
     3587    // 1.8.0: set separate URL and use esc_url
     3588    $moreurl = $baseurl . '/category/' . $catslug . '/';
     3589    $morelink = '<div align="right">&rarr; <a href="' . esc_url( $moreurl ) . '" style="feedlink" target="_blank"> ' . esc_html( wqhelper_translate( 'More' ) ) . '...</a></div>';
    28783590
    28793591    // --- fetch the category feed ---
    2880     $categoryrss = @fetch_feed($categoryurl); $feeditems = 10;
     3592    $categoryrss = fetch_feed( $categoryurl );
     3593    $feeditems = 10;
    28813594
    28823595    // --- Process the Category Feed ---
    2883     $args = array($categoryrss, $feeditems);
    2884     $categoryfeed = wqhelper_process_rss_feed($args);
    2885     if ($categoryfeed != '') {$categoryfeed .= $morelink;}
     3596    $args = array( $categoryrss, $feeditems );
     3597    $categoryfeed = wqhelper_process_rss_feed( $args );
     3598    if ( '' != $categoryfeed ) {
     3599        $categoryfeed .= $morelink;
     3600    }
    28863601
    28873602    // --- send back to parent window ---
    2888     echo '<script language="javascript" type="text/javascript">
    2889     var categoryfeed = "'.$categoryfeed.'";
    2890     parent.document.getElementById("'.$namespace.'feeddisplay").innerHTML = categoryfeed;
    2891     </script>';
     3603    // 1.8.0: added missing esc_js wrappers on variables
     3604    echo "<script>categoryfeed = '" . esc_js( $categoryfeed ) . "';
     3605    parent.document.getElementById('" . esc_js( site ) . "feeddisplay').innerHTML = categoryfeed;
     3606    </script>";
    28923607
    28933608    exit;
     
    28983613// Process RSS Feed
    28993614// ----------------
    2900 $funcname = 'wqhelper_process_rss_feed_'.$wqhv;
    2901 if (!isset($wqfunctions[$funcname]) || !is_callable($wqfunctions[$funcname])) {
    2902  $wqfunctions[$funcname] = function($args) {
    2903 
    2904     $rss = $args[0]; $feeditems = $args[1]; $processed = '';
    2905     if (is_wp_error($rss)) {return '';}
    2906 
    2907     $maxitems = $rss->get_item_quantity($feeditems);
    2908     $rssitems = $rss->get_items(0, $maxitems);
    2909 
    2910     if ($maxitems == 0) {$processed = '';}
    2911     else {
     3615$funcname = 'wqhelper_process_rss_feed_' . $wqhv;
     3616if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     3617 $wqfunctions[$funcname] = function( $args ) {
     3618
     3619    $rss = $args[0];
     3620    $feeditems = $args[1];
     3621    $processed = '';
     3622    if ( is_wp_error( $rss ) ) {
     3623        return '';
     3624    }
     3625
     3626    $maxitems = $rss->get_item_quantity( $feeditems );
     3627    $rssitems = $rss->get_items( 0, $maxitems );
     3628
     3629    if ( 0 == $maxitems ) {
     3630        $processed = '';
     3631    } else {
    29123632        // --- create feed list item display ---
    2913         $processed = "<ul style='list-style:none;margin:0;text-align:left;'>";
    2914         foreach ($rssitems as $item) {
    2915             $processed .= "<li>&rarr; <a href='".esc_url($item->get_permalink())."' class='feedlink' target='_blank' ";
    2916             $processed .= "title='Posted ".$item->get_date('j F Y | g:i a')."'>";
    2917             $processed .= esc_html($item->get_title())."</a></li>";
    2918         }
    2919         $processed .= "</ul>";
     3633        $processed = '<ul style="list-style:none;margin:0;text-align:left;">';
     3634        foreach ( $rssitems as $item ) {
     3635            $processed .= '<li>&rarr; <a href="' . esc_url( $item->get_permalink() ) . '" class="feedlink" target="_blank"';
     3636            $processed .= ' title="Posted ' . esc_attr( $item->get_date( 'j F Y | g:i a' ) ) . '">';
     3637            $processed .= esc_html( $item->get_title() ) . '</a></li>';
     3638        }
     3639        $processed .= '</ul>';
    29203640    }
    29213641    return $processed;
     
    29233643}
    29243644
     3645// -----------
     3646// Get Feed Ad
     3647// -----------
     3648// 1.8.0: get ad via feed
     3649$funcname = 'wqhelper_get_feed_ad_' . $wqhv;
     3650if ( !isset( $wqfunctions[$funcname] ) || !is_callable( $wqfunctions[$funcname] ) ) {
     3651 $wqfunctions[$funcname] = function( $pluginslug ) {
     3652
     3653    global $wqurls;
     3654    $feedurl = $wqurls['prn'] . '/recommends/?s=1&f=1&c=' . esc_attr( $pluginslug ) . '&t=sidebar';
     3655    add_filter( 'wp_feed_cache_transient_lifetime', 'wqhelper_ad_feed_interval' );
     3656    $rss = fetch_feed( $feedurl );
     3657    remove_filter( 'wp_feed_cache_transient_lifetime', 'wqhelper_ad_feed_interval' );
     3658    if ( !$rss || is_wp_error( $rss ) ) {
     3659        return '';
     3660    }
     3661    $rssitems = $rss->get_items( 0, 1 );
     3662    $item = $rssitems[0];
     3663    return $item->get_content();
     3664 };
     3665}
     3666
     3667// ----------------------
     3668// Ad Feed Cache Interval
     3669// ----------------------
     3670// 1.8.0: added for ad feed interval
     3671if ( !function_exists( 'wqhelper_ad_feed_interval' ) ) {
     3672 function wqhelper_ad_feed_interval( $seconds ) {
     3673    // --- change feed interval ---
     3674    return 300;
     3675 }
     3676}
     3677
     3678
    29253679// --- manual function list debug point ---
    2926 // add_action('plugins_loaded', function() {
    2927 //  echo "<!-- WQ Helper Functions: ".print_r($wqfunctions,true)." -->;
     3680// add_action( 'plugins_loaded', function() {
     3681//  echo "<!-- WQ Helper Functions: " . print_r( $wqfunctions, true ) . " -->";
    29283682// });
    29293683
     
    29323686// === Changelog ===
    29333687// -----------------
     3688
     3689// = 1.8.2 =
     3690// - fix to floatbox divs condition when no recommendation
     3691// - sanitize HTTP_HOST server global key
     3692
     3693// = 1.8.1 =
     3694// - improved output escaping and sanitization
     3695
     3696// = 1.8.0 =
     3697// - Fix WordPress Coding Standards sniffs
     3698// - Change from script ads to feed ads
     3699
     3700// = 1.7.9 =
     3701// - fix to Admin submenu icon styles
     3702
     3703// = 1.7.8 =
     3704// - WordPress Coding Standards redux
     3705// - added output escaping sanitization
     3706// - fix to sidebar option saving variable
     3707// - prefix javascript functions
    29343708
    29353709// = 1.7.7 =
Note: See TracChangeset for help on using the changeset viewer.