diff --git a/.github/workflows/plugin-check.yml b/.github/workflows/plugin-check.yml new file mode 100644 index 0000000..83a326f --- /dev/null +++ b/.github/workflows/plugin-check.yml @@ -0,0 +1,210 @@ +name: WordPress Plugin Check + +on: + pull_request: + types: [opened, synchronize, reopened] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + plugin-check: + name: WordPress.org Guidelines Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Composer dependencies + run: composer install --no-dev --optimize-autoloader + + - uses: wordpress/plugin-check-action@v1 + id: plugin-check + with: + categories: plugin_repo,security,performance,general + exclude-directories: | + tests + bin + .github + ignore-codes: | + WordPress.WP.I18n.TextDomainMismatch + textdomain_mismatch + hidden_files + WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound + WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound + WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound + WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound + WordPress.PHP.DevelopmentFunctions.error_log_trigger_error + WordPress.WP.EnqueuedResourceParameters.MissingVersion + include-experimental: true + repo-token: '' + + - name: Plugin Check Summary + if: always() + env: + RESULTS_FILE: ${{ runner.temp }}/plugin-check-results.txt + run: | + echo "## WordPress Plugin Check Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ ! -s "$RESULTS_FILE" ]; then + echo "No results file found or file is empty." >> $GITHUB_STEP_SUMMARY + echo "Check the action logs for details." >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + PARSED=$(RESULTS_FILE="$RESULTS_FILE" python3 << 'PYEOF' + import json, os, re + + results_path = os.environ["RESULTS_FILE"] + + high_risk_codes = [ + "plugin_updater", "code_obfuscation", "no_unfiltered_uploads", + "trademarked_term", "trademarks" + ] + high_risk_messages = [ + r"Plugin Updater detected", r"Missing.*License.*Plugin Header", + r"restricted term", r"Unescaped parameter.*\$wpdb", + r"Use placeholders and.*\$wpdb->prepare" + ] + medium_risk_codes = [ + "missing_direct_file_access_protection", "trunk_stable_tag", + "mismatched_plugin_name", "application_detected" + ] + medium_risk_messages = [ + r"Missing.*\$domain.*parameter", r"has been deprecated", + r"wp_get_sites", r"cURL functions is highly discouraged" + ] + + high, medium, other = [], [], [] + + try: + with open(results_path, "r") as f: + content = f.read().strip() + + all_issues = [] + try: + data = json.loads(content) + if isinstance(data, list): + all_issues = data + elif isinstance(data, dict): + for fp, issues in data.items(): + if isinstance(issues, list): + for issue in issues: + issue['_file'] = fp + all_issues.append(issue) + except json.JSONDecodeError: + for line in content.split('\n'): + line = line.strip() + if not line: + continue + try: + parsed = json.loads(line) + if isinstance(parsed, list): + all_issues.extend(parsed) + elif isinstance(parsed, dict): + all_issues.append(parsed) + except json.JSONDecodeError: + continue + + for issue in all_issues: + code = issue.get('code', '') + msg = issue.get('message', '') + itype = issue.get('type', 'ERROR') + line_num = issue.get('line', 0) + file_path = issue.get('_file', '') + + prefix = "❌" if itype == "ERROR" else "⚠️" + location = "" + if file_path: + location = f" ({file_path}" + if line_num and line_num > 0: + location += f", line {line_num}" + location += ")" + elif line_num and line_num > 0: + location = f" (line {line_num})" + + readable = f"{prefix} {msg}{location}" + + is_high = code in high_risk_codes + if not is_high: + for p in high_risk_messages: + if re.search(p, msg, re.IGNORECASE): + is_high = True + break + + is_medium = code in medium_risk_codes + if not is_medium and not is_high: + for p in medium_risk_messages: + if re.search(p, msg, re.IGNORECASE): + is_medium = True + break + + if is_high: + high.append(readable) + elif is_medium: + medium.append(readable) + else: + other.append(readable) + + def dedup(lst): + seen = set() + result = [] + for item in lst: + if item not in seen: + seen.add(item) + result.append(item) + return result + + high, medium, other = dedup(high), dedup(medium), dedup(other) + + print("---HIGH---") + for i in high: print(i) + print("---MEDIUM---") + for i in medium: print(i) + print("---OTHER---") + for i in other: print(i) + print("---COUNTS---") + print(f"{len(high)}|{len(medium)}|{len(other)}") + + except Exception as e: + print(f"Parse error: {e}", file=__import__('sys').stderr) + print("---HIGH---\n---MEDIUM---\n---OTHER---\n---COUNTS---\n0|0|0") + PYEOF + ) + + HIGH_SECTION=$(echo "$PARSED" | sed -n '/^---HIGH---$/,/^---MEDIUM---$/p' | sed '1d;$d') + MEDIUM_SECTION=$(echo "$PARSED" | sed -n '/^---MEDIUM---$/,/^---OTHER---$/p' | sed '1d;$d') + OTHER_SECTION=$(echo "$PARSED" | sed -n '/^---OTHER---$/,/^---COUNTS---$/p' | sed '1d;$d') + COUNTS=$(echo "$PARSED" | tail -1) + OTHER_COUNT=$(echo "$COUNTS" | cut -d'|' -f3) + + echo "### 🚨 HIGH RISK — Can cause plugin closure or suspension" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ -n "$HIGH_SECTION" ]; then + echo "$HIGH_SECTION" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No high-risk issues found." >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + + echo "### ⚠️ MEDIUM RISK — Commonly flagged in wordpress.org reviews" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ -n "$MEDIUM_SECTION" ]; then + echo "$MEDIUM_SECTION" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No medium-risk issues found." >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + + echo "
" >> $GITHUB_STEP_SUMMARY + echo "📋 Other issues ($OTHER_COUNT) — click to expand" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ -n "$OTHER_SECTION" ]; then + echo "$OTHER_SECTION" >> $GITHUB_STEP_SUMMARY + else + echo "No other issues." >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY diff --git a/CHANGELOG.md b/CHANGELOG.md index a1afdfb..1890455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,60 @@ +##### [Version 0.13.21](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.20...v0.13.21) (2026-02-03) + +- Enhanced security + +##### [Version 0.13.20](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.19...v0.13.20) (2025-12-15) + +- Fixed compatibility with PHP 8.1+ versions +- Updated dependencies + +##### [Version 0.13.19](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.18...v0.13.19) (2025-09-05) + +- Updated dependencies + +##### [Version 0.13.18](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.17...v0.13.18) (2025-05-23) + +- Updated dependencies + +##### [Version 0.13.17](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.16...v0.13.17) (2025-04-17) + +- Updated dependencies + +##### [Version 0.13.16](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.15...v0.13.16) (2024-11-07) + +- Updated dependencies + +##### [Version 0.13.15](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.14...v0.13.15) (2024-07-10) + +- Removed recommendations of unsupported plugins +- Fixed conditions for theme recommendation + +##### [Version 0.13.14](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.13...v0.13.14) (2024-05-14) + +- Enhanced security + +##### [Version 0.13.13](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.12...v0.13.13) (2024-04-18) + +### Improvements +​- **Updated internal dependencies:​​** Enhanced performance and security. + +##### [Version 0.13.12](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.11...v0.13.12) (2024-04-01) + +### Improvements +- **Updated internal dependencies** + +##### [Version 0.13.11](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.10...v0.13.11) (2024-03-29) + +### Fixes +- Updated internal dependencies +- Enhanced security + +##### [Version 0.13.10](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.9...v0.13.10) (2024-03-26) + +### Improvements +- Updated internal dependencies +- Improved readme to link to the public source files +- Filter promotions + ##### [Version 0.13.9](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.8...v0.13.9) (2024-02-23) ### Fixes diff --git a/includes/front.php b/includes/front.php index cb42e40..2ae6c1e 100644 --- a/includes/front.php +++ b/includes/front.php @@ -51,6 +51,19 @@ final class Menu_Icons_Front_End { */ protected static $hidden_label_class = 'visuallyhidden'; + /** + * Align-self map for vertical-align values. + * + * @access private + * @var array + */ + private static $align_self_map = array( + 'top' => 'flex-start', + 'middle' => 'center', + 'bottom' => 'flex-end', + 'baseline' => 'baseline', + ); + /** * Add hooks for front-end functionalities @@ -339,6 +352,18 @@ public static function get_icon_style( $meta, $keys, $as_attribute = true ) { $rule = self::$default_style[ $key ]; + // Special handling for vertical-align because it affects the layout of flex containers. + if ( 'vertical_align' === $key ) { + if ( ! isset( $meta[ $key ] ) || $meta[ $key ] === $rule['value'] ) { + continue; + } + + $stored = $meta[ $key ]; + $style_a[ $rule['property'] ] = $stored; + $style_a['align-self'] = isset( self::$align_self_map[ $stored ] ) ? self::$align_self_map[ $stored ] : 'center'; + continue; + } + if ( ! isset( $meta[ $key ] ) || $meta[ $key ] === $rule['value'] ) { continue; } @@ -355,13 +380,13 @@ public static function get_icon_style( $meta, $keys, $as_attribute = true ) { return $style_s; } - foreach ( $style_a as $key => $value ) { - $style_s .= "{$key}:{$value};"; + foreach ( $style_a as $prop => $value ) { + $style_s .= "{$prop}:{$value};"; } $style_s = esc_attr( $style_s ); - if ( $as_attribute ) { + if ( $as_attribute ) { $style_s = sprintf( ' style="%s"', $style_s ); } @@ -483,10 +508,10 @@ public static function get_svg_icon( $meta ) { } } if ( ! empty( $width ) ) { - $width = sprintf( ' width="%d"', $width ); + $width = sprintf( ' width="%d"', esc_attr( $width ) ); } if ( ! empty( $height ) ) { - $height = sprintf( ' height="%d"', $height ); + $height = sprintf( ' height="%d"', esc_attr( $height ) ); } $image_alt = get_post_meta( $meta['icon'], '_wp_attachment_image_alt', true ); $image_alt = $image_alt ? wp_strip_all_tags( $image_alt ) : ''; @@ -495,9 +520,9 @@ public static function get_svg_icon( $meta ) { esc_url( wp_get_attachment_url( $meta['icon'] ) ), esc_attr( $classes ), esc_attr( $image_alt ), - esc_attr( $width ), - esc_attr( $height ), - esc_attr( $style ) + $width, + $height, + $style ); } diff --git a/includes/meta.php b/includes/meta.php index fd8563d..51c8d0f 100644 --- a/includes/meta.php +++ b/includes/meta.php @@ -103,6 +103,14 @@ public static function get( $id, $defaults = array() ) { $value['position'] = $defaults['position']; } + // Backward-compatibility: values removed in favour of align-self support. + $supported_vertical_align = array( 'top', 'middle', 'bottom', 'baseline' ); + if ( isset( $value['vertical_align'] ) && + ! in_array( $value['vertical_align'], $supported_vertical_align, true ) + ) { + $value['vertical_align'] = 'middle'; + } + if ( isset( $value['size'] ) && ! isset( $value['font_size'] ) ) { $value['font_size'] = $value['size']; unset( $value['size'] ); diff --git a/includes/settings.php b/includes/settings.php index 666eb57..c7f88f4 100644 --- a/includes/settings.php +++ b/includes/settings.php @@ -535,18 +535,10 @@ public static function get_settings_fields( array $values = array() ) { 'label' => __( 'Vertical Align', 'menu-icons' ), 'default' => 'middle', 'choices' => array( - array( - 'value' => 'super', - 'label' => __( 'Super', 'menu-icons' ), - ), array( 'value' => 'top', 'label' => __( 'Top', 'menu-icons' ), ), - array( - 'value' => 'text-top', - 'label' => __( 'Text Top', 'menu-icons' ), - ), array( 'value' => 'middle', 'label' => __( 'Middle', 'menu-icons' ), @@ -555,18 +547,10 @@ public static function get_settings_fields( array $values = array() ) { 'value' => 'baseline', 'label' => __( 'Baseline', 'menu-icons' ), ), - array( - 'value' => 'text-bottom', - 'label' => __( 'Text Bottom', 'menu-icons' ), - ), array( 'value' => 'bottom', 'label' => __( 'Bottom', 'menu-icons' ), ), - array( - 'value' => 'sub', - 'label' => __( 'Sub', 'menu-icons' ), - ), ), ), 'font_size' => array( diff --git a/menu-icons.php b/menu-icons.php index 5d23929..a0b02dd 100644 --- a/menu-icons.php +++ b/menu-icons.php @@ -11,7 +11,7 @@ * Plugin name: Menu Icons * Plugin URI: https://github.com/Codeinwp/wp-menu-icons * Description: Spice up your navigation menus with pretty icons, easily. - * Version: 0.13.9 + * Version: 0.13.21 * Author: ThemeIsle * Author URI: https://themeisle.com * License: GPLv2 @@ -29,7 +29,7 @@ final class Menu_Icons { const DISMISS_NOTICE = 'menu-icons-dismiss-notice'; - const VERSION = '0.13.9'; + const VERSION = '0.13.21'; /** * Holds plugin data diff --git a/package.json b/package.json index 8031c12..c1b1286 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "menu-icons", "title": "Menu Icons", "description": "Spice up your navigation menus with pretty icons, easily.", - "version": "0.13.9", + "version": "0.13.21", "homepage": "http://wordpress.org/plugins/menu-icons/", "license": "GPL-2.0", "author": { diff --git a/readme.txt b/readme.txt index f163704..dd7a5bb 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: codeinwp, themeisle Tags: menu, nav-menu, icons, navigation Requires at least: 4.7 -Tested up to: 6.4 +Tested up to: 6.9 Stable tag: trunk License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -220,8 +220,106 @@ add_filter( 'menu_icons_menu_settings', 'my_menu_icons_menu_settings', 10, 2 ); = I can't select a custom image size from the *Image Size* dropdown = Read [this blog post](http://kucrut.org/add-custom-image-sizes-right-way/). += How to report a security issue? = + +Plugin security is a core priority for us. If you identify a potential vulnerability, we ask that you disclose it responsibly. +Please follow the reporting protocols outlined on our [Security Page](https://themeisle.com/security/). + == Changelog == +##### [Version 0.13.21](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.20...v0.13.21) (2026-02-03) + +- Enhanced security + + + + +##### [Version 0.13.20](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.19...v0.13.20) (2025-12-15) + +- Fixed compatibility with PHP 8.1+ versions +- Updated dependencies + + + + +##### [Version 0.13.19](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.18...v0.13.19) (2025-09-05) + +- Updated dependencies + + + + +##### [Version 0.13.18](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.17...v0.13.18) (2025-05-23) + +- Updated dependencies + + + + +##### [Version 0.13.17](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.16...v0.13.17) (2025-04-17) + +- Updated dependencies + + + + +##### [Version 0.13.16](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.15...v0.13.16) (2024-11-07) + +- Updated dependencies + + + + +##### [Version 0.13.15](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.14...v0.13.15) (2024-07-10) + +- Removed recommendations of unsupported plugins +- Fixed conditions for theme recommendation + + + + +##### [Version 0.13.14](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.13...v0.13.14) (2024-05-14) + +- Enhanced security + + + + +##### [Version 0.13.13](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.12...v0.13.13) (2024-04-18) + +### Improvements +​- **Updated internal dependencies:​​** Enhanced performance and security. + + + + +##### [Version 0.13.12](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.11...v0.13.12) (2024-04-01) + +### Improvements +- **Updated internal dependencies** + + + + +##### [Version 0.13.11](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.10...v0.13.11) (2024-03-29) + +### Fixes +- Updated internal dependencies +- Enhanced security + + + + +##### [Version 0.13.10](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.9...v0.13.10) (2024-03-26) + +### Improvements +- Updated internal dependencies +- Improved readme to link to the public source files +- Filter promotions + + + + ##### [Version 0.13.9](https://github.com/codeinwp/wp-menu-icons/compare/v0.13.8...v0.13.9) (2024-02-23) ### Fixes