REPLACE the entire contents of widget/logic.php with the following:
<?php
if (!defined('ABSPATH')) exit; // Exit if accessed directly
/**
* Evaluate widget logic safely.
* Supports basic && and || operations with a whitelist of WP conditional functions,
* and allows extension via filter hook for custom functions.
*
* @param string|bool $logic The widget logic string or boolean.
* @return bool True if widget should display, false otherwise.
*/
function widget_logic_check_logic($logic)
{
$logic = trim((string) $logic);
// Allow external override (must return true/false)
$logic = apply_filters('widget_logic_eval_override', $logic);
if (is_bool($logic)) {
return $logic;
}
if ($logic === '') {
return true;
}
// Split by OR (||) operators
$or_parts = preg_split('/\s*\|\|\s*/', $logic);
foreach ($or_parts as $or_part) {
// Split by AND (&&) operators
$and_parts = preg_split('/\s*&&\s*/', $or_part);
$and_result = true;
foreach ($and_parts as $and_part) {
$and_part = trim($and_part);
if (!evaluate_condition($and_part)) {
$and_result = false;
break;
}
}
if ($and_result) {
return true;
}
}
return false;
}
/**
* Evaluate a single condition string.
*
* @param string $condition Single condition like is_home() or current_user_can('edit_posts').
* @return bool
*/
function evaluate_condition($condition)
{
// Match function name and optional args: functionName() or functionName('arg')
if (!preg_match('/^([a-zA-Z_][a-zA-Z0-9_]*)\s*(\(.*\))?$/', $condition, $matches)) {
return false;
}
$func = $matches[1];
$args = isset($matches[2]) ? $matches[2] : '';
// Whitelist allowed functions — filterable so themes/plugins can add more
$allowed_funcs = array(
'is_home',
'is_front_page',
'is_single',
'is_page',
'is_category',
'is_tag',
'is_archive',
'is_author',
'is_search',
'is_404',
'is_user_logged_in',
'current_user_can',
'is_active_sidebar',
);
$allowed_funcs = apply_filters('widget_logic_allowed_functions', $allowed_funcs);
if (!in_array($func, $allowed_funcs, true)) {
return false;
}
if ($args === '') {
return function_exists($func) ? $func() : false;
}
// Process args string to array
$args = trim($args, '() ');
if ($args === '') {
return function_exists($func) ? $func() : false;
}
// Split arguments respecting commas
$argList = preg_split('/\s*,\s*/', $args);
// Trim quotes and whitespace from each arg
$argList = array_map(function ($arg) {
return trim($arg, "'\" ");
}, $argList);
if (!function_exists($func)) {
return false;
}
return call_user_func_array($func, $argList);
}
/**
* Custom error handler for widget logic errors.
*
* @param int $errno
* @param string $errstr
* @return bool
*/
function widget_logic_error_handler($errno, $errstr)
{
global $wl_options;
$show_errors = !empty($wl_options['widget_logic-options-show_errors']) && current_user_can('manage_options');
if ($show_errors) {
echo 'Invalid Widget Logic: ' . esc_html($errstr);
}
return true;
}
/**
* Retrieve widget logic string for a widget ID.
*
* @param string $widget_id
* @return string
*/
function widget_logic_by_id($widget_id)
{
global $wl_options;
if (preg_match('/^(.+)-(\d+)$/', $widget_id, $m)) {
$widget_class = $m[1];
$widget_i = $m[2];
$info = get_option('widget_' . $widget_class);
if (empty($info[$widget_i])) {
return '';
}
$info = $info[$widget_i];
} else {
$info = (array) get_option('widget_' . $widget_id, array());
}
if (isset($info['widget_logic'])) {
$logic = $info['widget_logic'];
} elseif (isset($wl_options[$widget_id])) {
$logic = stripslashes($wl_options[$widget_id]);
widget_logic_save($widget_id, $logic);
unset($wl_options[$widget_id]);
update_option('widget_logic', $wl_options);
} else {
$logic = '';
}
return $logic;
}
/**
* Save widget logic string for a widget ID.
*
* @param string $widget_id
* @param string $logic
* @return void
*/
function widget_logic_save($widget_id, $logic)
{
global $wl_options;
if (preg_match('/^(.+)-(\d+)$/', $widget_id, $m)) {
$widget_class = $m[1];
$widget_i = $m[2];
$info = get_option('widget_' . $widget_class);
if (!is_array($info[$widget_i])) {
$info[$widget_i] = array();
}
$info[$widget_i]['widget_logic'] = $logic;
update_option('widget_' . $widget_class, $info);
} elseif (
isset($_POST['widget_logic_nonce'])
&& wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['widget_logic_nonce'])), 'widget_logic_save')
) {
$info = (array) get_option('widget_' . $widget_id, array());
$info['widget_logic'] = $logic;
update_option('widget_' . $widget_id, $info);
}
}