| 开发者 | swabic |
|---|---|
| 更新时间 | 2026年7月22日 20:32 |
| PHP版本: | 8.3 及以上 |
| WordPress版本: | 6.9 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
$wpdb->prepare() — OWASP SQL injection preventionnettoprofit folder to /wp-content/plugins/.Yes. It requires no account, no license key, and no API credentials. Install, click "Run Scan", and see your health score immediately.
No. NettoProfit is purpose-built for WooCommerce stores and requires WooCommerce 6.7+.
Yes. HPOS (Custom Order Tables) is required. It is enabled by default in WooCommerce 8.2 and later. The plugin will display a notice if HPOS is disabled.
The Pixel Health Checker fetches your own store's public pages (via wp_remote_get) — no data leaves your server. The AI Advisor (PRO+AI) sends aggregated P&L numbers to Anthropic's Claude API — never customer PII.
Google Ads (including Performance Max campaigns), Meta Ads (including Advantage+ Shopping), TikTok Ads (including Smart+ campaigns), and manual UTM-tracked sources. Microsoft/Bing Ads available as a manual provider via UTM parameters.
ttq.page() base-snippet call — conventional TikTok installs were previously reported as missing PageView on every page.fbq('init', id, {...}) third argument or fbq('set', 'userData', ...)) instead of being credited whenever the pixel exists.gtag('consent', 'default', ...) call itself, so unrelated scripts can no longer produce a false "all parameters present".sgtm. anywhere in the HTML; Meta CAPI / TikTok Events API status wording now says "credentials configured" (a static scan cannot verify a live connection).GET /pixel-check/history returns the persisted history instead of rebuilding the current snapshot.vendor/, or composer.json would ship.Service provider / Terms of service / Privacy policy line to the top of the bullet list so the canonical Terms/Privacy URL is the first URL the scanner encounters in each section. NettoProfit's own Terms/Privacy now resolve to https://nettoprofit.com/terms/ and https://nettoprofit.com/privacy-policy/.src/Database/Repository.php entirely. The class had zero call sites anywhere in the plugin (no new Repository, no Repository::, no static usage in tests or anywhere else); WPCS 3.x sniffer in PCP fires WordPress.DB.PreparedSQL.NotPrepared on $wpdb->get_*($variable) regardless of how the variable was prepared because it does not trace assignments through the $this->wpdb property pattern. Deleting the dead class is the cleanest fix.NettoProfit\Database\Repository entries from vendor/composer/autoload_classmap.php and vendor/composer/autoload_static.php.Database\Repository so every $wpdb->prepare() result is assigned to a $sql variable before being passed to $wpdb->get_row/get_var/get_results. PCP runs PHPCS with --ignore-annotations so file-level phpcs:disable was being bypassed; this is the structural pattern the sniffer recognises.Repository::scalar() and Repository::rawQuery() helpers (no callers across the codebase) — eliminates two UnescapedDBParameter warnings on raw $wpdb->get_var($sql) / $wpdb->query($preparedSql) calls.$_FILES['csv_file']['tmp_name'] read in ProductCostPage::ajaxImportCsv with sanitize_text_field(wp_unslash(...)) so the sniffer no longer flags it as unsanitized input (the subsequent is_uploaded_file() + realpath() guards already made it safe in practice).== Upgrade Notice == entries to fit the 300-character wp.org limit.Contributors: swabic so the listed contributor matches the plugin owner's WordPress.org account.set_time_limit(300) from src/API/RestProEndpoints.php::syncOrders — host PHP limits must not be forced globally.SettingsPage::saveLicense() (in addition to the parent handleSave nonce) and ProductSalesPage::getDateRange() (capability check + Y-m-d format validation for from/to).$_FILES['csv_file'] in ProductCostPage::ajaxImportCsv (per-field unslash/sanitize + realpath() for tmp_name) and of $_POST['new_rule'] in SettingsPage::saveAlerts (every array key unslashed/sanitized individually before the whitelist check).$sortIcon($col['key']) output in templates/admin/product-sales.php via wp_kses() with an explicit <span class> allowlist.np_ / NP_ / pp_ / pp- short prefix (41 elements) to nettop_ / NETTOP_ / nettop- so all reserved identifiers are over 4 characters. Covers PHP functions and constants, WP-cron hooks (nettop_every_6h, nettop_license_refresh, nettop_ai_cleanup, nettop_weekly_pixel_scan), AJAX actions (nettop_sync_license, nettop_save_product_cost, nettop_import_csv, nettop_export_csv, nettop_inline_edit), transients (nettop_license_status, nettop_grace_mode, nettop_ai_*, nettop_pixel_scan_result, nettop_alert_notices), DB tables ({prefix}nettop_ad_spend, {prefix}nettop_order_profits, {prefix}nettop_expenses, etc.), post/order meta (_nettop_cost), JS/CSS asset handles (nettop-charts, nettop-admin, nettop-ai-advisor, nettop-hierarchy-table, nettop-pixel-checker, nettop-utm-capture), and wp_localize_script variable names (nettopDashboardSync, nettopDashboardCharts, nettopAdmin, nettopAI, nettopHierarchy, nettopPixelCheckerSync, nettopPixelCheckerLegacy, etc.).HierarchyAnalyzer::fetchCampaigns/fetchAdsets/fetchAds/fetchFlatEntities/fetchTrendMap/fetchSparklineMap and RestProEndpoints::getTimeSeries to use %i identifier placeholders for $table/$idCol (WP 6.2+) and split the optional $provider clause into two fully-static prepared queries — no more variables interpolated into wpdb::prepare() first argument.Database\Repository::upsert to use the native $wpdb->replace() API, and refactored findBy/all/paginate so every SQL identifier flows through %i and every value flows through %s/%f/%d placeholders; dropped the bespoke sanitizeColumn() helper that the previous build leaned on.uninstall.php cleanup queries (DROP TABLE, transient/option/meta DELETE) all routed through $wpdb->prepare() with %i table placeholders and %s LIKE patterns.build-wporg.ps1 for the new NETTOP_* constants and nettop_* function names so the injected NETTOP_WPORG_BUILD marker and the nettop_pro_gate/nettop_ai_gate no-op stubs land on the renamed symbols.phpcs:disable/phpcs:enable blocks in uninstall.php into a single block from the foreach drop-tables loop down to the last cleanup query, and reverted the cleanup block to the parent rule WordPress.DB.DirectDatabaseQuery. Subrule-level disables (...DirectQuery, ...NoCaching) are silently ignored by the current Plugin Check release; parent-rule disables propagate to children. Clears the final 10 warnings.phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,...NoCaching per-line annotations in uninstall.php with a phpcs:disable/phpcs:enable block around the full cleanup section. Single-line phpcs:ignore does not propagate to multi-line $wpdb->query() calls in the current Plugin Check release; block-form does. (Subrule sniff names did not actually take effect — see 1.13.16.)phpcs:ignore WordPress.DB.DirectDatabaseQuery annotations in uninstall.php to explicit DirectQuery,NoCaching subrules — Plugin Check propagates parent-rule disables but not parent-rule ignores, so the per-line suppressions were not catching the child sniffs.phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound directive together with the NETTOP_WPORG_BUILD constant so the injected define() lands inside the suppression scope.// phpcs:enable directives in uninstall.php, templates/admin/ad-detail.php, and src/Database/Repository.php to enumerate the rules being re-enabled. Bare phpcs:enable reactivates every rule, including file-level PrefixAllGlobals.NonPrefixedVariableFound disables, so the variables in scope after the directive were getting flagged again.vendor/dompdf, vendor/phenx, vendor/sabberworm, and vendor/masterminds (PDF export gracefully degrades when the library is absent)..po translation files — only the canonical nettoprofit.pot is shipped (translations are managed via translate.wordpress.org).uninstall.php now also clears np_* and nettoprofit_* transients (single + multisite) and np_* cron events.$_GET, $_POST, and $_FILES value is now unslashed and sanitized before use.phpcs:disable rationale on real-time analytics queries (table identifiers come from $wpdb->prefix; user values are placeholder-bound; caching would yield stale data).load_plugin_textdomain() call (WP 4.6+ auto-loads translations from the languages/ folder).Tags: to the WordPress.org-permitted maximum of five.error_log() sites (gated by WP_DEBUG) and silenced sniff false-positives with auditable inline comments..wordpress-org/, screenshot-*.png, banner-*.png, icon-*.png so directory assets are never shipped inside the plugin ZIP.