Table of Contents
Negative Space and Dead Code
Code that exists, is fully documented, and is never reached. This page is the one place where the reference generator's own limits matter most, so the method is stated before the findings.
Method, and why it is only a candidate list
A symbol is a candidate for dead code when its name appears nowhere in the first-party tree except at its own declaration, measured with comments and string literals removed. This deliberately over-reports, because a text search cannot see every way a symbol can be reached:
- Plugin hooks are called by the admin UI by convention, not by name.
- Some helpers are dispatched dynamically from a name array. This is not hypothetical: `Bootstrap::sendSecurityHeaders()` calls `x_frame_option`, `x_content_type_options`, `x_xss_protection`, `strict_transport_security` and the rest by iterating an array of strings. An earlier pass that only looked for `name(` reported all of those as dead. They are not.
- A declaration guarded by `if (!function_exists('name'))` still counts as a declaration, and the guard line itself looks like a mention. Neither form proves a call.
Third-party code is excluded: `lib/vendor/`, `lib/HTMLPurifier/`, the flat `lib/core/HTMLPurifier*` shims, `node_modules/` and `vendor-bin/`.
1. The one certain case
`Scriptlog\Core\Psr4AutoloadTest` — `lib/core/Psr4AutoloadTest.php`, 22 lines, 2 methods, zero references.
A test class living in `lib/core/` rather than `tests/`. PHPUnit discovers tests by scanning configured directories, so if `lib/core` is not in the test suite's path this never runs. It is the single highest-confidence dead-code finding in the tree, and the only unreferenced type in the whole codebase — every other class is reachable.
2. Admin plugin hooks — almost certainly not dead
| Function | File |
| — | — |
| `hello_world_display()` | `admin/plugins/hello-world/functions.php` |
| `hello_world_get_info()` | `admin/plugins/hello-world/functions.php` |
These are the documented hook pair for a bundled example plugin. They are called by the plugin loader through a naming convention, so a text search cannot see the call. Listed for completeness, not as a defect.
3. Utility functions — 72 candidates, needs per-item review
All 72 live in `lib/utility/*.php`, the unnamespaced procedural layer. They are grouped here by what they suggest about the codebase's history.
A Medoo compatibility shim (6). `medoo_join`, `medoo_get_join`, `medoo_fetch_callback`, `medoo_update`, `medoo_replace`, and friends. These exist to support both the mysqli and PDO drivers. The `FrontHelper` docblock records that a legacy path “was mysqli-only and broke on PDO”, so this shim is the visible scar of that migration. A cluster like this is a strong candidate for removal *once* the supported driver set is decided — but not before.
Syntax highlighting internals (4). `hl_commentCdata`, `hl_entity`, `hl_tag`, `transform_html`. `Scriptlog\Core\SyntaxHighlight` is the class that would use them. That class is reachable — it is registered in `lib/autoload-aliases.php` — so the highlighting path as a whole is live; these four helpers may simply be its internals reached by a mechanism this pass does not model, or leftovers from before highlighting moved into the class.
Database helpers (6). `db_begin_transaction`, `db_commit`, `db_insert_id`, `db_num_rows`, `check_table`, `db_close`. These predate the `Database` wrapper in `lib/core/`. Their existence alongside that wrapper is exactly the kind of duplication worth resolving deliberately.
Environment probing (7). `checking_connection_with_fopen`, `is_online`, `check_weblink`, `detect_origin`, `detect_proxy_by_headers`, `find_webserver_name`, `get_webserver_config_filename`. Deployment diagnostics that may be reachable only from an admin diagnostic screen.
Randomness (5). `make_seed`, `ircmaxell_generator_numbers`, `ircmaxell_random_compat`, `random_password`, `str_rand`. The `ircmaxell_*` names point at a vendored algorithm absorbed into `lib/utility/`.
HTTP and HTMX (5). `get_request_header`, `set_cors_headers`, `handle_preflight_request`, `htmx_target`, `htmx_trigger`. Note the consistency: the class page for `HTMX` renders fine because the *class* is reachable, but these two procedural helpers are not.
UI and plugin plumbing (7). `admin_t`, `set_plugin_navigation`, `invoke_hero_image`, `get_download_links`, `disable_plugin`, `validate_plugin_zip`, `allow_admin_ajax`. Plugin lifecycle functions, which may be convention-invoked like the admin hooks above.
Misc (32). `add_scheme`, `write_config`, `rar_file_scanner`, `is_cookies`, `set_cookies_path`, `current_http_version`, `current_load_page`, `grab_month`, `rm_from_folder`, `get_browser_name`, `get_operating_system`, `get_directory_size_spl`, `request_ip_address`, `image_encoder`, `str_word_count_utf8`, `parse_post_id`, `parse_query`, `form_filled_validation`, `forbidden_direct_access`, `get_cookie_consent_from_db`, `process_consent_ajax`, `relative_url`, `safe_filter_html`, `locale_dropdown`, `tag_slug`, `truncate_tags`, `strip_tags_content`, `timezone_picker`, `markdown_html_out`, `validate_time_login`, `scriptlog_shutdown_fatal`.
4. Theme functions — 8 confirmed dead in the active theme
| Function | Declared in |
| — | — |
| `get_slideshow()` | `public/themes/blog/functions-media.php` |
| `initialize_comment()` | `public/themes/blog/functions-post.php` |
| `retrieves_topic_prepared()` | `public/themes/blog/functions-post.php` |
| `retrieve_tags()` | `public/themes/blog/functions-post.php` |
| `searching_by_tag()` | `public/themes/blog/functions-post.php` |
| `language_switcher()` | `public/themes/blog/functions-i18n.php` |
| `get_all_language_names()` | `public/themes/blog/functions-i18n.php` |
| `reset_i18n_cache()` | `public/themes/blog/functions-i18n.php` |
This group was checked by hand and is confirmed dead, not merely suspicious. The verification:
- `blog` is the only theme in `public/themes/`, so there is no second theme that might call them.
- A recursive search of all 29 PHP files in the theme finds each name in its own declaring file and nowhere else.
- A search across every file type — not just PHP, so also the theme's seven `lang/*.json` files, `theme.ini` and its CSS — finds the same result.
- Each declaration is wrapped in `if (!function_exists('name'))`, so the missing call sites produce no error. The theme renders identically with all eight deleted.
That last point is why they survived: the guard suppresses the error that would otherwise have exposed the missing call. `get_slideshow()` is a clean example of the trap — its own docblock reads `get_slideshow() - Get posts with media for slideshow`, which a comment-unaware search happily counts as a call site.
5. What is *not* dead
For balance, the things a reader might expect to be dead that are not:
- `Scriptlog\Core\SyntaxHighlight` and `Scriptlog\Core\ModelException` look unreferenced in application code but are both registered in `lib/autoload-aliases.php` and `lib/autoload-aliases-map.php` for backward compatibility. An earlier pass that omitted the flat `lib/*.php` files from its scope wrongly flagged both.
- The five security-header functions are dynamically dispatched from `Bootstrap::sendSecurityHeaders()`.
- `Scriptlog\Core\FrontHelper` is deprecated but very much alive.
