=== NonStop Link Reporter ===
Contributors: nonstopdev
Tags: links, broken links, link checker, security, export
Requires at least: 6.5
Tested up to: 6.8
Requires PHP: 8.1
Stable tag: 0.1.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Search for all links, good, bad, and ugly that are on your WordPress site.

== Description ==

NonStop Link Reporter finds every URL on your WordPress site and tells you exactly which pages each one lives on. Export the whole thing to CSV or JSON, and — if you want them — switch on two separate modules that find broken links and malicious links.

**The link inventory (always on)**

* Scans posts, pages, every custom post type, term descriptions, comments, widgets, navigation menus, user profiles and theme settings.
* Records every URL along with the page it was found on, where inside that page, the HTML element and attribute, the link text, and the `rel` and `target` values.
* Finds links that are not anchors too: `img`, `iframe`, `script`, `link`, `form`, `video`, `object` and more.
* Flags links that are styled to be invisible to visitors — the signature of injected SEO spam.
* Makes no outbound requests at all.

**Link Health (separate option)**

* Checks every link, including third-party sites, and records the HTTP status.
* Captures the full redirect chain hop by hop, so a link that 404s and bounces through two redirects before landing somewhere unexpected is visible at a glance.
* Flags redirects that leave the original domain.
* Polite by default: identifies itself honestly and throttles requests per host.

**Link Security (separate option)**

* Scores every link against more than twenty malicious-link patterns, each with a plain-English explanation of why it was flagged.
* Catches `javascript:` and `data:` URIs, bare IP hosts, punycode look-alike domains, domains one character off your own, credentials embedded in URLs, non-standard ports, URL shorteners, high-abuse TLDs, encoded query payloads, open-redirect parameters, spam keywords, cloaked link text, hidden links, off-site scripts and frames, and links hidden in theme settings.
* Optional Google Safe Browsing lookup using your own API key — off by default.
* Runs entirely on your own server unless you turn Safe Browsing on.

**Export**

* CSV with one row per link-on-a-page — the report most people are after.
* CSV with one row per unique URL and a summary of where it appears.
* JSON for scripts and other tools.
* Streamed in chunks, so exporting a very large site does not exhaust memory.

**Also included**

* Scheduled scans (daily, weekly or monthly) with an optional email summary.
* Dashboard widget with the headline numbers.
* WP-CLI commands: `wp nslr scan`, `wp nslr check`, `wp nslr analyze`, `wp nslr status`, `wp nslr export`, `wp nslr reset`.
* Documented action and filter hooks throughout.

== Installation ==

1. Upload the `nonstop-link-reporter` folder to `/wp-content/plugins/`, or install the zip through Plugins → Add New → Upload Plugin.
2. Activate the plugin.
3. Go to **Link Reporter → Overview** and run the link inventory.
4. Optionally go to **Link Reporter → Settings** and switch on Link Health and/or Link Security, then run those from the Overview screen.

On a large site, running the first scan through WP-CLI (`wp nslr scan`) is faster and avoids browser timeouts.

== Frequently Asked Questions ==

= Does this slow my site down? =

No. Nothing is loaded on the front end, and admin assets load only on the plugin's own screens. Scans run in small batches so a single request never runs long.

= Does it contact other websites? =

Only if you enable the Link Health module and run a check, which is the whole point of that module. The link inventory and the security heuristics work entirely on your own server. Google Safe Browsing is a separate opt-in on top of the security module and needs your own API key.

= Will it find links a hacker injected? =

That is the main thing it was built for. It scans places content-only tools miss — widget option data, theme mods, navigation menus, comment author URLs and user bios — and it flags links that are hidden from visitors, links whose text names one domain while pointing at another, `javascript:` and `data:` URIs, and look-alike domains.

= Can I find broken links on other people's sites that I link to? =

Yes. Enable Link Health and leave "Links to third-party sites" checked.

= Where is the data stored? =

In three custom database tables. Link occurrence data runs to tens of thousands of rows on a modest site; storing that in post meta would slow down every query on your site, so it is kept separate.

= What happens when I delete the plugin? =

Nothing is removed unless you ticked "Delete all report data and settings when the plugin is deleted" on the Settings screen. Deactivating never removes data.

== Screenshots ==

1. Overview screen with headline counts and the three scan runners.
2. All Links, showing each URL alongside the pages it appears on.
3. Link detail, listing every place a single URL was found.
4. Suspicious Links, with a plain-English explanation for each flag.
5. Export screen.

== Changelog ==

= 0.1.2 =
* Ignoring a link now actually hides it. All Links, Broken Links and Suspicious Links gained "Needs review", "Ignored" and "All" views with counts, and open on "Needs review". Previously the Ignore action set a flag that nothing acted on.
* New "Ignore everything on this host" row action. On a site with a few thousand links, most belong to a handful of hosts, so trusting one clears them in a single click.
* Host rules are permanent and apply at display time, so links found on a trusted host by a later scan stay hidden automatically. A bare domain covers its subdomains.
* New "Hide these from review" setting for managing those rules by hand. Accepts bare domains, paths and * wildcards.
* Ignored links are now skipped by the health check and the security analysis, so trusting a host also cuts the number of outbound requests.
* Exports still contain everything by default, so the file remains a complete record of the site. A new checkbox leaves ignored links out when you want a shorter working list.
* Clarified the existing "Never record URLs matching" setting, which excludes URLs from the scan entirely, versus the new hide-from-review rules, which keep them in the report.

= 0.1.1 =
* Every result now links straight to the screen that edits it. Item titles in the report are clickable through to the edit screen, not just the front end.
* Comments and WooCommerce product reviews now show the product or post they belong to, with direct "Edit product" and "View" links. Previously you could see a link was in a review but had no way to reach the product.
* Widgets now show the real widget area name, for example "Widget area: Footer Column 2", instead of a raw sidebar slug, plus a link that opens that exact area in the Customizer. Widgets that are inactive or orphaned say so.
* Menu items now name the menu they belong to and the theme location it is displayed in, and link to that menu's edit screen.
* Theme mods and options now say whether they live in the Customizer or in Settings, and link there.
* Item types are now shown using their real labels, so a WooCommerce product reads "Product" rather than "Content".
* Occurrence exports gained an "Edit link (admin)" column, so a spreadsheet row is directly actionable.
* Database schema updated to version 2 to store the widget handle needed for the above. Existing data is preserved; re-run the link scan once to pinpoint widget links recorded by an earlier version. The plugin will prompt you.

= 0.1.0 =
* Initial release.
* Link inventory across posts, terms, comments, widgets, menus, users and theme options.
* Per-occurrence recording of source, location, element, attribute, link text, rel, target and hidden state.
* Link Health module: HTTP status, hop-by-hop redirect chains, off-domain redirect detection.
* Link Security module: 20+ weighted heuristics with explanations, optional Google Safe Browsing.
* CSV and JSON export, streamed.
* Scheduled scans with email summary, dashboard widget, WP-CLI commands.

== Upgrade Notice ==

= 0.1.2 =
Ignored links are now genuinely hidden, and you can trust a whole host in one click. Reports open on "Needs review" instead of everything.

= 0.1.1 =
Adds direct "go to it" links throughout the report, including the product a review sits on and the widget area a widget lives in. Re-run the link scan once after upgrading.

= 0.1.0 =
First release.
